Advertisement
Guest User

Magic interpreter in Javascript

a guest
Apr 13th, 2013
246
0
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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement