daily pastebin goal
14%
SHARE
TWEET

Magic interpreter in Javascript

a guest Apr 13th, 2013 89 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //okay, lets do this
  2. //keywords, so I dont forget any
  3. //unsummon, summon, summonhold, conjure, enchant, dispel, bind, bindself, with, empty, print, set, skip
  4.  
  5. //a spirit is something summoned and running, a spell is the scroll, or the recipe
  6. //spirits hold variables, spells don't
  7.  
  8. //THIS ONE WITH ONE INSTRUCTION PER TIME
  9.  
  10.  
  11.  
  12. function parseline(s){
  13.         s = "("+s+")";  //the fuck? is this lisp?
  14.         s = s.replace(/\(/g," ( ").replace(/\)/g," ) ").replace(/ +/g, " ");
  15.         s = s.substring(1,s.length-1);  //remove the border spaces
  16.         var t = s.split(" ");
  17.         return read_from(t);
  18. }
  19.  
  20.         function read_from(tokens) {
  21.                 if (tokens.length == 0) {
  22.                         throw ( "unexpected EOF while reading" );
  23.                 }
  24.                 var token = tokens[0];
  25.                 tokens.shift();
  26.                 if ("(" == token) {
  27.                         var L = [];
  28.                         while (tokens[0] != ")") {
  29.                                 L.push(read_from(tokens));
  30.                         }
  31.                         tokens.shift(); //pop off ")"
  32.                         return L;
  33.                 } else if (")" == token) {
  34.                         throw("unexpected )");
  35.                 } else {
  36.                         return token;
  37.                 }
  38.         }
  39.  
  40. function parsefile(s){
  41.         s = s.replace(/\n+/g,"\n");
  42.         return map(parseline,s.split("\n"));
  43. }
  44.  
  45. function map(func,t){
  46.         var t2 = [];
  47.         for (var x=0;x<t.length;x++) {
  48.                 t2[x] = func(t[x]);
  49.         }
  50.         return t2;
  51. }
  52.  
  53. function conjureempty(){
  54.         return {spells:[]};
  55. }
  56.  
  57. function enchant(form,t){       //of course a syntax check must be done first, right??
  58.         form.spells.push(t);
  59. }
  60.  
  61. function setat(form,n,v){       //a form that isn't summoned is just a list
  62.         form.spells[n]=v;
  63. }
  64.  
  65. /*
  66. function slice(t,start)
  67.         var t2 = []
  68.         for x=start,#t do
  69.                 table.insert(t2,t[x])
  70.         }
  71.         return t2
  72. }*/
  73.  
  74. function slice(t,start) { return t.slice(start);}
  75.  
  76. function copy(t){
  77.         return t.slice(0);
  78. }
  79.  
  80. var spiritlist = [];
  81. var spiritcount = 0;
  82.  
  83. function summon(form,bindings){
  84.         var spirit = {spells:copy(form.spells),bindings:bindings,p:0}  //must be a copy cuz it might be altered at runtime
  85.         spiritlist[spiritcount] = spirit;
  86.         spirit.id = spiritcount;
  87.         spiritcount=spiritcount+1;
  88.         spirit.bindings.self = spirit;  //not a special word, but a common var that can be changed with set! U WOOT!!
  89.         spirit.bindings.selfform = form;
  90.         spirit.bindings.firstloop = true;       //a useful(?) boolean
  91.         return spirit;
  92. }
  93.  
  94. function unsummon(spirit){      //need to remove it from the spirit list, and put a tag on it saying "dead"
  95.         spiritlist[spirit.id] = false;
  96.         spirit.dead=true;
  97.         if (spirit.bindings.summoner) {
  98.                 spirit.bindings.summoner.halt=false;    //this unhalts the summoner
  99.         }
  100. }
  101.  
  102. //function summonhold(form,bindings)
  103. //      var spirit = summon(form,bindings)
  104. //      while not spirit.dead do
  105. //              evalspirit(spirit)
  106. //      }
  107. //      return spirit
  108. //}
  109.  
  110. var mymath2 = {"+":function (a,b) { return a+b; },
  111.           "-":function (a,b){ return a-b; },
  112.           "*":function (a,b){ return a*b; },
  113.           "/":function (a,b){ return a/b; },
  114.           "%":function (a,b){ return a%b; },
  115.           "=":function (a,b){ return a==b; },
  116.           "!=":function (a,b){ return a!=b; },
  117.           ">":function (a,b){ return a>b; },
  118.           "<":function (a,b){ return a<b; },
  119.           ">=":function (a,b){ return a>=b; },
  120.           "<=":function (a,b){ return a<=b; },
  121.           "and":function (a,b){ return a && b; },       //yea, and as a function it's no good, I kno
  122.           "concat":function (a,b){ return a.toString()+b.toString(); }}
  123.  
  124. var mymath1 = {"not" : function (a){ return !a; },
  125.            "sin" : function (a){ return Math.sin(a); },
  126.            "cos" : function (a){ return Math.cos(a); },
  127.            "tan" : function (a){ return Math.tan(a); }}
  128.            
  129.  
  130. function processwith(t,spirit){
  131.         var bindings = {};
  132.         var count = 0;
  133.         while (true) {
  134.                 bindings[t[count]] = evalline(t[count+1],spirit);
  135.                 //print(t[count],bindings[t[count]])
  136.                 if (t[count+2] == "and") {
  137.                         count = count + 3;
  138.                 } else {
  139.                         break;
  140.                 }
  141.         }
  142.         return bindings;
  143. }
  144.  
  145. function evalline(t,spirit){    //a spirit holds its variables, aka bindings
  146.         if (!isNaN(parseInt(t))) {
  147.                 return parseInt(t);
  148.         } else if (typeof t == "string") {
  149.                 if (t.charAt(0) === '"' && t.charAt(t.length-1) === '"') {
  150.                         return t.substring(1,t.length-1);
  151.                 } else if (typeof spirit.bindings[t] != "undefined") {
  152.                         return spirit.bindings[t];
  153.                 } else {
  154.                         //for k,v in pairs(spirit.bindings) do print(k,v) }
  155.                         //throw("unknown binding "+t+t.length);
  156.                 }
  157.         } else if (typeof t != "object") {
  158.                 throw("wrong type "+(typeof t));
  159.         } else if (t[0] == "conjure") {
  160.                 if (t[1] == "empty") {
  161.                         return conjureempty();
  162.                 } else {
  163.                         var spell = evalline(t[1],spirit);
  164.                         return conjurecopy(spell);      //you might make a copy of a spell, for some reason
  165.                 }
  166.         } else if (t[0] == "enchant") {
  167.                 var spell = evalline(t[1],spirit);
  168.                 enchant(spell, slice(t,2));     //the line ain't checked? only when executed? u avin a giggle m8?
  169.         } else if (t[0] == "bindself") {
  170.                 /*var exists = spirit.bindings[t[1]]
  171.                 if (exists) {
  172.                         throw("bindself: "..t[1].." already binded")   
  173.                 }*/
  174.                 spirit.bindings[t[1]] = evalline(slice(t,2),spirit)
  175.         } else if (t[0] == "bind") {
  176.                 var spr = evalline(t[1],spirit);
  177.                 /*var exists = spr.bindings[t[2]];      //exists considered harmful
  178.                 if (exists) {
  179.                         throw("bind: "..t[2].." already binded")
  180.                 }*/
  181.                 spr.bindings[t[2]] = evalline(slice(t,3),spirit)
  182.         } else if (t[0] == "from") {    //you can get the value of a bind from a different spirit
  183.                 var spr = evalline(t[1],spirit);
  184.                 return spr.bindings[t[2]];
  185.         } else if (t[0] == "at") {      //to be used with forms, which are also the listguys (why??)
  186.                 var sprorform = evalline(t[1],spirit);
  187.                 var n = evalline(t[2],spirit);
  188.                 return sprorform.spells[n]; //changed numbers so far
  189.         } else if (t[0] == "setat") {
  190.                 var sprorform = evalline(t[1],spirit);
  191.                 var n = evalline(t[2],spirit);
  192.                 var v = evalline(t[3],spirit);
  193.                 setat(sprorform,n,v);
  194.         } else if (mymath2[t[0]]) {
  195.                 var a = evalline(t[1],spirit);
  196.                 var b = evalline(t[2],spirit);
  197.                 return mymath2[t[0]](a,b)
  198.         } else if (mymath1[t[0]]) {
  199.                 var a = evalline(t[1],spirit);
  200.                 return mymath1[t[0]](a);
  201.         } else if (t[0] == "set") {     //just.. why?   DEPRECATED, BIND CAN CHANGE VALUES TOO
  202.                 //      this aint scheme fuk u
  203.                 //var exists = spirit.bindings[t[2]]
  204.                 //if not exists {
  205.                 //      throw("set: "..t[2].." not already binded")
  206.                 //}
  207.                 spirit.bindings[t[1]] = evalline(slice(t,2),spirit);
  208.         } else if (t[0] == "summon") {
  209.                 var spell = evalline(t[1],spirit);
  210.                 var bindings = {};
  211.                 if (t[2] == "with") {
  212.                         bindings = processwith(slice(t,3),spirit);
  213.                 }
  214.                 var spr = summon(spell,bindings)        //summon only adds it to the list, but doesnt do anything yet
  215.                 bindings.summoner = spirit;
  216.                 spirit.halt=true;       //when you summon, you're halted
  217.                 return spr
  218.         //elseif t[1] == "summonhold" {
  219.         //      var spell = evalline(t[2],spirit)
  220.         //      var bindings = {summoner=spirit}
  221.         //      if t[3] == "with" {
  222.         //              bindings = processwith(slice(t,4),spirit)
  223.         //              bindings.summoner=spirit
  224.         //      }
  225.         //      var spr = summonhold(spell,bindings)    //summonhold halts everything, evaling the spirit continuously until it is unsummoned
  226.         //      return spr.rturn
  227.         } else if (t[0] == "unsummon") {
  228.                 var spr = evalline(t[1],spirit)
  229.                 unsummon(spr);
  230.                 if (t[2] == "with") {   //this only has meaning if its a "unsummon self"
  231.                         spr.rturn = evalline(t[3],spirit)
  232.                 }
  233.         } else if (t[0] == "return") {
  234.                 var spr = evalline(t[1],spirit);
  235.                 return spr.rturn;
  236.         } else if (t[0] == "if") {      //oh god, if wont work without parentheses and =,>,<,etc
  237.                 var cond = evalline(t[1],spirit)
  238.                 if (cond) {
  239.                         return evalline(slice(t,2),spirit)
  240.                 }
  241.         } else if (t[0] == "print") {   //dunno how i'll do this, eval t[2] or slice(t,2)? for now i'll use slice
  242.                 var s
  243.                 if (t.length == 2) {
  244.                         s = evalline(t[1],spirit);
  245.                 } else {
  246.                         s = evalline(slice(t,1),spirit);
  247.                 }
  248.                 //print(s);
  249.                 alert(s);
  250.         } else if (t[0] == "read") {
  251.                 //return io.read()
  252.                 return 10;
  253.         } else if (t[0] == "skip") {
  254.                 var n
  255.                 if (t.length == 2) {
  256.                         n = evalline(t[1],spirit)
  257.                 } else {
  258.                         n = evalline(slice(t,1),spirit)
  259.                 }
  260.                 spirit.p = (spirit.p+n)%spirit.spells.length
  261.         } else if (t[0] && !t[1]) {     //something went wrong, sliced instead of using t[x]? quickfix
  262.                 return evalline(t[0],spirit);
  263.         }
  264. }
  265.  
  266. function mydofile(s) {
  267.         spiritlist=[];  //need to clear it
  268.         spiritcount=0;
  269.         var spells = parsefile(s);
  270.         var mainform = conjureempty();  //spells are forms but I should call spells' spells enchantments dunno
  271.         mainform.spells = spells;
  272.         enchant(mainform,["unsummon","self"]);  //so it will only run once
  273.         summon(mainform,{});
  274.         dospirits();
  275.         return "hehe";
  276. }
  277.  
  278. /*
  279. function mydofilename(filename){
  280.         spiritlist=[];  //need to clear it
  281.         spiritcount=0;
  282.         var file = io.open(filename,"r")
  283.         var s = file:read("*a")
  284.         mydofile(s)
  285. }*/
  286.  
  287. function dospirits(){   //here's where the shit gets done
  288.         while (true) {
  289.                 var sprcount = 0;       //it's different from spiritcount up there /\, that other is like an id count
  290.                 for (var k in spiritlist) {
  291.                         var spirit = spiritlist[k];
  292.                         if (spirit){
  293.                                 if (!spirit.halt) {
  294.                                         evalspirit(spirit);
  295.                                 }
  296.                                         sprcount = sprcount+1;
  297.                         }
  298.                 }
  299.                 if (sprcount == 0) {    //no more spirits alive, why should we keep running?
  300.                         break;
  301.                 }
  302.         }
  303. }
  304.  
  305. function evalspirit(spirit){
  306.         //while spirit.p <= #spirit.spells do
  307.                 if (spirit.dead) { //todo:unhalt summoner       //nvm, i do that in the unsummon in evalline
  308.                         //break
  309.                 }
  310.                 evalline(spirit.spells[spirit.p],spirit);
  311.                 spirit.p = spirit.p+1;
  312.         //}
  313.         if (spirit.p >= spirit.spells.length) {
  314.                 spirit.p=0;
  315.         }
  316.         //spirit.bindings.firstloop = false
  317. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top