Compare commits
1 Commits
8502abeff6
...
c318c780da
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c318c780da |
@ -2,14 +2,14 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
def emit(string):
|
def emit(string):
|
||||||
sys.stdout.buffer.write(string.encode('latin_1'))
|
sys.stdout.write(string)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def trace(header, value):
|
def trace(header, value):
|
||||||
if os.environ.get('TRACE'):
|
if os.environ.get('TRACE'):
|
||||||
sys.stderr.write(f'{header}={value!r}\n')
|
sys.stderr.write(f'{header}={value!r}\n')
|
||||||
|
|
||||||
eof = chr(0xFF)
|
eof = chr(0)
|
||||||
eol = chr(10)
|
eol = chr(10)
|
||||||
quote = chr(34)
|
quote = chr(34)
|
||||||
PEEK = None
|
PEEK = None
|
||||||
@ -39,36 +39,6 @@ def skip():
|
|||||||
|
|
||||||
PEEK = None
|
PEEK = None
|
||||||
|
|
||||||
def __check(func, args: list[str], msg: list[str]) -> None:
|
|
||||||
result = func(*args)
|
|
||||||
if result:
|
|
||||||
return
|
|
||||||
|
|
||||||
sys.stderr.write('ERROR: ' + ' '.join(msg) + '\n')
|
|
||||||
sys.stderr.flush()
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
MAPSTORE = {}
|
|
||||||
|
|
||||||
def mapclear(mapname: str) -> str:
|
|
||||||
MAPSTORE.pop(mapname)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def mapgetkey(mapname: str, key: str, default: str) -> str:
|
|
||||||
return MAPSTORE.get(mapname, {}).get(key, default)
|
|
||||||
|
|
||||||
def mapsetkey(mapname: str, key: str, value: str) -> str:
|
|
||||||
MAPSTORE.setdefault(mapname, {})
|
|
||||||
MAPSTORE[mapname][key] = value
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def registerid(id: str) -> str:
|
|
||||||
idname = mapgetkey("REGISTERID", id, "")
|
|
||||||
if idname:
|
|
||||||
return idname
|
|
||||||
idname = "id_" + id
|
|
||||||
return idname
|
|
||||||
|
|
||||||
def emitln(data):
|
def emitln(data):
|
||||||
emit(data)
|
emit(data)
|
||||||
emit(eol)
|
emit(eol)
|
||||||
@ -111,15 +81,12 @@ def parseconststring():
|
|||||||
emit(quote)
|
emit(quote)
|
||||||
|
|
||||||
def parseexprvarref():
|
def parseexprvarref():
|
||||||
varname = lexident()
|
var = lexident()
|
||||||
varid = registerid(varname)
|
emit(var)
|
||||||
emit(varid)
|
|
||||||
|
|
||||||
def parseexprcall():
|
def parseexprcall():
|
||||||
funcname = lexident()
|
funcname = lexident()
|
||||||
__check(mapgetkey, ["FUNCREG", funcname, ""], ["Function", funcname, "does not exist"])
|
emit(funcname)
|
||||||
funcid = registerid(funcname)
|
|
||||||
emit(funcid)
|
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
@ -142,12 +109,11 @@ def parsestatdeclare(indent):
|
|||||||
|
|
||||||
def parsestatset(indent):
|
def parsestatset(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
varname = lexident()
|
var = lexident()
|
||||||
varid = registerid(varname)
|
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(varid)
|
emit(var)
|
||||||
emit(' = ')
|
emit(' = ')
|
||||||
|
|
||||||
parseconststring()
|
parseconststring()
|
||||||
@ -157,12 +123,11 @@ def parsestatset(indent):
|
|||||||
|
|
||||||
def parsestatcalc(indent):
|
def parsestatcalc(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
varname = lexident()
|
var = lexident()
|
||||||
varid = registerid(varname)
|
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(varid)
|
emit(var)
|
||||||
emit(' = ')
|
emit(' = ')
|
||||||
|
|
||||||
parseexprcall()
|
parseexprcall()
|
||||||
@ -201,21 +166,17 @@ def parsestatreturn(indent):
|
|||||||
parseconststring()
|
parseconststring()
|
||||||
else:
|
else:
|
||||||
parseexprvarref()
|
parseexprvarref()
|
||||||
else:
|
|
||||||
emit('""')
|
|
||||||
emit(eol)
|
emit(eol)
|
||||||
skipchar(eol)
|
skipchar(eol)
|
||||||
|
|
||||||
def parsestatcheck(indent):
|
def parsestatcheck(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit('__check(')
|
emit('assert ')
|
||||||
|
|
||||||
funcname = lexident()
|
func_name = lexident()
|
||||||
funcid = registerid(funcname)
|
emit(func_name)
|
||||||
trace("funcid", funcid)
|
emit('(')
|
||||||
emit(funcid)
|
|
||||||
emit(', [')
|
|
||||||
notfirst = False
|
notfirst = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -236,7 +197,7 @@ def parsestatcheck(indent):
|
|||||||
|
|
||||||
skipchar(':')
|
skipchar(':')
|
||||||
|
|
||||||
emit('], [')
|
emit('), (')
|
||||||
notfirst = False
|
notfirst = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -253,21 +214,19 @@ def parsestatcheck(indent):
|
|||||||
if eol == peek():
|
if eol == peek():
|
||||||
break
|
break
|
||||||
notfirst = True
|
notfirst = True
|
||||||
|
emitln(')')
|
||||||
emitln('])')
|
|
||||||
|
|
||||||
def parsestattrace(indent):
|
def parsestattrace(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit('__trace("')
|
emit('trace("')
|
||||||
|
|
||||||
varname = lexident()
|
var_name = lexident()
|
||||||
varid = registerid(varname)
|
|
||||||
skipchar(eol)
|
skipchar(eol)
|
||||||
|
|
||||||
emit(varname)
|
emit(var_name)
|
||||||
emit('", ')
|
emit('", ')
|
||||||
emit(varid)
|
emit(var_name)
|
||||||
emitln(')')
|
emitln(')')
|
||||||
|
|
||||||
def parsestat(indent):
|
def parsestat(indent):
|
||||||
@ -310,12 +269,8 @@ def parsestat(indent):
|
|||||||
parsestattrace(indent)
|
parsestattrace(indent)
|
||||||
return
|
return
|
||||||
|
|
||||||
__check(mapgetkey, ["FUNCREG", call, ""], ["Function", call, "does not exist"])
|
|
||||||
|
|
||||||
callid = registerid(call)
|
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(callid)
|
emit(call)
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
@ -352,22 +307,19 @@ def parseblock(indent):
|
|||||||
|
|
||||||
def parsefunc():
|
def parsefunc():
|
||||||
funcname = lexident()
|
funcname = lexident()
|
||||||
funcid = registerid(funcname)
|
|
||||||
mapsetkey("FUNCREG", funcname, "1")
|
|
||||||
|
|
||||||
trace('funcname', funcname)
|
trace('funcname', funcname)
|
||||||
emit('def ')
|
emit('def ')
|
||||||
emit(funcid)
|
emit(funcname)
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
while ' ' == peek():
|
while ' ' == peek():
|
||||||
skip()
|
skip()
|
||||||
varname = lexident()
|
var = lexident()
|
||||||
varid = registerid(varname)
|
|
||||||
if not first:
|
if not first:
|
||||||
emit(", ")
|
emit(", ")
|
||||||
emit(varid)
|
emit(var)
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
if '/' == peek():
|
if '/' == peek():
|
||||||
@ -392,26 +344,26 @@ def emitheader():
|
|||||||
emitln("import os")
|
emitln("import os")
|
||||||
emitln("import sys")
|
emitln("import sys")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __eq(a: str, b: str) -> str:")
|
emitln("def eq(a, b):")
|
||||||
emitln(" return '1' if a == b else ''")
|
emitln(" return a == b")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __lt(a: str, b: str) -> str:")
|
emitln("def lt(a, b):")
|
||||||
emitln(" return '1' if a < b else ''")
|
emitln(" return a[0] < b[0]")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __add(a: str, b: str) -> str:")
|
emitln("def addstringchar(a, b):")
|
||||||
emitln(" return a + b")
|
emitln(" return a + b[0]")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __emit(string):")
|
emitln("def emit(string):")
|
||||||
emitln(" sys.stdout.buffer.write(string.encode('latin_1'))")
|
emitln(" sys.stdout.write(string)")
|
||||||
emitln(" sys.stdout.flush()")
|
emitln(" sys.stdout.flush()")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __trace(header, value):")
|
emitln("def trace(header, value):")
|
||||||
emitln(" if os.environ.get('TRACE'):")
|
emitln(" if os.environ.get('TRACE'):")
|
||||||
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
|
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("__EOF = chr(0xFF)")
|
emitln("eof = chr(0)")
|
||||||
emitln("__EOL = chr(10)")
|
emitln("eol = chr(10)")
|
||||||
emitln("__QUOTE = chr(34)")
|
emitln("quote = chr(34)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("STDINCOLNO = 0")
|
emitln("STDINCOLNO = 0")
|
||||||
emitln("STDINLINENO = 1")
|
emitln("STDINLINENO = 1")
|
||||||
@ -419,106 +371,41 @@ def emitheader():
|
|||||||
emitln("")
|
emitln("")
|
||||||
emitln("def _readchar():")
|
emitln("def _readchar():")
|
||||||
emitln(" char = sys.stdin.read(1)")
|
emitln(" char = sys.stdin.read(1)")
|
||||||
emitln(" __trace('char', char)")
|
emitln(" trace('char', char)")
|
||||||
emitln(" if not char:")
|
emitln(" if not char:")
|
||||||
emitln(" return __EOF")
|
emitln(" return eof")
|
||||||
emitln(" return char")
|
emitln(" return char")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __peek():")
|
emitln("def peek():")
|
||||||
emitln(" return STDINPEEK")
|
emitln(" return STDINPEEK")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __skip():")
|
emitln("def skip():")
|
||||||
emitln(" global STDINCOLNO")
|
emitln(" global STDINCOLNO")
|
||||||
emitln(" global STDINLINENO")
|
emitln(" global STDINLINENO")
|
||||||
emitln(" global STDINPEEK")
|
emitln(" global STDINPEEK")
|
||||||
emitln(" if __EOL == STDINPEEK:")
|
emitln(" if eol == STDINPEEK:")
|
||||||
emitln(" STDINLINENO += 1")
|
emitln(" STDINLINENO += 1")
|
||||||
emitln(" STDINCOLNO = 0")
|
emitln(" STDINCOLNO = 0")
|
||||||
emitln(" STDINCOLNO += 1")
|
emitln(" STDINCOLNO += 1")
|
||||||
emitln(" STDINPEEK = _readchar()")
|
emitln(" STDINPEEK = _readchar()")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __stdinlineno():")
|
emitln("def stdinlineno():")
|
||||||
emitln(" global STDINLINENO")
|
emitln(" global STDINLINENO")
|
||||||
emitln(" return str(STDINLINENO)")
|
emitln(" return str(STDINLINENO)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def __stdincolno():")
|
emitln("def stdincolno():")
|
||||||
emitln(" global STDINCOLNO")
|
emitln(" global STDINCOLNO")
|
||||||
emitln(" return str(STDINCOLNO)")
|
emitln(" return str(STDINCOLNO)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("__skip()")
|
emitln("skip()")
|
||||||
emitln("")
|
|
||||||
emitln("MAPSTORE = {}")
|
|
||||||
emitln("")
|
|
||||||
emitln("def __mapclear(mapname: str) -> str:")
|
|
||||||
emitln(" MAPSTORE.pop(mapname)")
|
|
||||||
emitln(" return ''")
|
|
||||||
emitln("")
|
|
||||||
emitln("def __mapgetkey(mapname: str, key: str, default: str) -> str:")
|
|
||||||
emitln(" return MAPSTORE.get(mapname, {}).get(key, default)")
|
|
||||||
emitln("")
|
|
||||||
emitln("def __mapsetkey(mapname: str, key: str, value: str) -> str:")
|
|
||||||
emitln(" MAPSTORE.setdefault(mapname, {})")
|
|
||||||
emitln(" MAPSTORE[mapname][key] = value")
|
|
||||||
emitln(" return ''")
|
|
||||||
emitln("")
|
|
||||||
emitln("def __not(a: str) -> str:")
|
|
||||||
emitln(" if a:")
|
|
||||||
emitln(" return ''")
|
|
||||||
emitln(" return '1'")
|
|
||||||
emitln("")
|
|
||||||
emitln("def __check(func, args: list[str], msg: list[str]) -> None:")
|
|
||||||
emitln(" result = func(*args)")
|
|
||||||
emitln(" if result:")
|
|
||||||
emitln(" return")
|
|
||||||
emitln("")
|
|
||||||
emitln(" sys.stderr.write('ERROR: ' + ' '.join(msg) + '\\n')")
|
|
||||||
emitln(" sys.stderr.flush()")
|
|
||||||
emitln(" exit(1)")
|
|
||||||
emitln("")
|
|
||||||
emitln("# ### END OF RUNTIME ### #")
|
|
||||||
emitln("")
|
emitln("")
|
||||||
|
|
||||||
def emitfooter():
|
def emitfooter():
|
||||||
mainid = registerid("main")
|
emit("if __name__ == '__main__':\n")
|
||||||
emitln("if __name__ == '__main__':")
|
emit(" main()\n")
|
||||||
emit(" ")
|
|
||||||
emit(mainid)
|
|
||||||
emitln("()")
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
emitheader()
|
emitheader()
|
||||||
|
|
||||||
# Standard library constants
|
|
||||||
mapsetkey("REGISTERID", "eof", "__EOF")
|
|
||||||
mapsetkey("REGISTERID", "eol", "__EOL")
|
|
||||||
mapsetkey("REGISTERID", "quote", "__QUOTE")
|
|
||||||
|
|
||||||
# Standard library functions
|
|
||||||
mapsetkey("FUNCREG", "add", "1")
|
|
||||||
mapsetkey("REGISTERID", "add", "__add")
|
|
||||||
mapsetkey("FUNCREG", "emit", "1")
|
|
||||||
mapsetkey("REGISTERID", "emit", "__emit")
|
|
||||||
mapsetkey("FUNCREG", "eq", "1")
|
|
||||||
mapsetkey("REGISTERID", "eq", "__eq")
|
|
||||||
mapsetkey("FUNCREG", "lt", "1")
|
|
||||||
mapsetkey("REGISTERID", "lt", "__lt")
|
|
||||||
mapsetkey("FUNCREG", "not", "1")
|
|
||||||
mapsetkey("REGISTERID", "not", "__not")
|
|
||||||
mapsetkey("FUNCREG", "mapclear", "1")
|
|
||||||
mapsetkey("REGISTERID", "mapclear", "__mapclear")
|
|
||||||
mapsetkey("FUNCREG", "mapgetkey", "1")
|
|
||||||
mapsetkey("REGISTERID", "mapgetkey", "__mapgetkey")
|
|
||||||
mapsetkey("FUNCREG", "mapsetkey", "1")
|
|
||||||
mapsetkey("REGISTERID", "mapsetkey", "__mapsetkey")
|
|
||||||
mapsetkey("FUNCREG", "peek", "1")
|
|
||||||
mapsetkey("REGISTERID", "peek", "__peek")
|
|
||||||
mapsetkey("FUNCREG", "skip", "1")
|
|
||||||
mapsetkey("REGISTERID", "skip", "__skip")
|
|
||||||
mapsetkey("FUNCREG", "stdincolno", "1")
|
|
||||||
mapsetkey("REGISTERID", "stdincolno", "__stdincolno")
|
|
||||||
mapsetkey("FUNCREG", "stdinlineno", "1")
|
|
||||||
mapsetkey("REGISTERID", "stdinlineno", "__stdinlineno")
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if eof == peek():
|
if eof == peek():
|
||||||
break
|
break
|
||||||
|
|||||||
@ -36,8 +36,5 @@ lang0py.py: lang0py.lang0 lang0py2.exe
|
|||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
-diff lang0py2.py lang0py.py
|
-diff lang0py2.py lang0py.py
|
||||||
|
|
||||||
$(LANG0PY): $(CURDIR)/../0-lang0py/lang0py.py $(CURDIR)/../0-lang0py/lang0py.lang0
|
|
||||||
cd ../0-lang0py && make lang0py.exe
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f lang0py*.py lang0py*.c lang0py*.o lang0py*.exe
|
rm -f lang0py*.py lang0py*.c lang0py*.o lang0py*.exe
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
registerid id:
|
skipchar exp:
|
||||||
declare idname
|
declare act
|
||||||
declare newidx
|
declare lineno
|
||||||
|
declare colno
|
||||||
calc idname mapgetkey "REGISTERID" id ""
|
calc act peek
|
||||||
if idname
|
calc lineno stdinlineno
|
||||||
return idname
|
calc colno stdincolno
|
||||||
/
|
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
||||||
|
skip
|
||||||
calc idname add "id_" id
|
|
||||||
return idname
|
|
||||||
/
|
/
|
||||||
|
|
||||||
emitln data:
|
emitln data:
|
||||||
@ -16,6 +14,14 @@ emitln data:
|
|||||||
emit eol
|
emit eol
|
||||||
/
|
/
|
||||||
|
|
||||||
|
increaseindent indent:
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
return indent
|
||||||
|
/
|
||||||
|
|
||||||
lexident:
|
lexident:
|
||||||
declare word
|
declare word
|
||||||
set word ""
|
set word ""
|
||||||
@ -29,28 +35,12 @@ lexident:
|
|||||||
if isafterz
|
if isafterz
|
||||||
break
|
break
|
||||||
/
|
/
|
||||||
calc word add word char
|
calc word addstringchar word char
|
||||||
skip
|
skip
|
||||||
/
|
/
|
||||||
return word
|
return word
|
||||||
/
|
/
|
||||||
|
|
||||||
skipchar exp:
|
|
||||||
declare act
|
|
||||||
declare lineno
|
|
||||||
declare colno
|
|
||||||
calc act peek
|
|
||||||
calc lineno stdinlineno
|
|
||||||
calc colno stdincolno
|
|
||||||
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
|
||||||
skip
|
|
||||||
/
|
|
||||||
|
|
||||||
increaseindent indent:
|
|
||||||
calc indent add indent " "
|
|
||||||
return indent
|
|
||||||
/
|
|
||||||
|
|
||||||
parseconststring:
|
parseconststring:
|
||||||
skipchar quote
|
skipchar quote
|
||||||
emit quote
|
emit quote
|
||||||
@ -73,15 +63,12 @@ parseconststring:
|
|||||||
|
|
||||||
parseexprvarref:
|
parseexprvarref:
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
calc varid registerid varname
|
emit varname
|
||||||
emit varid
|
|
||||||
/
|
/
|
||||||
|
|
||||||
parseexprcall:
|
parseexprcall:
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
calc funcid registerid funcname
|
emit funcname
|
||||||
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
|
|
||||||
emit funcid
|
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -113,18 +100,16 @@ parseexprcall:
|
|||||||
|
|
||||||
parsestatdeclare indent:
|
parsestatdeclare indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
skipchar eol
|
skipchar eol
|
||||||
/
|
/
|
||||||
|
|
||||||
parsestatset indent:
|
parsestatset indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit varid
|
emit var
|
||||||
emit " = "
|
emit " = "
|
||||||
parseconststring
|
parseconststring
|
||||||
emit eol
|
emit eol
|
||||||
@ -133,11 +118,10 @@ parsestatset indent:
|
|||||||
|
|
||||||
parsestatcalc indent:
|
parsestatcalc indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit varid
|
emit var
|
||||||
emit " = "
|
emit " = "
|
||||||
parseexprcall
|
parseexprcall
|
||||||
emit eol
|
emit eol
|
||||||
@ -176,7 +160,6 @@ parsestatreturn indent:
|
|||||||
emit "return "
|
emit "return "
|
||||||
calc char peek
|
calc char peek
|
||||||
calc isspace eq char " "
|
calc isspace eq char " "
|
||||||
calc isnotspace not isspace
|
|
||||||
if isspace
|
if isspace
|
||||||
skip
|
skip
|
||||||
calc char peek
|
calc char peek
|
||||||
@ -189,10 +172,6 @@ parsestatreturn indent:
|
|||||||
parseexprvarref
|
parseexprvarref
|
||||||
/
|
/
|
||||||
/
|
/
|
||||||
if isnotspace
|
|
||||||
emit quote
|
|
||||||
emit quote
|
|
||||||
/
|
|
||||||
emit eol
|
emit eol
|
||||||
skipchar eol
|
skipchar eol
|
||||||
/
|
/
|
||||||
@ -207,12 +186,11 @@ parsestatcheck indent:
|
|||||||
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit "__check("
|
emit "assert "
|
||||||
|
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
calc funcid registerid funcname
|
emit funcname
|
||||||
emit funcid
|
emit "("
|
||||||
emit ", ["
|
|
||||||
|
|
||||||
set notfirst ""
|
set notfirst ""
|
||||||
forever
|
forever
|
||||||
@ -242,8 +220,7 @@ parsestatcheck indent:
|
|||||||
|
|
||||||
skipchar ":"
|
skipchar ":"
|
||||||
|
|
||||||
emit "], ["
|
emit "), ("
|
||||||
|
|
||||||
set notfirst ""
|
set notfirst ""
|
||||||
|
|
||||||
forever
|
forever
|
||||||
@ -272,20 +249,19 @@ parsestatcheck indent:
|
|||||||
set notfirst "1"
|
set notfirst "1"
|
||||||
/
|
/
|
||||||
|
|
||||||
emitln "])"
|
emitln ")"
|
||||||
/
|
/
|
||||||
|
|
||||||
parsestattrace indent:
|
parsestattrace indent:
|
||||||
emit indent
|
emit indent
|
||||||
emit "__trace("
|
emit "trace("
|
||||||
emit quote
|
emit quote
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
calc varid registerid varname
|
|
||||||
emit varname
|
emit varname
|
||||||
emit quote
|
emit quote
|
||||||
emit ", "
|
emit ", "
|
||||||
emit varid
|
emit varname
|
||||||
emitln ")"
|
emitln ")"
|
||||||
skipchar eol
|
skipchar eol
|
||||||
/
|
/
|
||||||
@ -338,10 +314,8 @@ parsestat indent:
|
|||||||
parsestatcheck indent
|
parsestatcheck indent
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
check mapgetkey "FUNCREG" call "" : "Function" call "does not exist"
|
|
||||||
calc callid registerid call
|
|
||||||
emit indent
|
emit indent
|
||||||
emit callid
|
emit call
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -406,11 +380,9 @@ parseblock indent:
|
|||||||
|
|
||||||
parsefunc:
|
parsefunc:
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
calc funcid registerid funcname
|
|
||||||
trace funcname
|
trace funcname
|
||||||
mapsetkey "FUNCREG" funcname "1"
|
|
||||||
emit "def "
|
emit "def "
|
||||||
emit funcid
|
emit funcname
|
||||||
emit "("
|
emit "("
|
||||||
set isnotfirst ""
|
set isnotfirst ""
|
||||||
forever
|
forever
|
||||||
@ -421,12 +393,11 @@ parsefunc:
|
|||||||
break
|
break
|
||||||
/
|
/
|
||||||
skip
|
skip
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
if isnotfirst
|
if isnotfirst
|
||||||
emit ", "
|
emit ", "
|
||||||
/
|
/
|
||||||
emit varid
|
emit var
|
||||||
set isnotfirst "1"
|
set isnotfirst "1"
|
||||||
/
|
/
|
||||||
calc char peek
|
calc char peek
|
||||||
@ -450,31 +421,26 @@ emitheader:
|
|||||||
emitln "import os"
|
emitln "import os"
|
||||||
emitln "import sys"
|
emitln "import sys"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __eq(a: str, b: str) -> str:"
|
emitln "def eq(a, b):"
|
||||||
emitln " return '1' if a == b else ''"
|
emitln " return a == b"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __lt(a: str, b: str) -> str:"
|
emitln "def lt(a, b):"
|
||||||
emitln " return '1' if a < b else ''"
|
emitln " return a[0] < b[0]"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __not(a: str) -> str:"
|
emitln "def addstringchar(a, b):"
|
||||||
emitln " if a:"
|
emitln " return a + b[0]"
|
||||||
emitln " return ''"
|
|
||||||
emitln " return '1'"
|
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __add(a: str, b :str) -> str:"
|
emitln "def emit(string):"
|
||||||
emitln " return a + b"
|
emitln " sys.stdout.write(string)"
|
||||||
emitln ""
|
|
||||||
emitln "def __emit(string):"
|
|
||||||
emitln " sys.stdout.buffer.write(string.encode('latin_1'))"
|
|
||||||
emitln " sys.stdout.flush()"
|
emitln " sys.stdout.flush()"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __trace(header, value):"
|
emitln "def trace(header, value):"
|
||||||
emitln " if os.environ.get('TRACE'):"
|
emitln " if os.environ.get('TRACE'):"
|
||||||
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "__EOF = chr(0xFF)"
|
emitln "eof = chr(0)"
|
||||||
emitln "__EOL = chr(10)"
|
emitln "eol = chr(10)"
|
||||||
emitln "__QUOTE = chr(34)"
|
emitln "quote = chr(34)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "STDINCOLNO = 0"
|
emitln "STDINCOLNO = 0"
|
||||||
emitln "STDINLINENO = 1"
|
emitln "STDINLINENO = 1"
|
||||||
@ -482,105 +448,43 @@ emitheader:
|
|||||||
emitln ""
|
emitln ""
|
||||||
emitln "def _readchar():"
|
emitln "def _readchar():"
|
||||||
emitln " char = sys.stdin.read(1)"
|
emitln " char = sys.stdin.read(1)"
|
||||||
emitln " __trace('char', char)"
|
emitln " trace('char', char)"
|
||||||
emitln " if not char:"
|
emitln " if not char:"
|
||||||
emitln " return __EOF"
|
emitln " return eof"
|
||||||
emitln " return char"
|
emitln " return char"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __peek():"
|
emitln "def peek():"
|
||||||
emitln " return STDINPEEK"
|
emitln " return STDINPEEK"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __skip():"
|
emitln "def skip():"
|
||||||
emitln " global STDINCOLNO"
|
emitln " global STDINCOLNO"
|
||||||
emitln " global STDINLINENO"
|
emitln " global STDINLINENO"
|
||||||
emitln " global STDINPEEK"
|
emitln " global STDINPEEK"
|
||||||
emitln " if __EOL == STDINPEEK:"
|
emitln " if eol == STDINPEEK:"
|
||||||
emitln " STDINLINENO += 1"
|
emitln " STDINLINENO += 1"
|
||||||
emitln " STDINCOLNO = 0"
|
emitln " STDINCOLNO = 0"
|
||||||
emitln " STDINCOLNO += 1"
|
emitln " STDINCOLNO += 1"
|
||||||
emitln " STDINPEEK = _readchar()"
|
emitln " STDINPEEK = _readchar()"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __stdinlineno():"
|
emitln "def stdinlineno():"
|
||||||
emitln " global STDINLINENO"
|
emitln " global STDINLINENO"
|
||||||
emitln " return str(STDINLINENO)"
|
emitln " return str(STDINLINENO)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def __stdincolno():"
|
emitln "def stdincolno():"
|
||||||
emitln " global STDINCOLNO"
|
emitln " global STDINCOLNO"
|
||||||
emitln " return str(STDINCOLNO)"
|
emitln " return str(STDINCOLNO)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "__skip()"
|
emitln "skip()"
|
||||||
emitln ""
|
|
||||||
emitln ""
|
|
||||||
emitln "MAPSTORE = {}"
|
|
||||||
emitln ""
|
|
||||||
emitln "def __mapclear(mapname: str) -> str:"
|
|
||||||
emitln " MAPSTORE.pop(mapname)"
|
|
||||||
emitln " return ''"
|
|
||||||
emitln ""
|
|
||||||
emitln "def __mapgetkey(mapname: str, key: str, default: str) -> str:"
|
|
||||||
emitln " return MAPSTORE.get(mapname, {}).get(key, default)"
|
|
||||||
emitln ""
|
|
||||||
emitln "def __mapsetkey(mapname: str, key: str, value: str) -> str:"
|
|
||||||
emitln " MAPSTORE.setdefault(mapname, {})"
|
|
||||||
emitln " MAPSTORE[mapname][key] = value"
|
|
||||||
emitln " return ''"
|
|
||||||
emitln ""
|
|
||||||
emitln "def __check(func, args: list[str], msg: list[str]) -> None:"
|
|
||||||
emitln " result = func(*args)"
|
|
||||||
emitln " if result:"
|
|
||||||
emitln " return"
|
|
||||||
emitln ""
|
|
||||||
emitln " sys.stderr.write('ERROR: ' + ' '.join(msg) + '\\n')"
|
|
||||||
emitln " sys.stderr.flush()"
|
|
||||||
emitln " exit(1)"
|
|
||||||
emitln ""
|
|
||||||
emitln "# ### END OF RUNTIME ### #"
|
|
||||||
emitln ""
|
emitln ""
|
||||||
/
|
/
|
||||||
|
|
||||||
emitfooter:
|
emitfooter:
|
||||||
declare mainid
|
|
||||||
calc mainid registerid "main"
|
|
||||||
|
|
||||||
emitln "if __name__ == '__main__':"
|
emitln "if __name__ == '__main__':"
|
||||||
emit " "
|
emitln " main()"
|
||||||
emit mainid
|
|
||||||
emitln "()"
|
|
||||||
/
|
/
|
||||||
|
|
||||||
main:
|
main:
|
||||||
emitheader
|
emitheader
|
||||||
|
|
||||||
mapsetkey "REGISTERID" "eof" "__EOF"
|
|
||||||
mapsetkey "REGISTERID" "eol" "__EOL"
|
|
||||||
mapsetkey "REGISTERID" "quote" "__QUOTE"
|
|
||||||
|
|
||||||
mapsetkey "FUNCREG" "add" "1"
|
|
||||||
mapsetkey "REGISTERID" "add" "__add"
|
|
||||||
mapsetkey "FUNCREG" "emit" "1"
|
|
||||||
mapsetkey "REGISTERID" "emit" "__emit"
|
|
||||||
mapsetkey "FUNCREG" "eq" "1"
|
|
||||||
mapsetkey "REGISTERID" "eq" "__eq"
|
|
||||||
mapsetkey "FUNCREG" "lt" "1"
|
|
||||||
mapsetkey "REGISTERID" "lt" "__lt"
|
|
||||||
mapsetkey "FUNCREG" "not" "1"
|
|
||||||
mapsetkey "REGISTERID" "not" "__not"
|
|
||||||
mapsetkey "FUNCREG" "mapclear" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapclear" "__mapclear"
|
|
||||||
mapsetkey "FUNCREG" "mapgetkey" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapgetkey" "__mapgetkey"
|
|
||||||
mapsetkey "FUNCREG" "mapsetkey" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapsetkey" "__mapsetkey"
|
|
||||||
mapsetkey "FUNCREG" "peek" "1"
|
|
||||||
mapsetkey "REGISTERID" "peek" "__peek"
|
|
||||||
mapsetkey "FUNCREG" "skip" "1"
|
|
||||||
mapsetkey "REGISTERID" "skip" "__skip"
|
|
||||||
mapsetkey "FUNCREG" "stdincolno" "1"
|
|
||||||
mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
|
|
||||||
mapsetkey "FUNCREG" "stdinlineno" "1"
|
|
||||||
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
|
|
||||||
|
|
||||||
|
|
||||||
forever
|
forever
|
||||||
calc char peek
|
calc char peek
|
||||||
calc iseof eq char eof
|
calc iseof eq char eof
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
registerid id:
|
skipchar exp:
|
||||||
declare idname
|
declare act
|
||||||
declare newidx
|
declare lineno
|
||||||
|
declare colno
|
||||||
calc idname mapgetkey "REGISTERID" id ""
|
calc act peek
|
||||||
if idname
|
calc lineno stdinlineno
|
||||||
return idname
|
calc colno stdincolno
|
||||||
/
|
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
||||||
|
skip
|
||||||
calc idname add "id_" id
|
|
||||||
return idname
|
|
||||||
/
|
/
|
||||||
|
|
||||||
emitln data:
|
emitln data:
|
||||||
@ -16,6 +14,14 @@ emitln data:
|
|||||||
emit eol
|
emit eol
|
||||||
/
|
/
|
||||||
|
|
||||||
|
increaseindent indent:
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
calc indent addstringchar indent " "
|
||||||
|
return indent
|
||||||
|
/
|
||||||
|
|
||||||
lexident:
|
lexident:
|
||||||
declare char
|
declare char
|
||||||
declare isbeforea
|
declare isbeforea
|
||||||
@ -32,28 +38,12 @@ lexident:
|
|||||||
if isafterz
|
if isafterz
|
||||||
break
|
break
|
||||||
/
|
/
|
||||||
calc word add word char
|
calc word addstringchar word char
|
||||||
skip
|
skip
|
||||||
/
|
/
|
||||||
return word
|
return word
|
||||||
/
|
/
|
||||||
|
|
||||||
skipchar exp:
|
|
||||||
declare act
|
|
||||||
declare lineno
|
|
||||||
declare colno
|
|
||||||
calc act peek
|
|
||||||
calc lineno stdinlineno
|
|
||||||
calc colno stdincolno
|
|
||||||
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
|
||||||
skip
|
|
||||||
/
|
|
||||||
|
|
||||||
increaseindent indent:
|
|
||||||
calc indent add indent " "
|
|
||||||
return indent
|
|
||||||
/
|
|
||||||
|
|
||||||
parseconststring:
|
parseconststring:
|
||||||
declare char
|
declare char
|
||||||
declare iseof
|
declare iseof
|
||||||
@ -79,18 +69,16 @@ parseconststring:
|
|||||||
/
|
/
|
||||||
|
|
||||||
parseexprvarref:
|
parseexprvarref:
|
||||||
declare varid
|
|
||||||
declare varname
|
declare varname
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
calc varid registerid varname
|
emit "var_"
|
||||||
emit varid
|
emit varname
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
|
||||||
parseexprcall:
|
parseexprcall:
|
||||||
declare char
|
declare char
|
||||||
declare first
|
declare first
|
||||||
declare funcid
|
|
||||||
declare funcname
|
declare funcname
|
||||||
declare isspace
|
declare isspace
|
||||||
declare isnotspace
|
declare isnotspace
|
||||||
@ -99,9 +87,7 @@ parseexprcall:
|
|||||||
declare isquote
|
declare isquote
|
||||||
declare isnotquote
|
declare isnotquote
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
|
emit funcname
|
||||||
calc funcid registerid funcname
|
|
||||||
emit funcid
|
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -133,14 +119,12 @@ parseexprcall:
|
|||||||
/
|
/
|
||||||
|
|
||||||
parsestatdeclare indent:
|
parsestatdeclare indent:
|
||||||
declare varid
|
declare var
|
||||||
declare varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
emit indent
|
emit indent
|
||||||
emit "char * "
|
emit "char * var_"
|
||||||
emit varid
|
emit var
|
||||||
emit ";"
|
emit ";"
|
||||||
emit eol
|
emit eol
|
||||||
skipchar eol
|
skipchar eol
|
||||||
@ -148,14 +132,13 @@ parsestatdeclare indent:
|
|||||||
/
|
/
|
||||||
|
|
||||||
parsestatset indent:
|
parsestatset indent:
|
||||||
declare varid
|
declare var
|
||||||
declare varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit varid
|
emit "var_"
|
||||||
|
emit var
|
||||||
emit " = "
|
emit " = "
|
||||||
parseconststring
|
parseconststring
|
||||||
emit ";"
|
emit ";"
|
||||||
@ -165,14 +148,13 @@ parsestatset indent:
|
|||||||
/
|
/
|
||||||
|
|
||||||
parsestatcalc indent:
|
parsestatcalc indent:
|
||||||
declare varid
|
declare var
|
||||||
declare varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit varid
|
emit "var_"
|
||||||
|
emit var
|
||||||
emit " = "
|
emit " = "
|
||||||
parseexprcall
|
parseexprcall
|
||||||
emit ";"
|
emit ";"
|
||||||
@ -245,8 +227,7 @@ parsestatreturn indent:
|
|||||||
/
|
/
|
||||||
/
|
/
|
||||||
if isnotspace
|
if isnotspace
|
||||||
emit quote
|
emit "0"
|
||||||
emit quote
|
|
||||||
/
|
/
|
||||||
emit ";"
|
emit ";"
|
||||||
emit eol
|
emit eol
|
||||||
@ -256,7 +237,6 @@ parsestatreturn indent:
|
|||||||
|
|
||||||
parsestatcheck indent:
|
parsestatcheck indent:
|
||||||
declare char
|
declare char
|
||||||
declare funcid
|
|
||||||
declare funcname
|
declare funcname
|
||||||
declare iscolon
|
declare iscolon
|
||||||
declare iseol
|
declare iseol
|
||||||
@ -269,8 +249,7 @@ parsestatcheck indent:
|
|||||||
emit "if( 0 == strlen("
|
emit "if( 0 == strlen("
|
||||||
|
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
calc funcid registerid funcname
|
emit funcname
|
||||||
emit funcid
|
|
||||||
emit "("
|
emit "("
|
||||||
|
|
||||||
set notfirst ""
|
set notfirst ""
|
||||||
@ -305,7 +284,6 @@ parsestatcheck indent:
|
|||||||
emit indent
|
emit indent
|
||||||
emitln "{"
|
emitln "{"
|
||||||
|
|
||||||
emit indent
|
|
||||||
emit " fprintf(stderr, "
|
emit " fprintf(stderr, "
|
||||||
emit quote
|
emit quote
|
||||||
emit "%s"
|
emit "%s"
|
||||||
@ -343,14 +321,6 @@ parsestatcheck indent:
|
|||||||
/
|
/
|
||||||
/
|
/
|
||||||
|
|
||||||
emit indent
|
|
||||||
emit " fprintf(stderr, "
|
|
||||||
emit quote
|
|
||||||
emit "%s"
|
|
||||||
emit quote
|
|
||||||
emit ", __EOL"
|
|
||||||
emitln ");"
|
|
||||||
|
|
||||||
emit indent
|
emit indent
|
||||||
emitln " exit(1);"
|
emitln " exit(1);"
|
||||||
emit indent
|
emit indent
|
||||||
@ -358,18 +328,16 @@ parsestatcheck indent:
|
|||||||
/
|
/
|
||||||
|
|
||||||
parsestattrace indent:
|
parsestattrace indent:
|
||||||
declare varid
|
|
||||||
declare varname
|
declare varname
|
||||||
emit indent
|
emit indent
|
||||||
emit "__trace("
|
emit "trace("
|
||||||
emit quote
|
emit quote
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
calc varid registerid varname
|
|
||||||
emit varname
|
emit varname
|
||||||
emit quote
|
emit quote
|
||||||
emit ", "
|
emit ", var_"
|
||||||
emit varid
|
emit varname
|
||||||
emitln ");"
|
emitln ");"
|
||||||
skipchar eol
|
skipchar eol
|
||||||
return
|
return
|
||||||
@ -377,7 +345,6 @@ parsestattrace indent:
|
|||||||
|
|
||||||
parsestat indent:
|
parsestat indent:
|
||||||
declare call
|
declare call
|
||||||
declare callid
|
|
||||||
declare char
|
declare char
|
||||||
declare first
|
declare first
|
||||||
declare iscall
|
declare iscall
|
||||||
@ -434,10 +401,8 @@ parsestat indent:
|
|||||||
parsestattrace indent
|
parsestattrace indent
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
check mapgetkey "FUNCREG" call "" : "Function" call "does not exist"
|
|
||||||
calc callid registerid call
|
|
||||||
emit indent
|
emit indent
|
||||||
emit callid
|
emit call
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -451,17 +416,17 @@ parsestat indent:
|
|||||||
calc char peek
|
calc char peek
|
||||||
calc isquote eq char quote
|
calc isquote eq char quote
|
||||||
calc isnotquote not isquote
|
calc isnotquote not isquote
|
||||||
calc isfirst eq first "1"
|
|
||||||
calc isnotfirst not isfirst
|
|
||||||
if isnotfirst
|
|
||||||
emit ", "
|
|
||||||
/
|
|
||||||
if isquote
|
if isquote
|
||||||
parseconststring
|
parseconststring
|
||||||
/
|
/
|
||||||
if isnotquote
|
if isnotquote
|
||||||
parseexprvarref
|
parseexprvarref
|
||||||
/
|
/
|
||||||
|
calc isfirst eq first "1"
|
||||||
|
calc isnotfirst not isfirst
|
||||||
|
if isnotfirst
|
||||||
|
emit ", "
|
||||||
|
/
|
||||||
set first "0"
|
set first "0"
|
||||||
/
|
/
|
||||||
skipchar eol
|
skipchar eol
|
||||||
@ -511,23 +476,17 @@ parseblock indent:
|
|||||||
parsefunc:
|
parsefunc:
|
||||||
declare char
|
declare char
|
||||||
declare first
|
declare first
|
||||||
declare funcid
|
|
||||||
declare funcname
|
declare funcname
|
||||||
declare iseoblock
|
declare iseoblock
|
||||||
declare isfirst
|
declare isfirst
|
||||||
declare ismain
|
|
||||||
declare isnotmain
|
|
||||||
declare isspace
|
declare isspace
|
||||||
declare isnotfirst
|
declare isnotfirst
|
||||||
declare isnotspace
|
declare isnotspace
|
||||||
declare varid
|
declare var
|
||||||
declare varname
|
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
mapsetkey "FUNCREG" funcname "1"
|
|
||||||
calc funcid registerid funcname
|
|
||||||
trace funcname
|
trace funcname
|
||||||
emit "char * "
|
emit "char * "
|
||||||
emit funcid
|
emit funcname
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -538,15 +497,14 @@ parsefunc:
|
|||||||
break
|
break
|
||||||
/
|
/
|
||||||
skip
|
skip
|
||||||
calc varname lexident
|
calc var lexident
|
||||||
calc varid registerid varname
|
|
||||||
calc isfirst eq first "1"
|
calc isfirst eq first "1"
|
||||||
calc isnotfirst not isfirst
|
calc isnotfirst not isfirst
|
||||||
if isnotfirst
|
if isnotfirst
|
||||||
emit ", "
|
emit ", "
|
||||||
/
|
/
|
||||||
emit "char * "
|
emit "char * var_"
|
||||||
emit varid
|
emit var
|
||||||
set first "0"
|
set first "0"
|
||||||
/
|
/
|
||||||
calc char peek
|
calc char peek
|
||||||
@ -574,45 +532,45 @@ emitheader:
|
|||||||
emitln "#include <string.h>"
|
emitln "#include <string.h>"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char __EOF[2] = {0xFF, 0};"
|
emitln "char var_eof[2] = {-1, 0};"
|
||||||
emitln "char __EOL[2] = {10, 0};"
|
emitln "char var_eol[2] = {10, 0};"
|
||||||
emitln "char __QUOTE[2] = {34, 0};"
|
emitln "char var_quote[2] = {34, 0};"
|
||||||
emitln "char __FALSE[1] = {0};"
|
emitln "char var_false[1] = {0};"
|
||||||
emitln "char __TRUE[2] = {'1', 0};"
|
emitln "char var_true[2] = {'1', 0};"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __eq(char * a, char * b)"
|
emitln "char * eq(char * a, char * b)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " return (strcmp(a, b) == 0) ? __TRUE : __FALSE;"
|
emitln " return (strcmp(a, b) == 0) ? var_true : var_false;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __lt(char * a, char * b)"
|
emitln "char * lt(char * a, char * b)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " return (strcmp(a, b) < 0) ? __TRUE : __FALSE;"
|
emitln " return (strcmp(a, b) < 0) ? var_true : var_false;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln "char * __not(char * a)"
|
emitln "char * not(char * a)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " return (0 == strlen(a)) ? __TRUE : __FALSE;"
|
emitln " return (strcmp(a, var_true) != 0) ? var_true : var_false;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __add(char * lft, char * rgt)"
|
emitln "char * addstringchar(char * str, char * chr)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " int lft_len = strlen(lft);"
|
emitln " int str_len = strlen(str);"
|
||||||
emitln " int rgt_len = strlen(rgt);"
|
emitln " assert(strlen(chr) == 1);"
|
||||||
emitln " char * res = malloc((lft_len + rgt_len + 1) * sizeof(char));"
|
emitln " char * res = malloc((str_len + 2) * sizeof(char));"
|
||||||
emitln " strcpy(res, lft);"
|
emitln " strcpy(res, str);"
|
||||||
emitln " strcpy(res + lft_len, rgt);"
|
emitln " res[str_len + 0] = chr[0];"
|
||||||
emitln " res[lft_len + rgt_len] = 0;"
|
emitln " res[str_len + 1] = 0;"
|
||||||
emitln " return res;"
|
emitln " return res;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __emit(char * str)"
|
emitln "char * emit(char * str)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " fputs(str, stdout);"
|
emitln " fputs(str, stdout);"
|
||||||
emitln " return 0;"
|
emitln " return 0;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __trace(char * var_name, char * var_value)"
|
emitln "char * trace(char * var_name, char * var_value)"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emit " const char * env_trace = getenv("
|
emit " const char * env_trace = getenv("
|
||||||
emit quote
|
emit quote
|
||||||
@ -627,7 +585,7 @@ emitheader:
|
|||||||
emit quote
|
emit quote
|
||||||
emitln ", stderr);"
|
emitln ", stderr);"
|
||||||
emitln " fputs(var_value, stderr);"
|
emitln " fputs(var_value, stderr);"
|
||||||
emitln " fputs(__EOL, stderr);"
|
emitln " fputs(var_eol, stderr);"
|
||||||
emitln " return 0;"
|
emitln " return 0;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
@ -643,13 +601,13 @@ emitheader:
|
|||||||
emitln " return res;"
|
emitln " return res;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __peek()"
|
emitln "char * peek()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
|
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
|
||||||
emitln " return STDINPEEK;"
|
emitln " return STDINPEEK;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "void __skip()"
|
emitln "void skip()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
|
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
|
||||||
emitln " if( STDINPEEK[0] == 10 ) {"
|
emitln " if( STDINPEEK[0] == 10 ) {"
|
||||||
@ -660,7 +618,7 @@ emitheader:
|
|||||||
emitln " STDINPEEK = _readchar();"
|
emitln " STDINPEEK = _readchar();"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __stdinlineno()"
|
emitln "char * stdinlineno()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " char * res = malloc(8*sizeof(char));"
|
emitln " char * res = malloc(8*sizeof(char));"
|
||||||
emit " sprintf(res, "
|
emit " sprintf(res, "
|
||||||
@ -671,7 +629,7 @@ emitheader:
|
|||||||
emitln " return res;"
|
emitln " return res;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * __stdincolno()"
|
emitln "char * stdincolno()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " char * res = malloc(8*sizeof(char));"
|
emitln " char * res = malloc(8*sizeof(char));"
|
||||||
emit " sprintf(res, "
|
emit " sprintf(res, "
|
||||||
@ -682,137 +640,11 @@ emitheader:
|
|||||||
emitln " return res;"
|
emitln " return res;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "struct KEYVALUE"
|
|
||||||
emitln "{"
|
|
||||||
emitln " char * key;"
|
|
||||||
emitln " char * value;"
|
|
||||||
emitln " struct KEYVALUE * nextkeyvalue;"
|
|
||||||
emitln "};"
|
|
||||||
emitln ""
|
|
||||||
emitln "struct MAP"
|
|
||||||
emitln "{"
|
|
||||||
emitln " char * mapname;"
|
|
||||||
emitln " struct KEYVALUE * firstkeyvalue;"
|
|
||||||
emitln " struct MAP * nextmap;"
|
|
||||||
emitln "};"
|
|
||||||
emitln ""
|
|
||||||
emitln "struct MAP * MAPSTORE = 0;"
|
|
||||||
emitln ""
|
|
||||||
emitln "struct MAP * __map_get(char * mapname, int create)"
|
|
||||||
emitln "{"
|
|
||||||
emitln " struct MAP *prevmap, *map;"
|
|
||||||
emitln ""
|
|
||||||
emitln " prevmap = 0;"
|
|
||||||
emitln " map = MAPSTORE;"
|
|
||||||
emitln " while( map ) {"
|
|
||||||
emitln " if( strcmp(mapname, map->mapname) == 0) break;"
|
|
||||||
emitln " prevmap = map;"
|
|
||||||
emitln " map = map->nextmap;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " if( map ) {"
|
|
||||||
emitln " return map;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " if( !create ) {"
|
|
||||||
emitln " return 0;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " map = malloc(sizeof(struct MAP));"
|
|
||||||
emitln " map->mapname = mapname;"
|
|
||||||
emitln " map->firstkeyvalue = 0;"
|
|
||||||
emitln " map->nextmap = 0;"
|
|
||||||
emitln " if( prevmap == 0) {"
|
|
||||||
emitln " MAPSTORE = map;"
|
|
||||||
emitln " } else {"
|
|
||||||
emitln " prevmap->nextmap = map;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " return map;"
|
|
||||||
emitln "}"
|
|
||||||
emitln ""
|
|
||||||
emitln "struct KEYVALUE * __map_keyvalue_get(struct MAP * map, char * key, int create)"
|
|
||||||
emitln "{"
|
|
||||||
emitln " struct KEYVALUE *prevkeyvalue, *keyvalue;"
|
|
||||||
emitln ""
|
|
||||||
emitln " prevkeyvalue = 0;"
|
|
||||||
emitln " keyvalue = map->firstkeyvalue;"
|
|
||||||
emitln " while( keyvalue ) {"
|
|
||||||
emitln " if( strcmp(key, keyvalue->key) == 0) break;"
|
|
||||||
emitln " prevkeyvalue = keyvalue;"
|
|
||||||
emitln " keyvalue = keyvalue->nextkeyvalue;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " if( keyvalue ) {"
|
|
||||||
emitln " return keyvalue;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " if( !create ) {"
|
|
||||||
emitln " return 0;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " keyvalue = malloc(sizeof(struct KEYVALUE));"
|
|
||||||
emitln " keyvalue->key = key;"
|
|
||||||
emitln " keyvalue->nextkeyvalue = 0;"
|
|
||||||
emitln " if( prevkeyvalue == 0) {"
|
|
||||||
emitln " map->firstkeyvalue = keyvalue;"
|
|
||||||
emitln " } else {"
|
|
||||||
emitln " prevkeyvalue->nextkeyvalue = keyvalue;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emitln " return keyvalue;"
|
|
||||||
emitln "}"
|
|
||||||
emitln ""
|
|
||||||
emitln "char * __mapclear(char * mapname)"
|
|
||||||
emitln "{"
|
|
||||||
emitln " struct MAP * map = __map_get(mapname, 0);"
|
|
||||||
emitln " if( map ) {"
|
|
||||||
emitln " map->firstkeyvalue = 0;"
|
|
||||||
emitln " }"
|
|
||||||
emitln ""
|
|
||||||
emit " return "
|
|
||||||
emit quote
|
|
||||||
emit quote
|
|
||||||
emitln ";"
|
|
||||||
emitln "}"
|
|
||||||
emitln ""
|
|
||||||
emitln "char * __mapgetkey(char * mapname, char * key, char * def)"
|
|
||||||
emitln "{"
|
|
||||||
emitln " struct MAP * map = __map_get(mapname, 0);"
|
|
||||||
emitln " if( !map ) return def;"
|
|
||||||
emitln ""
|
|
||||||
emitln " struct KEYVALUE *keyvalue = __map_keyvalue_get(map, key, 0);"
|
|
||||||
emitln " if( !keyvalue ) return def;"
|
|
||||||
emitln ""
|
|
||||||
emitln " return keyvalue->value;"
|
|
||||||
emitln "}"
|
|
||||||
emitln ""
|
|
||||||
emitln "char * __mapsetkey(char * mapname, char * key, char * value)"
|
|
||||||
emitln "{"
|
|
||||||
emitln " struct MAP *map = __map_get(mapname, 1);"
|
|
||||||
emitln " struct KEYVALUE *keyvalue = __map_keyvalue_get(map, key, 1);"
|
|
||||||
emitln " keyvalue->value = value;"
|
|
||||||
emit " return "
|
|
||||||
emit quote
|
|
||||||
emit quote
|
|
||||||
emitln ";"
|
|
||||||
emitln "}"
|
|
||||||
emitln ""
|
|
||||||
emitln "// ### END OF RUNTIME ### //"
|
|
||||||
emitln ""
|
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
|
||||||
emitfooter:
|
emitfooter:
|
||||||
declare mainid
|
emit ""
|
||||||
calc mainid registerid "main"
|
|
||||||
|
|
||||||
emitln "int main() {"
|
|
||||||
emit " "
|
|
||||||
emit mainid
|
|
||||||
emitln "();"
|
|
||||||
emitln " return 0;"
|
|
||||||
emitln "}"
|
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
|
||||||
@ -821,38 +653,7 @@ main:
|
|||||||
declare iseof
|
declare iseof
|
||||||
declare iseol
|
declare iseol
|
||||||
declare isnoteol
|
declare isnoteol
|
||||||
|
|
||||||
emitheader
|
emitheader
|
||||||
|
|
||||||
mapsetkey "REGISTERID" "eof" "__EOF"
|
|
||||||
mapsetkey "REGISTERID" "eol" "__EOL"
|
|
||||||
mapsetkey "REGISTERID" "quote" "__QUOTE"
|
|
||||||
|
|
||||||
mapsetkey "FUNCREG" "add" "1"
|
|
||||||
mapsetkey "REGISTERID" "add" "__add"
|
|
||||||
mapsetkey "FUNCREG" "emit" "1"
|
|
||||||
mapsetkey "REGISTERID" "emit" "__emit"
|
|
||||||
mapsetkey "FUNCREG" "eq" "1"
|
|
||||||
mapsetkey "REGISTERID" "eq" "__eq"
|
|
||||||
mapsetkey "FUNCREG" "lt" "1"
|
|
||||||
mapsetkey "REGISTERID" "lt" "__lt"
|
|
||||||
mapsetkey "FUNCREG" "not" "1"
|
|
||||||
mapsetkey "REGISTERID" "not" "__not"
|
|
||||||
mapsetkey "FUNCREG" "mapclear" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapclear" "__mapclear"
|
|
||||||
mapsetkey "FUNCREG" "mapgetkey" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapgetkey" "__mapgetkey"
|
|
||||||
mapsetkey "FUNCREG" "mapsetkey" "1"
|
|
||||||
mapsetkey "REGISTERID" "mapsetkey" "__mapsetkey"
|
|
||||||
mapsetkey "FUNCREG" "peek" "1"
|
|
||||||
mapsetkey "REGISTERID" "peek" "__peek"
|
|
||||||
mapsetkey "FUNCREG" "skip" "1"
|
|
||||||
mapsetkey "REGISTERID" "skip" "__skip"
|
|
||||||
mapsetkey "FUNCREG" "stdincolno" "1"
|
|
||||||
mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
|
|
||||||
mapsetkey "FUNCREG" "stdinlineno" "1"
|
|
||||||
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
|
|
||||||
|
|
||||||
forever
|
forever
|
||||||
calc char peek
|
calc char peek
|
||||||
calc iseof eq char eof
|
calc iseof eq char eof
|
||||||
|
|||||||
39
README.md
39
README.md
@ -97,7 +97,7 @@ Exits the deepest `forever` loop.
|
|||||||
|
|
||||||
#### func args*
|
#### func args*
|
||||||
|
|
||||||
Calls the function name `func` with the given arguments. The return value is ignored.
|
Calls the function name `func` with the given arguments. The result, if any, is ignored.
|
||||||
|
|
||||||
#### if arg
|
#### if arg
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ Repeats the block until `break` or `return` is called.
|
|||||||
|
|
||||||
#### return var?
|
#### return var?
|
||||||
|
|
||||||
Returns the given value. If you don't give something to return, the function will return the empty string.
|
Returns the given value. You can not give an argument if your function is never used in `call`.
|
||||||
|
|
||||||
### Builtins
|
### Builtins
|
||||||
|
|
||||||
@ -121,23 +121,11 @@ Calls the given function with the given arguments. If the function's return valu
|
|||||||
|
|
||||||
Writes the name and value of the variable passed to stderr if the TRACE environment variable is set.
|
Writes the name and value of the variable passed to stderr if the TRACE environment variable is set.
|
||||||
|
|
||||||
### Standard library constants
|
|
||||||
|
|
||||||
#### eof
|
|
||||||
|
|
||||||
End of file character, zero byte.
|
|
||||||
|
|
||||||
#### eol
|
|
||||||
|
|
||||||
End of line character.
|
|
||||||
|
|
||||||
#### quote
|
|
||||||
|
|
||||||
Double quote character.
|
|
||||||
|
|
||||||
### Standard library functions
|
### Standard library functions
|
||||||
|
|
||||||
#### add a b
|
#### addstringchar a b
|
||||||
|
|
||||||
|
`b` is expected to have length 1.
|
||||||
|
|
||||||
Creates a new string with `b` appended to `a`.
|
Creates a new string with `b` appended to `a`.
|
||||||
|
|
||||||
@ -149,6 +137,13 @@ Writes the given string to standard output.
|
|||||||
|
|
||||||
Return true if the given strings are the same.
|
Return true if the given strings are the same.
|
||||||
|
|
||||||
|
#### intinc a
|
||||||
|
|
||||||
|
Available in it2 runtime and onwards.
|
||||||
|
|
||||||
|
Interprets string `a` as an integer, increases it by one and returns it (as a string).
|
||||||
|
If `a` cannot be interpreted as an integer, or has additional bytes, this function returns 1.
|
||||||
|
|
||||||
#### lt a b
|
#### lt a b
|
||||||
|
|
||||||
`a` and `b` are expected to have length 1.
|
`a` and `b` are expected to have length 1.
|
||||||
@ -157,12 +152,16 @@ Return true if a would sort before b.
|
|||||||
|
|
||||||
#### mapclear mapname
|
#### mapclear mapname
|
||||||
|
|
||||||
|
Available in it2 runtime and onwards.
|
||||||
|
|
||||||
Maps are global and can be used from any function.
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
Clears all values set in the map named `mapname`.
|
Clears all values set in the map named `mapname`.
|
||||||
|
|
||||||
#### mapgetkey mapname key
|
#### mapgetkey mapname key
|
||||||
|
|
||||||
|
Available in it2 runtime and onwards.
|
||||||
|
|
||||||
Maps are global and can be used from any function.
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
Looks up `key` in the map named `mapname` and returns it.
|
Looks up `key` in the map named `mapname` and returns it.
|
||||||
@ -170,14 +169,12 @@ If not found, returns an empty string.
|
|||||||
|
|
||||||
#### mapsetkey mapname key value
|
#### mapsetkey mapname key value
|
||||||
|
|
||||||
|
Available in it2 runtime and onwards.
|
||||||
|
|
||||||
Maps are global and can be used from any function.
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
Adds a mapping from `key` to `value` to the map named `mapname`.
|
Adds a mapping from `key` to `value` to the map named `mapname`.
|
||||||
|
|
||||||
#### not a
|
|
||||||
|
|
||||||
Returns "1" if a is empty; otherwise, returns "".
|
|
||||||
|
|
||||||
#### peek
|
#### peek
|
||||||
|
|
||||||
Checks stdin for the next character and returns it.
|
Checks stdin for the next character and returns it.
|
||||||
|
|||||||
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -1 +1 @@
|
|||||||
/Makefile.mk
|
/*.results
|
||||||
|
|||||||
@ -1,36 +1,38 @@
|
|||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
.PRECIOUS: build/%.it0.py build/%.it0.c
|
||||||
.DELETE_ON_ERROR:
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
PYVERSION=3.12
|
PYVERSION=3.12
|
||||||
PYPREFIX=/usr
|
PYPREFIX=/usr
|
||||||
CYTHON=cython3
|
CYTHON=cython3
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=-ggdb
|
|
||||||
|
|
||||||
all: verify-results
|
# builtincheckfalse is separate since it's supposed to crash. It's a test for the test 'framework', if you will.
|
||||||
|
TESTLIST=$(shell ls *.lang0 | grep -v 'builtincheckfalse' | sed 's/.lang0//')
|
||||||
|
|
||||||
Makefile.mk: generate-recipes.py $(wildcard test_*/test_*)
|
all: check
|
||||||
python3 generate-recipes.py Makefile.mk it0 it1 it2
|
|
||||||
|
|
||||||
include Makefile.mk
|
check: all-it0.results all-it1.results all-it2.results
|
||||||
|
! grep -v 'Success' $^
|
||||||
|
|
||||||
|
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST))) build/builtincheckfalse.it0
|
||||||
|
-rm -f $@
|
||||||
|
cat test-input.txt | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||||
|
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
|
||||||
|
|
||||||
|
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it1
|
||||||
|
-rm -f $@
|
||||||
|
cat test-input.txt | build/builtincheckfalse.it1 2> /dev/null 2>&1 | grep 'Success'
|
||||||
|
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
|
||||||
|
|
||||||
|
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it2
|
||||||
|
-rm -f $@
|
||||||
|
cat test-input.txt | build/builtincheckfalse.it2 2> /dev/null 2>&1 | grep 'Success'
|
||||||
|
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find build -name '*.c' -delete
|
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
||||||
find build -name '*.it0' -delete
|
|
||||||
find build -name '*.it0.result' -delete
|
|
||||||
find build -name '*.it0.stderr' -delete
|
|
||||||
find build -name '*.it0.stdout' -delete
|
|
||||||
find build -name '*.it1' -delete
|
|
||||||
find build -name '*.it1.result' -delete
|
|
||||||
find build -name '*.it1.stderr' -delete
|
|
||||||
find build -name '*.it1.stdout' -delete
|
|
||||||
find build -name '*.it2' -delete
|
|
||||||
find build -name '*.it2.result' -delete
|
|
||||||
find build -name '*.it2.stderr' -delete
|
|
||||||
find build -name '*.it2.stdout' -delete
|
|
||||||
find build -name '*.py' -delete
|
|
||||||
find build -name '*.tmp' -delete
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# it0
|
# it0
|
||||||
@ -39,17 +41,17 @@ clean:
|
|||||||
$(MAKE) -C ../0-lang0py
|
$(MAKE) -C ../0-lang0py
|
||||||
|
|
||||||
build/%.it0.py: %.lang0 ../0-lang0py/lang0py.exe
|
build/%.it0.py: %.lang0 ../0-lang0py/lang0py.exe
|
||||||
-cat $< | ../0-lang0py/lang0py.exe > $@.tmp 2> build/$*.it0.cmperr
|
cat $< | ../0-lang0py/lang0py.exe > $@.tmp
|
||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
|
|
||||||
build/%.it0.c: build/%.it0.py
|
build/%.it0.c: build/%.it0.py
|
||||||
$(CYTHON) -3 --embed -o $@ $^
|
$(CYTHON) -3 --embed -o $@ $^
|
||||||
|
|
||||||
build/%.it0.o: build/%.it0.c
|
build/%.it0.o: build/%.it0.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
||||||
|
|
||||||
build/%.it0: build/%.it0.o
|
build/%.it0: build/%.it0.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION)
|
$(CC) -o $@ $^ -lpython$(PYVERSION)
|
||||||
|
|
||||||
###
|
###
|
||||||
# it1
|
# it1
|
||||||
@ -58,17 +60,17 @@ build/%.it0: build/%.it0.o
|
|||||||
$(MAKE) -C ../1-lang0py
|
$(MAKE) -C ../1-lang0py
|
||||||
|
|
||||||
build/%.it1.py: %.lang0 ../1-lang0py/lang0py.exe
|
build/%.it1.py: %.lang0 ../1-lang0py/lang0py.exe
|
||||||
-cat $< | ../1-lang0py/lang0py.exe > $@.tmp 2> build/$*.it1.cmperr
|
cat $< | ../1-lang0py/lang0py.exe > $@.tmp
|
||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
|
|
||||||
build/%.it1.c: build/%.it1.py
|
build/%.it1.c: build/%.it1.py
|
||||||
$(CYTHON) -3 --embed -o $@ $^
|
$(CYTHON) -3 --embed -o $@ $^
|
||||||
|
|
||||||
build/%.it1.o: build/%.it1.c
|
build/%.it1.o: build/%.it1.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
||||||
|
|
||||||
build/%.it1: build/%.it1.o
|
build/%.it1: build/%.it1.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION)
|
$(CC) -o $@ $^ -lpython$(PYVERSION)
|
||||||
|
|
||||||
###
|
###
|
||||||
# it2
|
# it2
|
||||||
@ -77,11 +79,11 @@ build/%.it1: build/%.it1.o
|
|||||||
$(MAKE) -C ../2-lang0c
|
$(MAKE) -C ../2-lang0c
|
||||||
|
|
||||||
build/%.it2.c: %.lang0 ../2-lang0c/lang0c.exe
|
build/%.it2.c: %.lang0 ../2-lang0c/lang0c.exe
|
||||||
-cat $< | ../2-lang0c/lang0c.exe > $@.tmp 2> build/$*.it2.cmperr
|
cat $< | ../2-lang0c/lang0c.exe > $@.tmp
|
||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
|
|
||||||
build/%.it2.o: build/%.it2.c
|
build/%.it2.o: build/%.it2.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
||||||
|
|
||||||
build/%.it2: build/%.it2.o
|
build/%.it2: build/%.it2.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION)
|
$(CC) -o $@ $^ -lpython$(PYVERSION)
|
||||||
|
|||||||
14
tests/build/.gitignore
vendored
Normal file
14
tests/build/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*.it0
|
||||||
|
/*.it0.c
|
||||||
|
/*.it0.o
|
||||||
|
/*.it0.py
|
||||||
|
/*.it0.py.tmp
|
||||||
|
/*.it1
|
||||||
|
/*.it1.c
|
||||||
|
/*.it1.o
|
||||||
|
/*.it1.py
|
||||||
|
/*.it1.py.tmp
|
||||||
|
/*.it2
|
||||||
|
/*.it2.c
|
||||||
|
/*.it2.c.tmp
|
||||||
|
/*.it2.o
|
||||||
26
tests/build/test_builtins/.gitignore
vendored
26
tests/build/test_builtins/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_flow_control/.gitignore
vendored
26
tests/build/test_flow_control/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_parsing/.gitignore
vendored
26
tests/build/test_parsing/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_stdlib_constants/.gitignore
vendored
26
tests/build/test_stdlib_constants/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_stdlib_functions/.gitignore
vendored
26
tests/build/test_stdlib_functions/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_validation/.gitignore
vendored
26
tests/build/test_validation/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
26
tests/build/test_variables/.gitignore
vendored
26
tests/build/test_variables/.gitignore
vendored
@ -1,26 +0,0 @@
|
|||||||
/*.it0
|
|
||||||
/*.it0.c
|
|
||||||
/*.it0.cmperr
|
|
||||||
/*.it0.o
|
|
||||||
/*.it0.py
|
|
||||||
/*.it0.py.tmp
|
|
||||||
/*.it0.result
|
|
||||||
/*.it0.stderr
|
|
||||||
/*.it0.stdout
|
|
||||||
/*.it1
|
|
||||||
/*.it1.c
|
|
||||||
/*.it1.cmperr
|
|
||||||
/*.it1.o
|
|
||||||
/*.it1.py
|
|
||||||
/*.it1.py.tmp
|
|
||||||
/*.it1.result
|
|
||||||
/*.it1.stderr
|
|
||||||
/*.it1.stdout
|
|
||||||
/*.it2
|
|
||||||
/*.it2.c
|
|
||||||
/*.it2.cmperr
|
|
||||||
/*.it2.c.tmp
|
|
||||||
/*.it2.o
|
|
||||||
/*.it2.result
|
|
||||||
/*.it2.stderr
|
|
||||||
/*.it2.stdout
|
|
||||||
3
tests/builtincheckfalse.lang0
Normal file
3
tests/builtincheckfalse.lang0
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
main:
|
||||||
|
check not "1" : "Success"
|
||||||
|
/
|
||||||
4
tests/builtinchecktrue.lang0
Normal file
4
tests/builtinchecktrue.lang0
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
main:
|
||||||
|
check not "" : "Failure"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
@ -1,7 +1,6 @@
|
|||||||
main:
|
main:
|
||||||
forever
|
forever
|
||||||
emit "Suc"
|
|
||||||
break
|
break
|
||||||
/
|
/
|
||||||
emit "cess"
|
emit "Success"
|
||||||
/
|
/
|
||||||
8
tests/flowiffalse.lang0
Normal file
8
tests/flowiffalse.lang0
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
set bool ""
|
||||||
|
if bool
|
||||||
|
return
|
||||||
|
/
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
7
tests/flowiftrue.lang0
Normal file
7
tests/flowiftrue.lang0
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
set bool "1"
|
||||||
|
if bool
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
|
/
|
||||||
8
tests/flowreturnnothing.lang0
Normal file
8
tests/flowreturnnothing.lang0
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
func:
|
||||||
|
return
|
||||||
|
/
|
||||||
|
|
||||||
|
main:
|
||||||
|
func
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
11
tests/flowreturnvalue.lang0
Normal file
11
tests/flowreturnvalue.lang0
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
func:
|
||||||
|
declare result
|
||||||
|
set result "Success"
|
||||||
|
return result
|
||||||
|
/
|
||||||
|
|
||||||
|
main:
|
||||||
|
declare result
|
||||||
|
calc result func
|
||||||
|
emit result
|
||||||
|
/
|
||||||
9
tests/flowreturnvalueconstant.lang0
Normal file
9
tests/flowreturnvalueconstant.lang0
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
func:
|
||||||
|
return "Success"
|
||||||
|
/
|
||||||
|
|
||||||
|
main:
|
||||||
|
declare result
|
||||||
|
calc result func
|
||||||
|
emit result
|
||||||
|
/
|
||||||
@ -1,122 +0,0 @@
|
|||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
STAGE0_MAP = {
|
|
||||||
'it0': '.py',
|
|
||||||
'it1': '.py',
|
|
||||||
'it2': '.c',
|
|
||||||
}
|
|
||||||
|
|
||||||
class Rule:
|
|
||||||
def __init__(self, target: str, prerequisites: list[str], recipe: list[str]) -> None:
|
|
||||||
self.target = target
|
|
||||||
self.prerequisites = prerequisites
|
|
||||||
self.recipe = recipe
|
|
||||||
|
|
||||||
def make_lines(self):
|
|
||||||
return [
|
|
||||||
self.target + ': ' + ' '.join(self.prerequisites),
|
|
||||||
] + [
|
|
||||||
'\t' + line
|
|
||||||
for line in self.recipe
|
|
||||||
] + ['']
|
|
||||||
|
|
||||||
def get_file_list():
|
|
||||||
return sorted(glob.glob('test_*/*.lang0'))
|
|
||||||
|
|
||||||
def make_rules(file_path, lang0it):
|
|
||||||
result: list[Rule] = []
|
|
||||||
|
|
||||||
stdin = file_path.replace('.lang0', '.stdin')
|
|
||||||
exp_cmperr = file_path.replace('.lang0', '.exp.cmperr')
|
|
||||||
exp_stderr = file_path.replace('.lang0', '.exp.stderr')
|
|
||||||
exp_stdout = file_path.replace('.lang0', '.exp.stdout')
|
|
||||||
|
|
||||||
act_cmperr = 'build/' + file_path.replace('.lang0', f'.{lang0it}.cmperr')
|
|
||||||
|
|
||||||
act_stderr = 'build/' + file_path.replace('.lang0', f'.{lang0it}.stderr')
|
|
||||||
act_stdout = 'build/' + file_path.replace('.lang0', f'.{lang0it}.stdout')
|
|
||||||
|
|
||||||
act_result = 'build/' + file_path.replace('.lang0', f'.{lang0it}.result')
|
|
||||||
program = 'build/' + file_path.replace('.lang0', f'.{lang0it}')
|
|
||||||
|
|
||||||
program_stage0 = program + STAGE0_MAP[lang0it]
|
|
||||||
|
|
||||||
if os.path.isfile(exp_cmperr):
|
|
||||||
# No need to try to run the program
|
|
||||||
exp_list = [exp_cmperr]
|
|
||||||
act_list = [act_cmperr]
|
|
||||||
elif os.path.isfile(exp_stdout) or os.path.isfile(exp_stderr):
|
|
||||||
result.append(Rule(
|
|
||||||
act_stdout,
|
|
||||||
[program] + ([stdin] if os.path.isfile(stdin) else []),
|
|
||||||
[
|
|
||||||
'-' + (f'cat {stdin} | ' if os.path.isfile(stdin) else 'echo x | ')
|
|
||||||
+ f'{program} 1> {act_stdout} 2> {act_stderr}',
|
|
||||||
]
|
|
||||||
))
|
|
||||||
|
|
||||||
exp_list = [exp_stdout, exp_stderr]
|
|
||||||
act_list = [act_stdout, act_stderr]
|
|
||||||
else:
|
|
||||||
assert False, f'Missing expectations for {file_path}'
|
|
||||||
|
|
||||||
result.append(Rule(
|
|
||||||
act_result,
|
|
||||||
([program_stage0] if os.path.isfile(exp_cmperr) else [act_stdout]) + [
|
|
||||||
x
|
|
||||||
for x in exp_list
|
|
||||||
if os.path.isfile(x)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'rm -f $@',
|
|
||||||
] + [
|
|
||||||
f'-diff {exp_file} {act_file} >> $@'
|
|
||||||
for exp_file, act_file in zip(exp_list, act_list, strict=True)
|
|
||||||
if os.path.isfile(exp_file)
|
|
||||||
] + [
|
|
||||||
f'-diff /dev/null {act_file} >> $@'
|
|
||||||
for exp_file, act_file in zip(exp_list, act_list, strict=True)
|
|
||||||
if not os.path.isfile(exp_file)
|
|
||||||
]
|
|
||||||
))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def main(program, write_to, *lang0it):
|
|
||||||
rule_list_list = [
|
|
||||||
make_rules(file_path, it)
|
|
||||||
for file_path in get_file_list()
|
|
||||||
for it in lang0it
|
|
||||||
]
|
|
||||||
|
|
||||||
result_targets = [
|
|
||||||
rule.target
|
|
||||||
for rule_list in rule_list_list
|
|
||||||
for rule in rule_list
|
|
||||||
if rule.target.endswith('.result')
|
|
||||||
]
|
|
||||||
|
|
||||||
rule_list_list.append([Rule(
|
|
||||||
'verify-results',
|
|
||||||
result_targets,
|
|
||||||
[
|
|
||||||
'@echo Finding failed test results...',
|
|
||||||
'@find $^ -not -empty -print -exec false {} +',
|
|
||||||
'@echo All tests passed.'
|
|
||||||
]
|
|
||||||
)])
|
|
||||||
|
|
||||||
data = '\n'.join(
|
|
||||||
line
|
|
||||||
for rule_list in rule_list_list
|
|
||||||
for rule in rule_list
|
|
||||||
for line in rule.make_lines()
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(write_to, 'wt', encoding='ASCII') as fil:
|
|
||||||
fil.write(data)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main(*sys.argv)
|
|
||||||
10
tests/parsingpredeclaredfunction0.lang0
Normal file
10
tests/parsingpredeclaredfunction0.lang0
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
func/
|
||||||
|
|
||||||
|
main:
|
||||||
|
check func : "The function should return 1, even though it is not defined yet"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
|
|
||||||
|
func:
|
||||||
|
return "1"
|
||||||
|
/
|
||||||
10
tests/parsingpredeclaredfunction1.lang0
Normal file
10
tests/parsingpredeclaredfunction1.lang0
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
func arg/
|
||||||
|
|
||||||
|
main:
|
||||||
|
check func "1" : "The function should return 1, even though it is not defined yet"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
|
|
||||||
|
func arg:
|
||||||
|
return arg
|
||||||
|
/
|
||||||
86
tests/stdinlineno.lang0
Normal file
86
tests/stdinlineno.lang0
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
main:
|
||||||
|
declare char
|
||||||
|
declare colno
|
||||||
|
declare lineno
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "H" : "Read: H" char
|
||||||
|
check eq colno "1" : "The column number should not have advanced yet" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "e" : "Read: e" char
|
||||||
|
check eq colno "2" : "The column number should have been advanced by 1" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "l" : "Read: l" char
|
||||||
|
check eq colno "3" : "The column number should have been advanced by 2" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "l" : "Read: l" char
|
||||||
|
check eq colno "4" : "The column number should have been advanced by 3" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "o" : "Read: o" char
|
||||||
|
check eq colno "5" : "The column number should have been advanced by 4" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "!" : "Read: !" char
|
||||||
|
check eq colno "6" : "The column number should have been advanced by 5" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char eol : "Read: eol" char
|
||||||
|
check eq colno "7" : "The column number should have been advanced by 6" colno
|
||||||
|
check eq lineno "1" : "The line number should not have advanced yet" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char eol : "Read: eol" char
|
||||||
|
check eq colno "1" : "The column number should have been reset" colno
|
||||||
|
check eq lineno "2" : "The line number should have advanced by 1" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "T" : "Read: T" char
|
||||||
|
check eq colno "1" : "The column number should have been reset again" colno
|
||||||
|
check eq lineno "3" : "The line number should have advanced by 2" lineno
|
||||||
|
skip
|
||||||
|
|
||||||
|
calc char peek
|
||||||
|
calc colno stdincolno
|
||||||
|
calc lineno stdinlineno
|
||||||
|
check eq char "h" : "Read: h" char
|
||||||
|
check eq colno "2" : "The line number should not have been advanced by 1" colno
|
||||||
|
check eq lineno "3" : "The line number should not have advanced further" lineno
|
||||||
|
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
6
tests/stdlibaddstringchar.lang0
Normal file
6
tests/stdlibaddstringchar.lang0
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
main:
|
||||||
|
declare result
|
||||||
|
calc result addstringchar "abc" "d"
|
||||||
|
check eq result "abcd" : "Adding abc and d should be abcd"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
3
tests/stdlibemit.lang0
Normal file
3
tests/stdlibemit.lang0
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
main:
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
6
tests/stdlibeqfalse.lang0
Normal file
6
tests/stdlibeqfalse.lang0
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
calc bool eq "1" "2"
|
||||||
|
check not bool : "1 should not equal 2"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
5
tests/stdlibeqtrue.lang0
Normal file
5
tests/stdlibeqtrue.lang0
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
check eq "1" "1" : "1 should equal 1"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
6
tests/stdlibltfalse.lang0
Normal file
6
tests/stdlibltfalse.lang0
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
calc bool lt "b" "a"
|
||||||
|
check not bool : "a should should sort before b"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
5
tests/stdliblttrue.lang0
Normal file
5
tests/stdliblttrue.lang0
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
main:
|
||||||
|
declare bool
|
||||||
|
check lt "a" "b" : "a should should sort before b"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
6
tests/stdlibpeek.lang0
Normal file
6
tests/stdlibpeek.lang0
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
main:
|
||||||
|
declare char
|
||||||
|
calc char peek
|
||||||
|
check eq char "H" : "The first byte we're passed is expected to be an 'H'"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
12
tests/stdlibskip.lang0
Normal file
12
tests/stdlibskip.lang0
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
main:
|
||||||
|
declare char
|
||||||
|
skip
|
||||||
|
calc char peek
|
||||||
|
check eq char "e" : "The second byte we're passed is expected to be an 'e'"
|
||||||
|
skip
|
||||||
|
skip
|
||||||
|
skip
|
||||||
|
calc char peek
|
||||||
|
check eq char "o" : "The fifth byte we're passed is expected to be an 'o'"
|
||||||
|
emit "Success"
|
||||||
|
/
|
||||||
3
tests/test-input.txt
Normal file
3
tests/test-input.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Hello!
|
||||||
|
|
||||||
|
This is an example of standard input.
|
||||||
@ -1 +0,0 @@
|
|||||||
ERROR: Check failed successfully
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Still alive
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
main:
|
|
||||||
check not "" : "This should not trigger"
|
|
||||||
emit "Still alive"
|
|
||||||
emit eol
|
|
||||||
check not "1" : "Check failed successfully"
|
|
||||||
emit "This should not be output"
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Success
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Success
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
1 is true
|
|
||||||
A is true
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
main:
|
|
||||||
declare bool
|
|
||||||
set bool ""
|
|
||||||
if bool
|
|
||||||
emit "empty string is true"
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
set bool "1"
|
|
||||||
if bool
|
|
||||||
emit "1 is true"
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
set bool "A"
|
|
||||||
if bool
|
|
||||||
emit "A is true"
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
/
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
funca Constant
|
|
||||||
funcb Variable
|
|
||||||
funcc
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
funca:
|
|
||||||
return "Constant"
|
|
||||||
/
|
|
||||||
|
|
||||||
funcb:
|
|
||||||
declare var
|
|
||||||
set var "Variable"
|
|
||||||
return var
|
|
||||||
/
|
|
||||||
|
|
||||||
funcc:
|
|
||||||
return
|
|
||||||
/
|
|
||||||
|
|
||||||
main:
|
|
||||||
declare var
|
|
||||||
|
|
||||||
calc var funca
|
|
||||||
emit "funca "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
calc var funcb
|
|
||||||
emit "funcb "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
calc var funcc
|
|
||||||
emit "funcc "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
Predeclared without argument: 1
|
|
||||||
Predeclared with argument: 2
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
funca/
|
|
||||||
funcb arg/
|
|
||||||
|
|
||||||
main:
|
|
||||||
declare var
|
|
||||||
|
|
||||||
calc var funca
|
|
||||||
emit "Predeclared without argument: "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
calc var funcb "2"
|
|
||||||
emit "Predeclared with argument: "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
|
|
||||||
funca:
|
|
||||||
return "1"
|
|
||||||
/
|
|
||||||
|
|
||||||
funcb arg:
|
|
||||||
return arg
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
11
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
main:
|
|
||||||
declare assert
|
|
||||||
declare class
|
|
||||||
set assert "1"
|
|
||||||
set class "1"
|
|
||||||
emit assert
|
|
||||||
emit class
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<EFBFBD>
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
main:
|
|
||||||
emit eof
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
main:
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
"
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
main:
|
|
||||||
emit quote
|
|
||||||
/
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
1 + 2 = 12
|
|
||||||
10 + 20 = 1020
|
|
||||||
101 + 202 = 101202
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
func tst a b:
|
|
||||||
declare var
|
|
||||||
calc var add a b
|
|
||||||
emit a
|
|
||||||
emit " + "
|
|
||||||
emit b
|
|
||||||
emit " = "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
|
|
||||||
main:
|
|
||||||
declare var
|
|
||||||
|
|
||||||
calc var add "1" "2"
|
|
||||||
emit "1 + 2 = "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
calc var add "10" "20"
|
|
||||||
emit "10 + 20 = "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
calc var add "101" "202"
|
|
||||||
emit "101 + 202 = "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Hello, world!
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
main:
|
|
||||||
emit "Hello"
|
|
||||||
emit ", world!"
|
|
||||||
/
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
eq A A: 1
|
|
||||||
eq A B:
|
|
||||||
eq AA AA: 1
|
|
||||||
eq AA AB:
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
main:
|
|
||||||
declare result
|
|
||||||
emit "eq A A: "
|
|
||||||
calc result eq "A" "A"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "eq A B: "
|
|
||||||
calc result eq "A" "B"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "eq AA AA: "
|
|
||||||
calc result eq "AA" "AA"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "eq AA AB: "
|
|
||||||
calc result eq "AA" "AB"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
lt A A:
|
|
||||||
lt A B: 1
|
|
||||||
lt B A:
|
|
||||||
lt AA AA:
|
|
||||||
lt AA AB: 1
|
|
||||||
lt AB AA:
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
main:
|
|
||||||
declare result
|
|
||||||
emit "lt A A: "
|
|
||||||
calc result lt "A" "A"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "lt A B: "
|
|
||||||
calc result lt "A" "B"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "lt B A: "
|
|
||||||
calc result lt "B" "A"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "lt AA AA: "
|
|
||||||
calc result lt "AA" "AA"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "lt AA AB: "
|
|
||||||
calc result lt "AA" "AB"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
emit "lt AB AA: "
|
|
||||||
calc result lt "AB" "AA"
|
|
||||||
emit result
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
TESTMAP.abc0: def
|
|
||||||
OTHERMAP.abc0: def
|
|
||||||
TESTMAP.abc0: blue
|
|
||||||
TESTMAP.abc1: green
|
|
||||||
TESTMAP.abc2: def
|
|
||||||
OTHERMAP.abc0: blue
|
|
||||||
OTHERMAP.abc1: green
|
|
||||||
OTHERMAP.abc2: def
|
|
||||||
TESTMAP.abc0: def
|
|
||||||
TESTMAP.abc1: def
|
|
||||||
TESTMAP.abc2: def
|
|
||||||
OTHERMAP.abc0: blue
|
|
||||||
OTHERMAP.abc1: green
|
|
||||||
OTHERMAP.abc2: def
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
print mapname key:
|
|
||||||
declare value
|
|
||||||
calc value mapgetkey mapname key "def"
|
|
||||||
emit mapname
|
|
||||||
emit "."
|
|
||||||
emit key
|
|
||||||
emit ": "
|
|
||||||
emit value
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
|
|
||||||
main:
|
|
||||||
print "TESTMAP" "abc0"
|
|
||||||
print "OTHERMAP" "abc0"
|
|
||||||
|
|
||||||
mapsetkey "TESTMAP" "abc0" "blue"
|
|
||||||
mapsetkey "TESTMAP" "abc1" "green"
|
|
||||||
mapsetkey "OTHERMAP" "abc0" "blue"
|
|
||||||
mapsetkey "OTHERMAP" "abc1" "green"
|
|
||||||
|
|
||||||
print "TESTMAP" "abc0"
|
|
||||||
print "TESTMAP" "abc1"
|
|
||||||
print "TESTMAP" "abc2"
|
|
||||||
print "OTHERMAP" "abc0"
|
|
||||||
print "OTHERMAP" "abc1"
|
|
||||||
print "OTHERMAP" "abc2"
|
|
||||||
|
|
||||||
mapclear "TESTMAP"
|
|
||||||
|
|
||||||
print "TESTMAP" "abc0"
|
|
||||||
print "TESTMAP" "abc1"
|
|
||||||
print "TESTMAP" "abc2"
|
|
||||||
print "OTHERMAP" "abc0"
|
|
||||||
print "OTHERMAP" "abc1"
|
|
||||||
print "OTHERMAP" "abc2"
|
|
||||||
/
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
not == 1
|
|
||||||
not a ==
|
|
||||||
not 1 ==
|
|
||||||
not -1 ==
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
test a:
|
|
||||||
declare var
|
|
||||||
calc var not a
|
|
||||||
emit "not "
|
|
||||||
emit a
|
|
||||||
emit " == "
|
|
||||||
emit var
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
|
|
||||||
main:
|
|
||||||
test ""
|
|
||||||
test "a"
|
|
||||||
test "1"
|
|
||||||
test "-1"
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
AAA
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
main:
|
|
||||||
declare char
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ABC
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ABD
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
main:
|
|
||||||
declare char
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
skip
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
skip
|
|
||||||
skip
|
|
||||||
calc char peek
|
|
||||||
emit char
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ABCD
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
"A" 1
|
|
||||||
"
|
|
||||||
" 2
|
|
||||||
"B" 1
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
main:
|
|
||||||
declare char
|
|
||||||
declare colno
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc colno stdincolno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit colno
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
skip
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc colno stdincolno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit colno
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
skip
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc colno stdincolno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit colno
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
A
|
|
||||||
B
|
|
||||||
C
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
"A" 1
|
|
||||||
"
|
|
||||||
" 1
|
|
||||||
"B" 2
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
main:
|
|
||||||
declare char
|
|
||||||
declare lineno
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc lineno stdinlineno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit lineno
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
skip
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc lineno stdinlineno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit lineno
|
|
||||||
emit eol
|
|
||||||
|
|
||||||
skip
|
|
||||||
|
|
||||||
calc char peek
|
|
||||||
calc lineno stdinlineno
|
|
||||||
emit quote
|
|
||||||
emit char
|
|
||||||
emit quote
|
|
||||||
emit " "
|
|
||||||
emit lineno
|
|
||||||
emit eol
|
|
||||||
/
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
A
|
|
||||||
B
|
|
||||||
C
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ERROR: Function funca does not exist
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
main:
|
|
||||||
declare var
|
|
||||||
calc var funca "1"
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ERROR: Function routine does not exist
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
main:
|
|
||||||
routine "1"
|
|
||||||
/
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Success
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Success
|
|
||||||
Loading…
x
Reference in New Issue
Block a user