Assembly Programming Language
(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2008 Xaviar Czervik
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 compiles an assembly-like programming language, and runs it. Unlike most assembly code, which is fast, this is very, very, slow. You can't do anything you couldn't do in a tenth the number of lines of LSL, so there are no advantages to using it (besides having fun).
<lsl> list memory; integer lastProgLine;
string reg0; string type0; string reg1; string type1; string reg2; string type2;
integer lstn;
integer i;
err(integer li, string s) {
llOwnerSay("Error on line " + (string)li + ": " + s);
llResetScript();
}
save(string val, integer loc) {
integer add = lastProgLine + (integer)loc;
if (add < llGetListLength(memory)) {
memory = llListReplaceList(memory, [val], add, add);
} else {
integer i = 0;
while (i < add-llGetListLength(memory)) {
memory += "";
i++;
}
memory += val;
}
}
default {
touch_start(integer a) {
llGetNotecardLine("Prog", lastProgLine);
}
changed(integer a) {
if (a & CHANGED_INVENTORY) {
llResetScript();
}
}
dataserver(key qid, string data) {
if (data == EOF) {
state run;
}
memory += data;
llGetNotecardLine("Prog", (lastProgLine += 1));
}
}
state run {
changed(integer a) {
if (a & CHANGED_INVENTORY) {
llResetScript();
}
}
state_entry() {
i = 0;
llSetTimerEvent(.001);
}
timer() {
if (i >= lastProgLine) {
llResetScript();
}
string l = llList2String(memory, i);
string command;
string action;
if (llSubStringIndex(l, " ") != -1) {
list line = [llGetSubString(l, 0, llSubStringIndex(l, " ")-1), llGetSubString(l, llSubStringIndex(l, " ")+1, -1)];
command = llList2String(line, 0);
action = llList2String(line, 1);
} else {
command = l;
}
if (command == "ty0") {
if (!(action == "str" || action == "int" || action == "flo")) {
err(i, "Invalid registry type.");
}
type0 = action;
} else if (command == "ty1") {
if (!(action == "str" || action == "int")) {
err(i, "Invalid registry type.");
}
type1 = action;
} else if (command == "ty2") {
err(i, "Registry two can not be set.");
} else if (command == "st0") {
if (type0 == "") {
err(i, "Registry type has not been defined.");
}
reg0 = action;
} else if (command == "st1") {
if (type1 == "") {
err(i, "Registry type has not been defined.");
}
reg1 = action;
} else if (command == "st2") {
err(i, "Registry two can not be set.");
} else if (command == "jmp") {
i = (integer)action - 1;
} else if (command == "jil") {
if (type0 == "str" || type1 == "str") {
err(i, "Registries may not be of type str to compare.");
}
if ((float)reg0 < (float)reg1)
i = (integer)action - 1;
} else if (command == "jle") {
if (type0 == "str" || type1 == "str") {
err(i, "Registries may not be of type str to compare.");
}
if ((float)reg0 <= (float)reg1)
i = (integer)action - 1;
} else if (command == "jie") {
if (type0 == type1) {
if (reg0 == reg1)
i = (integer)action - 1;
}
} else if (command == "add") {
if (type0 == "str" || type1 == "str") {
type2 = "str";
reg2 = reg0 + reg1;
} else if (type0 == "int" && type1 == "int") {
type2 = "int";
reg2 = (string)((integer)reg0 + (integer)reg1);
} else if (type0 == "flo" && type1 == "flo") {
type2 = "int";
reg2 = (string)((float)reg0 + (float)reg1);
} else if (type0 == "flo" && type1 == "int") {
type2 = "int";
reg2 = (string)((float)reg0 + (integer)reg1);
} else if (type0 == "int" && type1 == "flo") {
type2 = "int";
reg2 = (string)((integer)reg0 + (float)reg1);
} else {
err(i, "Registry type mismatch or invalid.");
}
} else if (command == "sub") {
if (type0 == "int" && type1 == "int") {
type2 = "int";
reg2 = (string)((integer)reg0 - (integer)reg1);
} else {
err(i, "Registry type mismatch or invalid.");
}
} else if (command == "ld0") {
if (type0 == "") {
err(i, "Registry type has not been defined.");
}
reg0 = llList2String(memory, lastProgLine + (integer)action);
} else if (command == "ld1") {
if (type1 == "") {
err(i, "Registry type has not been defined.");
}
reg1 = llList2String(memory, lastProgLine + (integer)action);
} else if (command == "ld2") {
err(i, "Cannot load data into registry two.");
} else if (command == "sv0") {
save(reg0, (integer)action);
} else if (command == "sv1") {
save(reg1, (integer)action);
} else if (command == "sv2") {
save(reg2, (integer)action);
} else if (command == "say") {
llSay(0, reg0);
} else if (command == "inp") {
llSetTimerEvent(0);
lstn = llListen(0, "", "", "");
} else if (command == "rnd") {
if (type0 == "float" || type1 == "float") {
type2 = "flo";
reg2 = (string)(llFrand((float)reg1-(float)reg0)+(float)reg0);
} else if (type1 == "int" && type0 == "int") {
type2 = "int";
reg2 = (string)((integer)llFrand((float)reg1-(float)reg0+1)+(integer)reg0);
}
} else if (command == "rem") {
} else {
err(i, "Invalid command '" + command + "'.");
}
//llOwnerSay("Line " + (string)i + ": " + l);
//llOwnerSay("Command: '" + command + "'.");
//llOwnerSay(type0 + " " + reg0);
//llOwnerSay(type1 + " " + reg1);
//llOwnerSay(type2 + " " + reg2);
//llOwnerSay(llList2CSV(llList2List(memory, lastProgLine, -1)));
i++;
}
listen(integer i, string n, key id, string m) {
llListenRemove(lstn);
type2 = "str";
reg2 = m;
llSetTimerEvent(.0001);
}
} </lsl>