Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --okay, lets do this
- --keywords, so I dont forget any
- --unsummon, summon, summonhold, conjure, enchant, dispel, bind, bindself, with, empty, print, set, skip
- --a spirit is something summoned and running, a spell is the scroll, or the recipe
- --spirits hold variables, spells don't
- --THIS ONE WITH ONE INSTRUCTION PER TIME
- function string:split(sep)
- local sep, fields = sep or ":", {}
- local pattern = string.format("([^%s]+)", sep)
- self:gsub(pattern, function(c) fields[#fields+1] = c end)
- return fields
- end
- function parseline(s)
- s = "("..s..")" --the fuck? is this lisp?
- s = s:gsub("%("," ( "):gsub("%)"," ) "):gsub(" +"," ")
- local t = s:split(" ")
- return read_from(t)
- end
- function read_from(tokens)
- if #tokens == 0 then
- error ( "unexpected EOF while reading" )
- end
- local token = tokens[1]
- table.remove(tokens,1)
- if "(" == token then
- local L = {}
- while tokens[1] ~= ")" do
- table.insert(L, read_from(tokens))
- end
- table.remove(tokens,1) --pop off ")"
- return L
- elseif ")" == token then
- error("unexpected )")
- else
- return token
- end
- end
- function parsefile(s)
- s = s:gsub("\n+","\n")
- return map(parseline,s:split("\n"))
- end
- function map(func,t)
- local t2 = {}
- for x=1,#t do
- t2[x] = func(t[x])
- end
- return t2
- end
- function conjureempty()
- return {spells={}}
- end
- function enchant(form,t) --of course a syntax check must be done first, right??
- table.insert(form.spells,t)
- end
- function setat(form,n,v) --a form that isn't summoned is just a list
- form.spells[n]=v
- end
- function slice(t,start)
- local t2 = {}
- for x=start,#t do
- table.insert(t2,t[x])
- end
- return t2
- end
- function copy(t)
- return slice(t,1)
- end
- spiritlist = {}
- spiritcount = 0
- function summon(form,bindings)
- local spirit = {spells=copy(form.spells),bindings=bindings,p=1} --must be a copy cuz it might be altered at runtime
- spiritcount=spiritcount+1
- spiritlist[spiritcount] = spirit
- spirit.id = spiritcount
- spirit.bindings.self = spirit --not a special word, but a common var that can be changed with set! U WOOT!!
- spirit.bindings.selfform = form
- spirit.bindings.firstloop = true --a useful boolean
- return spirit
- end
- function unsummon(spirit) --need to remove it from the spirit list, and put a tag on it saying "dead"
- spiritlist[spirit.id] = nil
- spirit.dead=true
- if spirit.bindings.summoner then
- spirit.bindings.summoner.halt=false --this unhalts the summoner
- end
- end
- --function summonhold(form,bindings)
- -- local spirit = summon(form,bindings)
- -- while not spirit.dead do
- -- evalspirit(spirit)
- -- end
- -- return spirit
- --end
- mymath2 = {["+"]=function (a,b) return a+b end,
- ["-"]=function (a,b) return a-b end,
- ["*"]=function (a,b) return a*b end,
- ["/"]=function (a,b) return a/b end,
- ["%"]=function (a,b) return a%b end,
- ["="]=function (a,b) return a==b end,
- ["!="]=function (a,b) return a~=b end,
- [">"]=function (a,b) return a>b end,
- ["<"]=function (a,b) return a<b end,
- [">="]=function (a,b) return a>=b end,
- ["<="]=function (a,b) return a<=b end,
- ["and"]=function (a,b) return a and b end, --yea, and as a function it's no good, I kno
- ["concat"]=function (a,b) return tostring(a)..tostring(b) end}
- mymath1 = {["not"] = function (a) return (not a) end,
- ["sin"] = function (a) return math.sin(a) end,
- ["cos"] = function (a) return math.cos(a) end,
- ["tan"] = function (a) return math.tan(a) end}
- function processwith(t,spirit)
- local bindings = {}
- local count = 1
- while true do
- bindings[t[count]] = evalline(t[count+1],spirit)
- --print(t[count],bindings[t[count]])
- if t[count+2] == "and" then
- count = count + 3
- else
- break
- end
- end
- return bindings
- end
- function evalline(t,spirit) --a spirit holds its variables, aka bindings
- if type(tonumber(t)) == "number" then
- return tonumber(t)
- elseif type(t) == "string" then
- if t:sub(1,1) == '"' and t:sub(#t,#t) == '"' then
- return t:sub(2,#t-1)
- elseif spirit.bindings[t] ~= nil then
- return spirit.bindings[t]
- else
- for k,v in pairs(spirit.bindings) do print(k,v) end
- error("unknown binding "..t..#t..tostring(spirit.bindings[t]))
- end
- elseif type(t) ~= "table" then
- error("wrong type "..type(t))
- elseif t[1] == "conjure" then
- if t[2] == "empty" then
- return conjureempty()
- else
- local spell = evalline(t[2],spirit)
- return conjurecopy(spell) --you might make a copy of a spell, for some reason
- end
- elseif t[1] == "enchant" then
- local spell = evalline(t[2],spirit)
- enchant(spell, slice(t,3)) --the line ain't checked? only when executed? u avin a giggle m8?
- elseif t[1] == "bindself" then
- local exists = spirit.bindings[t[2]]
- if exists then
- error("bindself: "..t[2].." already binded")
- end
- spirit.bindings[t[2]] = evalline(slice(t,3),spirit)
- elseif t[1] == "bind" then
- local spr = evalline(t[2],spirit)
- local exists = spr.bindings[t[3]]
- if exists then
- error("bind: "..t[3].." already binded")
- end
- spr.bindings[t[3]] = evalline(slice(t,4),spirit)
- elseif t[1] == "from" then --you can get the value of a bind from a different spirit
- local spr = evalline(t[2],spirit)
- return spr.bindings[t[3]]
- elseif t[1] == "at" then --to be used with forms, which are also the listguys (why??)
- local sprorform = evalline(t[2],spirit)
- local n = evalline(t[3],spirit)
- return sprorform.spells[n]
- elseif t[1] == "setat" then
- local sprorform = evalline(t[2],spirit)
- local n = evalline(t[3],spirit)
- local v = evalline(t[4],spirit)
- setat(sprorform,n,v)
- elseif mymath2[t[1]] then
- local a = evalline(t[2],spirit)
- local b = evalline(t[3],spirit)
- return mymath2[t[1]](a,b)
- elseif mymath1[t[1]] then
- local a = evalline(t[2],spirit)
- return mymath1[t[1]](a)
- elseif t[1] == "set" then --just.. why?
- -- this aint scheme fuk u
- --local exists = spirit.bindings[t[2]]
- --if not exists then
- -- error("set: "..t[2].." not already binded")
- --end
- spirit.bindings[t[2]] = evalline(slice(t,3),spirit)
- elseif t[1] == "summon" then
- local spell = evalline(t[2],spirit)
- local bindings = {}
- if t[3] == "with" then
- bindings = processwith(slice(t,4),spirit)
- end
- local spr = summon(spell,bindings) --summon only adds it to the list, but doesnt do anything yet
- bindings.summoner = spirit
- spirit.halt=true --when you summon, you're halted
- return spr
- --elseif t[1] == "summonhold" then
- -- local spell = evalline(t[2],spirit)
- -- local bindings = {summoner=spirit}
- -- if t[3] == "with" then
- -- bindings = processwith(slice(t,4),spirit)
- -- bindings.summoner=spirit
- -- end
- -- local spr = summonhold(spell,bindings) --summonhold halts everything, evaling the spirit continuously until it is unsummoned
- -- return spr.rturn
- elseif t[1] == "unsummon" then
- local spr = evalline(t[2],spirit)
- unsummon(spr)
- if t[3] == "with" then --this only has meaning if its a "unsummon self"
- spr.rturn = evalline(t[4],spirit)
- end
- elseif t[1] == "return" then
- local spr = evalline(t[2],spirit)
- return spr.rturn
- elseif t[1] == "if" then --oh god, if wont work without parentheses and =,>,<,etc
- local cond = evalline(t[2],spirit)
- if cond then
- return evalline(slice(t,3),spirit)
- end
- elseif t[1] == "print" then --dunno how i'll do this, eval t[2] or slice(t,2)? for now i'll use slice
- local s
- if #t == 2 then
- s = evalline(t[2],spirit)
- else
- s = evalline(slice(t,2),spirit)
- end
- print(s)
- elseif t[1] == "read" then
- return io.read()
- elseif t[1] == "skip" then
- local n
- if #t == 2 then
- n = evalline(t[2],spirit)
- else
- n = evalline(slice(t,2),spirit)
- end
- spirit.p = spirit.p+n
- elseif t[1] and not t[2] then --something went wrong, sliced instead of using t[x]? quickfix
- return evalline(t[1],spirit)
- end
- end
- function mydofile(s)
- local spells = parsefile(s)
- local mainform = conjureempty() --spells are forms but I should call spells' spells enchantments dunno
- mainform.spells = spells
- enchant(mainform,{"unsummon","self"}) --so it will only run once
- summon(mainform,{})
- dospirits()
- return "hehe"
- end
- function mydofilename(filename)
- spiritlist={} --need to clear it
- spiritcount=0
- local file = io.open(filename,"r")
- local s = file:read("*a")
- mydofile(s)
- end
- function dospirits() --here's where the shit gets done
- while true do
- local sprcount = 0 --it's different from spiritcount up there /\, that other is like an id count
- for k,spirit in pairs(spiritlist) do
- if not spirit.halt then
- evalspirit(spirit)
- end
- sprcount = sprcount+1
- end
- if sprcount == 0 then --no more spirits alive, why should we keep running?
- break
- end
- end
- end
- function evalspirit(spirit)
- --while spirit.p <= #spirit.spells do
- if spirit.dead then --todo:unhalt summoner
- --break
- end
- evalline(spirit.spells[spirit.p],spirit)
- spirit.p = spirit.p+1
- --end
- if spirit.p > #spirit.spells then
- spirit.p=1
- end
- --spirit.bindings.firstloop = false
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement