diff --git a/.gitignore b/.gitignore
index 3847865..0bd19f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
test.lua
+*.ogg
diff --git a/DMS.xml b/DMS.xml
index 651e031..ac2db17 100644
--- a/DMS.xml
+++ b/DMS.xml
@@ -24,10 +24,10 @@
/*
*/
- ENABLE DISABLE LOAD ENTRY USING VERSION as
+ ENABLE DISABLE LOADFILE ENTRY USING VERSION as
if then return and or True False for while
- leaking debugging warnings
- ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD JUMP error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread setGlobalVar getGlobalVar
+ leaking debugging warnings statesave hostmsg
+ ceil tan CSIM log10 sinh GOTOE lshift deg MUL QUIT cosh exp rad GOTO SUB log ADD JUMP error POW randomseed floor tanh max atan SKIP acos DIV abs rshif COMPARE print atan2 asin cos sin mod sqrt function getInput sleep getVar setVar newThread setGlobalVar getGlobalVar SAVE LOAD WATCH
_VERSION
filesystem extendedDefine
diff --git a/Story/bedroom.dms b/Story/bedroom.dms
new file mode 100644
index 0000000..966062d
--- /dev/null
+++ b/Story/bedroom.dms
@@ -0,0 +1,3 @@
+[BEDROOM]{
+
+}
\ No newline at end of file
diff --git a/parseManager/audio.lua b/parseManager/audio.lua
new file mode 100644
index 0000000..1b4ef06
--- /dev/null
+++ b/parseManager/audio.lua
@@ -0,0 +1,29 @@
+require("proAudioRt")
+proAudio.create()
+local audio = {}
+audio.__index = audio
+function audio:new(path)
+ local c = {}
+ c.path = path
+ c.handle = proAudio.sampleFromFile(path)
+ setmetatable(c,audio)
+ return c
+end
+function audio:play(volume,loop)
+ local volume = volume or 1
+ if loop then
+ proAudio.soundLoop(self.handle, volume, volume, 0, 1)
+ else
+ proAudio.soundPlay(self.handle, volume, volume, 0, 1)
+ end
+end
+function audio:stop()
+ if not self then proAudio.soundStop() return end
+ proAudio.soundStop(self.handle)
+end
+function audio:setVolume(volume)
+ proAudio.soundUpdate(self.handle,volume,volume)
+end
+function parseManager:audio()
+ return audio
+end
\ No newline at end of file
diff --git a/parseManager/extendedDefine.lua b/parseManager/extendedDefine.lua
index be4a456..2396000 100644
--- a/parseManager/extendedDefine.lua
+++ b/parseManager/extendedDefine.lua
@@ -1,4 +1,4 @@
-local multi,bin,GLOBAL,sThread
+local multi, bin, GLOBAL,sThread
local loaded, err = pcall(function()
multi = require("multi")
local plat = multi:getPlatform()
@@ -7,18 +7,17 @@ local loaded, err = pcall(function()
elseif plat == "love2d" then
GLOBAL, sThread = require("multi.integration.loveManager").init()
end
- GLOBAL["TEST"]=true
bin = require("bin")
end)
function parseManager:extendedDefine()
if not loaded then self:pushWarning("Could not load the extendedDefine module!") print(err) end
local tc = 1
+ self.mainENV=GLOBAL
+ self.currentENV=GLOBAL
self:define{
- setVar = function(self,name,val)
- GLOBAL[name]=val
- end,
- getVar = function(self,name)
- return sThread.waitFor(name)
+ WATCH=function(self,...)
+ if self.watchvars then return end
+ self.watchvars = {...}
end,
newThread = function(self,block,name)
multi:newSystemThread(name or "NewThread"..tc,function(blck,path,name)
@@ -30,22 +29,18 @@ function parseManager:extendedDefine()
sThread=_G.sThread
end
local test=parseManager:load(path)
- t=test:next(blck)
+ test.mainENV = GLOBAL
+ test.currentENV = GLOBAL
test:define{
sleep = function(self,n)
thread.sleep(n)
end,
- setVar = function(self,name,val)
- GLOBAL[name]=val
- end,
- getVar = function(self,name)
- return sThread.waitFor(name)
- end,
- test = function(self,text)
- os.execute("title "..text.."")
+ title = function(self,t)
+ os.execute("title "..t)
end
}
- multi:newThread("Runner",function()
+ t=test:next(blck)
+ multi:newThread(name,function()
while true do
thread.skip(0)
if not t then error("Thread ended!") end
@@ -78,7 +73,9 @@ function parseManager:extendedDefine()
multi:mainloop()
end,block,self.currentChunk.path,name or "NewThread"..tc)
tc=tc+1
-
end,
}
end
+multi.OnError(function(...)
+ print(...)
+end)
diff --git a/parseManager/init.lua b/parseManager/init.lua
index 8fccf2e..fc40f97 100644
--- a/parseManager/init.lua
+++ b/parseManager/init.lua
@@ -1,3 +1,10 @@
+_print = print
+local noprint
+function print(...)
+ if not noprint then
+ _print(...)
+ end
+end
require("bin")
parseManager={}
parseManager.VERSION = 5
@@ -33,9 +40,9 @@ function parseManager:mainRunner(block)
elseif t.Type=="method" then
t=self:next()
elseif t.Type=="choice" then
- print(t.text)
+ _print(t.text)
for i=1,#t.choices do
- print(i..". "..t.choices[i])
+ _print(i..". "..t.choices[i])
end
io.write("Choose#: ")
cm=tonumber(io.read())
@@ -99,9 +106,15 @@ function factorial(n)
end
end
function parseManager:ENABLE(fn)
+ if fn == "hostmsg" then
+ noprint = false
+ end
self.stats[string.lower(fn)]=true
end
function parseManager:DISABLE(fn)
+ if fn == "hostmsg" then
+ noprint = true
+ end
self.stats[string.lower(fn)]=false
end
function parseManager:USING(fn,name)
@@ -168,6 +181,9 @@ function parseManager:load(path,c)
c = {}
setmetatable(c,parseManager)
end
+ if not c.path then
+ c.path = path
+ end
local file
if type(path)=="table" then
if path.Type=="bin" then
@@ -203,7 +219,7 @@ function parseManager:load(path,c)
self:debug("E",fn)
c:ENABLE(fn)
end
- for fn in header:gmatch("LOAD (.-)\n") do
+ for fn in header:gmatch("LOADFILE (.-)\n") do
self:debug("L",fn)
c:load(fn,c)
end
@@ -412,6 +428,7 @@ function parseManager:dump()
return str
end
function table.print(tbl, indent)
+ if type(tbl)~="table" then return end
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = string.rep(' ', indent) .. k .. ': '
@@ -469,7 +486,6 @@ local function pieceList(list,self,name)
else
local sym = getSymbol("`")
self:compileFWR("__PUSHPARSE",sym,'"$'..list[i]..'$"',name)
- cc=cc+1
L[#L+1]="\1"..sym
end
elseif list[i]:sub(1,1)=="\"" and list[i]:sub(-1,-1)=="\"" then
@@ -871,18 +887,32 @@ end
local function trim1(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
+local function extract(dat,name)
+ if type(dat)=="string" and dat:sub(1,1)=="\1" then
+ return dat:sub(2,-1)
+ elseif tonumber(dat)~=nil then
+ return tonumber(dat)
+ else
+ return dat
+ end
+end
function parseManager:compile(name,ctype,data)
local isFBlock,FBArgs=ctype:match("(f)unction%((.*)%)")
--Check if we are dealing with a FBlock
if isFBlock=="f" then
+ if not self.isInternal then
+ self.isInternal = {}
+ end
self.cFuncs[name]=true
-- if self.methods[name] then
-- self:pushError("You cannot create a method with the same name as a standard method or duplicate method names!",name)
-- end
self.methods[name]=function(...)
- self:Invoke(name,...)
+ --self:Invoke(name,...)
+ return self:Call(name,...)
end
- self.__INTERNAL[name] = true
+ self.isInternal[name]=self.methods[name]
+ -- self.__INTERNAL[name] = true
-- if not self.variables.__internal then
-- self.variables.__internal = {}
-- end
@@ -902,10 +932,10 @@ function parseManager:compile(name,ctype,data)
for i=1,#data do
data[i]=trim1(data[i])
if data[i]~="" then
- if data[i]:match("for[%s%w=%-]-[%d%-,%s]-<") then
+ if data[i]:match("for[%s%w=%-]-[%d%-%w%(%),%s]-<") then
choiceBlockFor=true
local sym = getSymbol("FOR")
- local var,a,b,c = data[i]:match("for%s*([%w_]+)%s*=%s*(%-*[%d]+),%s*(%-*[%d]+)%s*,*%s*(%-*[%d]*)")
+ local var,a,b,c = data[i]:match("for%s*([%w_]+)%s*=%s*(%-*[%d%w%(%)]+),%s*(%-*[%d%w%(%)]+)%s*,*%s*(%-*[%d%w%(%)]*)")
local s = getSymbol(getSymbol("LOOPEND"))
push(stack,{sym,var,a,b,s,1,c}) -- 1 for loop, 2 while loop
data[i] = "::"..sym.."::"
@@ -930,7 +960,12 @@ function parseManager:compile(name,ctype,data)
local s = dat[5]
local cmd = dat[6]
if cmd==1 then
- self:compileAssign(dat[2],dat[2] .. (tonumber(dat[7]) or "+1"),name)
+ local t = extract(dat[7],name)
+ if type(t)=="string" then
+ t="+"..t
+ end
+ -- print(dat[2] .. (t or "+1"))
+ self:compileAssign(dat[2],dat[2] .. (t or "+1"),name)
self:compileCondition(dat[2].."=="..tonumber(dat[4])+(tonumber(dat[7]) or 1),"GOTO(\""..s.."\")","GOTO(\""..dat[1].."\")",name)
data[i] = "::"..s.."::"
elseif cmd == 2 then
@@ -1050,6 +1085,15 @@ function parseManager:testDict(dict)
return
end
end
+function parseManager:dataToEnv(values)
+ local env = {}
+ if values then
+ for i,v in pairs(values) do
+ env[#env+1] = test:dataToValue(v)
+ end
+ end
+ return env
+end
function parseManager:dataToValue(name,envF,b) -- includes \1\
envF=envF or self.currentENV
local tab=name
@@ -1076,7 +1120,11 @@ function parseManager:dataToValue(name,envF,b) -- includes \1\
end
end
end
- return tab or {}
+ if tab~= nil then
+ return tab
+ else
+ return {}
+ end
end
function parseManager:define(t)
for i,v in pairs(t) do
@@ -1086,80 +1134,6 @@ end
function parseManager:handleChoice(func)
self.choiceManager = func
end
-function parseManager:Invoke(func,vars,...)
- if not self.isrunning then
- self.isrunning = true
- local t=self:next()
- local name=func
- local func=self.chunks[func]
- if func then
- if func.type:sub(1,1)=="f" then
- local returndata={}
- self.fArgs={...}
- if #self.fArgs==0 then
- self.fArgs={self.lastCall}
- end
- push(self.stack,{chunk=self.currentChunk,pos=self.currentChunk.pos,env=self.currentENV,vars=vars})
- self.currentENV = self:newENV()
- self.methods.JUMP(self,name)
- -- return
- else
- self:pushError("Attempt to call a non function block!",name)
- end
- else
- self:pushError("Attempt to call a non existing function!",name)
- end
- while t do
- if t.Type=="text" then
- io.write(t.text)
- io.read()
- t=self:next()
- elseif t.Type=="condition" then
- t=self:next()
- elseif t.Type=="assignment" then
- t=self:next()
- elseif t.Type=="label" then
- t=self:next()
- elseif t.Type=="method" then
- t=self:next()
- elseif t.Type=="choice" then
- if self.choiceManager then
- t=self:choiceManager(t)
- else
- t=self:next(nil,math.random(1,#t[1]))
- end
- elseif t.Type=="end" then
- if t.text=="leaking" then
- t=self:next()
- end
- elseif t.Type=="error" then
- error(t.text)
- else
- t=self:next()
- end
- end
- return
- end
- local name=func
- local func=self.chunks[func]
- if func then
- if func.type:sub(1,1)=="f" then
- local returndata={}
- self.fArgs={...}
- if #self.fArgs==0 then
- self.fArgs={self.lastCall}
- end
- push(self.stack,{chunk=self.currentChunk,pos=self.currentChunk.pos,env=self.currentENV,vars=vars})
- self.currentENV = self:newENV()
- self.methods.JUMP(self,name)
- return
- else
- self:pushError("Attempt to call a non function block!",name)
- end
- else
- self:pushError("Attempt to call a non existing function!",name)
- end
-end
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
@@ -1370,51 +1344,30 @@ function parseManager:next(block,choice)
self.lastCall=nil
return {Type="text",text=self:parseHeader(data.text)}
elseif data.Type=="funcblock" then
- local env=self.currentENV
- self.currentENV=self:newENV()
- self:pairAssign(data.args,self.fArgs,env)
+ -- self:pairAssign(data.args,self.fArgs)
return {Type="FBLOCK"}
elseif data.Type=="return" then
- local obj=pop(self.stack)
- local chunk=obj.chunk
- local pos=obj.pos
- local env=obj.env
- local vars=obj.vars
- local name=chunk.name
- local env=self.currentENV
- chunk.pos=pos
- self.currentENV=env
- self:pairAssign(vars,data.RETArgs,env)
- self.currentChunk=chunk
- return {Type="method"}
+ return {Type="method",Vars = vars, RetArgs = data.RETArgs}
elseif data.Type=="fwr" then
local args=self:dataToValue(data.args,nil,data.Func == "__PUSHPARSE")
local rets={}
local Func
- local Ext=false
if type(data.Func)=="table" then
Ext=true
Func=self.currentENV[data.Func[1]][data.Func[2]]
else
Func=self.methods[data.Func]
end
- if Ext then
+ if self.isInternal[data.Func] then
rets={Func(unpack(args))}
- elseif self.__INTERNAL[data.Func] then
- self:Invoke(data.Func,data.vars,unpack(args))
else
- if type(Func)~="function" then
- rets={self:Invoke(data.Func,data.vars,unpack(args))}
- return {Type="method"}
- else
- rets={Func(self,unpack(args))}
- end
+ rets={Func(self,unpack(args))}
end
if #rets~=0 then
self:pairAssign(data.vars,rets)
end
self.lastCall=nil
- return {Type="method"}
+ return {Type="method",name=data.Func,args = args}
elseif data.Type=="fwor" then
local args=self:dataToValue(data.args)
local Func
@@ -1428,14 +1381,9 @@ function parseManager:next(block,choice)
if Ext then
self.lastCall=Func(unpack(args))
else
- if type(Func)~="function" then
- self.lastCall=self:Invoke(data.Func,"lastCall",unpack(args))
- return {Type="method"}
- else
- self.lastCall=Func(self,unpack(args))
- end
+ self.lastCall=Func(self,unpack(args))
end
- return {Type="method"}
+ return {Type="method",name=data.Func,args = args}
elseif data.Type=="choice" then
self.choiceData=data
local CList={}
diff --git a/parseManager/standardDefine.lua b/parseManager/standardDefine.lua
index d6f09b8..cc1438f 100644
--- a/parseManager/standardDefine.lua
+++ b/parseManager/standardDefine.lua
@@ -1,3 +1,4 @@
+local bin = require("bin")
local clock = os.clock
parseManager:define{
__PUSHPARSE = function(self,dat)
@@ -10,7 +11,39 @@ parseManager:define{
return io.read()
end,
print=function(self,...)
- print(...)
+ _print(...)
+ end,
+ WATCH=function(self,...)
+ if self.watchvars then return end
+ self.watchvars = {...}
+ end,
+ SAVE=function(self,fn)
+ local file = bin.new()
+ local data = {}
+ for i=1,#self.watchvars do
+ data[self.watchvars[i]] = self.currentENV[self.watchvars[i]]
+ end
+ data["__CHUNK"] = self.methods.getCurrentChunk(self)
+ data["__POSITION"] = self.methods.getCurrentPosition(self)
+ file:addBlock(data)
+ file:tofile(fn or "save.dat")
+ end,
+ LOAD=function(self,fn)
+ if not bin.fileExists(fn or "save.dat") then return false end
+ local file = bin.load(fn or "save.dat")
+ t = file:getBlock("t")
+ local c,p = t.__CHUNK,t.__POSITION
+ t.__CHUNK,t.__POSITION = nil,nil
+ for i,v in pairs(t) do
+ self.mainENV[i] = v
+ end
+ if self.stats.statesave then
+ self.methods.JUMP(self,c, p)
+ end
+ return true,c,p
+ end,
+ EXECUTE = function(self,cmd)
+ os.execute(cmd)
end,
error=function(self,msg)
self:pushError(msg,"\2")
@@ -21,16 +54,29 @@ parseManager:define{
getGlobalVar=function(self,var,val)
self.mainENV[var]=val
end,
+ len=function(self,t)
+ return #t
+ end,
QUIT=function()
os.exit()
end,
+ getCurrentChunk = function(self)
+ for i,v in pairs(self.chunks) do
+ if self.currentChunk == v then
+ return i
+ end
+ end
+ end,
+ getCurrentPosition = function(self)
+ return self.currentChunk.pos-1
+ end,
sleep=function(self,n)
local t0 = clock()
while clock() - t0 <= n do end
end,
- JUMP=function(self,block)
+ JUMP=function(self,block,pos)
if self.chunks[block] then
- self.chunks[block].pos=1
+ self.chunks[block].pos=pos or 1
self.currentChunk=self.chunks[block]
else
self:pushError("Attempt to jump to a non existing block:","\2")
@@ -342,7 +388,4 @@ parseManager:define{
self.methods.SKIP(self,1)
end
end,
- print=function(self,...)
- print(...)
- end
}
diff --git a/proAudioRt.dll b/proAudioRt.dll
new file mode 100644
index 0000000..f24fcb9
Binary files /dev/null and b/proAudioRt.dll differ
diff --git a/rps.dmsc b/rps.dmsc
new file mode 100644
index 0000000..40c8dc6
Binary files /dev/null and b/rps.dmsc differ
diff --git a/save.dat b/save.dat
new file mode 100644
index 0000000..e7b995f
Binary files /dev/null and b/save.dat differ
diff --git a/test.dms b/test.dms
index 0feadef..977b3b1 100644
--- a/test.dms
+++ b/test.dms
@@ -1,43 +1,61 @@
-ENTRY MAIN
+ENTRY INIT2
+LOADFILE Story/bedroom.dms
USING extendedDefine
-VERSION 4.1
-[MAIN]{
- // test = [1,2,3,4,5,6,7,8,9,10]
- // t=0
- // test2 = "Hello"
- // str = $test2[1:-1]$
- // print("$test2[-1:1]$")
- // print(str)
- // t=testfunc(1,2)
- // print(t)
- // for i = 1,10 <
- // "Choice Test: $test[1]$" <
- // "A" setGlobalVar("t",1)
- // "B" continue()
- // "C" setGlobalVar("t",3)
- // >
- // >
- // ::leave::
- // print("t = $t$ i = $i$")
- val = 0
+DISABLE warnings
+USING audio as audio
+// DISABLE hostmsg
+[INIT2]{
multi = external()
- multi:newTLoop(testfunc,1)
- // multi:newTLoop(testfunc2)
- // alarm = multi:newAlarm(3)
- // alarm:OnRing(testfunc)
- print("Hooked function!")
+ multi:newTLoop(DoMe,1)
}
-[testfunc:function()]{
- val = val + 1
- print("Called $val$ times!")
- return True
+[DoMe:function(a)]{
+ print("Hi",a)
}
-[testfunc2:function()]{
- "Test"<
- "1" print("A")
- "2" print("B")
- "3" print("C")
- >
- // print("Yo whats up!")
- return True
-}
\ No newline at end of file
+/*
+[INIT]{
+ // The LOAD function will load variables and jump to the saved location. Be sure to setup runtime variables before the LOAD function is called!
+ WATCH("money","name","day","chapter","passive")
+ loaded,c,p = LOAD()
+ if loaded==false then JUMP("SETUP")|SKIP(0)
+ newThread("UPDATER","Thread_DisplayStats")
+ JUMP(c,p)
+ QUIT()
+}
+[SETUP]{
+ money = 100
+ name = getInput("Enter name: ")
+ day = 1
+ chapter = 1
+ passive = 1
+ newThread("UPDATER","Thread_DisplayStats")
+ SAVE()
+ JUMP("START")
+}
+[UPDATER]{
+ maintheme=audio:new("Audio/Nadia.ogg")
+ maintheme:play(.5)
+ ::loop::
+ EXECUTE("title $name$ $$money$ Day: $day$ Chap: $chapter$")
+ sleep(.1)
+ money = money + passive
+ GOTO("loop")
+}
+[stop:function()]{
+ "hmm"
+ return 1,2
+}
+[Fade:function(obj)]{
+ // for x = 100, 0, -1 <
+ // sleep(.1)
+ // obj:setVolume(x/100)
+ // >
+}
+[START]{
+ "HI!"
+ maintheme:setVolume(1)
+ sleep(1)
+ Fade(maintheme)
+ "Yo"
+ // JUMP("BEDROOM")
+}
+*/
diff --git a/test.dmsc b/test.dmsc
index e8567f7..ba0e4ea 100644
Binary files a/test.dmsc and b/test.dmsc differ
diff --git a/test.lua b/test.lua
index a059c82..86d4e15 100644
--- a/test.lua
+++ b/test.lua
@@ -1,16 +1,52 @@
package.path="?/init.lua;lua/?/init.lua;lua/?.lua;"..package.path
+package.cpath="?.dll;"..package.cpath
local bin = require("bin")
local multi = require("multi")
require("parseManager")
require("multi")
-test=parseManager:compileToFile("test.dms","test.dmsc")--load("StoryTest/init.dms")
---~ test = parseManager:loadCompiled("test.dmsc")
-print(test:dump())
+test=parseManager:load("test.dms")--parseManager:compileToFile("test.dms","test.dmsc")--
test:define{
- external=function(self)
+ external = function()
return multi
end
}
+--~ test = parseManager:loadCompiled("test.dmsc")
+function parseManager:Call(func,...)
+ local env = {}
+ local temp = parseManager:load(self.path)
+--~ local temp = {}
+--~ setmetatable(temp,{__index = self})
+ temp.fArgs = {...}
+ local t = temp:next(func)
+ while t do
+ if t.Type=="text" then
+ io.write(t.text.."\n")
+ t=temp:next()
+ elseif t.Type=="condition" then
+ t=temp:next()
+ elseif t.Type=="assignment" then
+ t=temp:next()
+ elseif t.Type=="label" then
+ t=temp:next()
+ elseif t.Type=="method" then
+ env = temp:dataToEnv(t.RetArgs)
+ t=temp:next()
+ elseif t.Type=="choice" then
+ _print(t.prompt)
+ io.write("Choose#: ")
+ cm=tonumber(1,#t[1])
+ t=temp:next(nil,cm)
+ elseif t.Type=="end" then
+ print("Something went wrong!")
+ elseif t.Type=="error" then
+ error(t.text)
+ else
+ t=temp:next()
+ end
+ end
+ return unpack(env)
+end
+--~ print(test.methods.DoMe(test,1,2))
t=test:next()
while t do
if t.Type=="text" then
@@ -26,7 +62,7 @@ while t do
elseif t.Type=="method" then
t=test:next()
elseif t.Type=="choice" then
- print(t.prompt)
+ _print(t.prompt)
for i=1,#t[1] do
print(i..". "..t[1][i])
end
@@ -45,4 +81,6 @@ while t do
t=test:next()
end
end
-multi:mainloop()
+multi:mainloop{
+ protect = true
+}