RPN Interpreter

From Second Life Wiki
Jump to navigation Jump to search

(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2013 Subus Tremor

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

This is a reverse polish notation interpreter - it's also called 0-address-machine as it does not need addressable storage locations for it's operation . It interprets rpn expressions. (see the code which operands are supported- feel free to change/extend it) There is no debugging etc. provided.

Create a box, and drop this script in it. Then edit the script and assign a rpn input expression to the input list - or even better :-) add an Input routine to it. Save the script and touch your box to run the code.

<lsl> // Simple RPN calculator as lsl plugin sample for my Real Inworld Computer - by Subus Tremor // made to compare it to the Real Inworld Computers rpn batch domme program notecard

list inlist; // Input as list list stack; // our stack

push(string val) {

   stack = val + stack;

} string pop() {

   string ret = llList2String(stack,0);
   stack = llDeleteSubList(stack,0,0);
   return ret;

} string abop (string a, string b, string func) { // does rout = a op b

   string  rout;
   integer iout;
   float   fout;
   if((~llSubStringIndex(a,"."))||(~llSubStringIndex(b,"."))) { //float
       float fa = (float)a;
       float fb = (float)b;
       integer fia;
       if(func=="+") fout = fa + fb;
       if(func=="-") fout = fa - fb;
       if(func=="*") fout = fa * fb;
       if(func=="/") fout = fa / fb;
       if(func=="sin") fout = llSin(fa);
       if(func=="cos") fout = llCos(fa);
       if(func=="abs") fout = llFabs(fa);
       rout = (string)fout;
       if(func=="round") {iout = llRound(fa); rout = (string)iout;}        
   }
   else { //integer
       integer ia = (integer)a;
       integer ib = (integer)b;
       if(func=="+") iout = ia + ib;
       if(func=="-") iout = ia - ib;
       if(func=="*") iout = ia * ib;
       if(func=="/") iout = ia / ib;
       if(func=="%") iout = ia % ib;
       if(func=="abs") iout = llAbs(ia);
       if(func=="ceil") iout = llCeil((float)a);
       if(func=="floor") iout = llFloor((float)a);
       rout = (string)iout;
   }
   return rout;

}

// two calculation samples - implement your own clever input providing to the calculator list rpntask1 = [ "3", "4", "+", "2", "1", "+", "+", "2", "*", "20", "-"]; // sample 1

               // does: (((3+4)+(2+1))*2)-20

list rpntask2 = [ "3.14", "sin", "0.001593", "/", "1", "-"]; // sample 2

               // does: (sin(3.14)/0.001593)-1
               

default {

   state_entry() { // provide some input to the calculator
       inlist = rpntask2;
   }
   touch_start(integer num_detected) { // start calculation when touched
       state running;
   }  

} state running {

   state_entry() { //RPN calculation :-) do what we have to do while we are active
       integer inpointer=0;    // point to an item in inlist 
       string _out;            // the special variable _out
       string b;               // the second operator variable
       string _last;           // keep the last input token till calculation
       //by intention written with jumps to make it compareable to the rpn domme program - the batch language of my Inworld computers
       @next;
       _out=llList2String(inlist,inpointer);   // take next
       _last=_out;
       inpointer++;
       if(_out=="") jump end;
       if(llSubStringIndex("+-*/%",_out)>=0) jump args2;                 // ifin _out +-*/% args2
       if(llSubStringIndex("sincosroundceilfloor",_out)>=0) jump args1;  // ifin _out sincosroundceilfloor args1
       push(_out);             // push _out
       jump next;
       @args2;
       b=pop();                // pop , var b _out
       @args1;
       _out=pop();             // pop
       _out=abop(_out,b,_last);// abop _out b _last
       llSay(0,_out);          // out
       push(_out);             // push _out
       jump next;
       @end;
       llSay(0,"RPN calculation finished");          // finished
       llResetScript();
   }    

} </lsl>