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>