RPN Interpreter
(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>