Compare commits
8 Commits
05eb2d3be7
...
c318c780da
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c318c780da | ||
|
|
1b8333fcfa | ||
|
|
2eaa763a2c | ||
|
|
ed09d37213 | ||
|
|
a184d4c5e3 | ||
|
|
5fa042c5cd | ||
|
|
931a861fef | ||
|
|
7568a15093 |
@ -1,6 +1,6 @@
|
||||
.SUFFIXES:
|
||||
|
||||
PYVERSION=3.10
|
||||
PYVERSION=3.12
|
||||
PYPREFIX=/usr
|
||||
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
||||
CYTHON=cython3
|
||||
|
||||
@ -3,6 +3,7 @@ import sys
|
||||
|
||||
def emit(string):
|
||||
sys.stdout.write(string)
|
||||
sys.stdout.flush()
|
||||
|
||||
def trace(header, value):
|
||||
if os.environ.get('TRACE'):
|
||||
@ -38,11 +39,6 @@ def skip():
|
||||
|
||||
PEEK = None
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def emitln(data):
|
||||
emit(data)
|
||||
emit(eol)
|
||||
@ -60,6 +56,11 @@ def lexident():
|
||||
|
||||
return word
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def parseconststring():
|
||||
skipchar(quote)
|
||||
emit(quote)
|
||||
@ -161,10 +162,60 @@ def parsestatreturn(indent):
|
||||
emit('return ')
|
||||
if ' ' == peek():
|
||||
skip()
|
||||
parseexprvarref()
|
||||
if quote == peek():
|
||||
parseconststring()
|
||||
else:
|
||||
parseexprvarref()
|
||||
emit(eol)
|
||||
skipchar(eol)
|
||||
|
||||
def parsestatcheck(indent):
|
||||
skipchar(' ')
|
||||
emit(' ' * indent)
|
||||
emit('assert ')
|
||||
|
||||
func_name = lexident()
|
||||
emit(func_name)
|
||||
emit('(')
|
||||
notfirst = False
|
||||
|
||||
while True:
|
||||
skipchar(' ')
|
||||
|
||||
if ':' == peek():
|
||||
break
|
||||
|
||||
if notfirst:
|
||||
emit(', ')
|
||||
|
||||
if quote == peek():
|
||||
parseconststring()
|
||||
else:
|
||||
parseexprvarref()
|
||||
|
||||
notfirst = True
|
||||
|
||||
skipchar(':')
|
||||
|
||||
emit('), (')
|
||||
notfirst = False
|
||||
|
||||
while True:
|
||||
skipchar(' ')
|
||||
|
||||
if notfirst:
|
||||
emit(', ')
|
||||
|
||||
if quote == peek():
|
||||
parseconststring()
|
||||
else:
|
||||
parseexprvarref()
|
||||
|
||||
if eol == peek():
|
||||
break
|
||||
notfirst = True
|
||||
emitln(')')
|
||||
|
||||
def parsestattrace(indent):
|
||||
skipchar(' ')
|
||||
emit(' ' * indent)
|
||||
@ -210,6 +261,10 @@ def parsestat(indent):
|
||||
parsestatreturn(indent)
|
||||
return
|
||||
|
||||
if call == "check":
|
||||
parsestatcheck(indent)
|
||||
return
|
||||
|
||||
if call == "trace":
|
||||
parsestattrace(indent)
|
||||
return
|
||||
@ -300,6 +355,7 @@ def emitheader():
|
||||
emitln("")
|
||||
emitln("def emit(string):")
|
||||
emitln(" sys.stdout.write(string)")
|
||||
emitln(" sys.stdout.flush()")
|
||||
emitln("")
|
||||
emitln("def trace(header, value):")
|
||||
emitln(" if os.environ.get('TRACE'):")
|
||||
@ -308,33 +364,40 @@ def emitheader():
|
||||
emitln("eof = chr(0)")
|
||||
emitln("eol = chr(10)")
|
||||
emitln("quote = chr(34)")
|
||||
emitln("PEEK = None")
|
||||
emitln("LINE = 1")
|
||||
emitln("")
|
||||
emitln("STDINCOLNO = 0")
|
||||
emitln("STDINLINENO = 1")
|
||||
emitln("STDINPEEK = None")
|
||||
emitln("")
|
||||
emitln("def _readchar():")
|
||||
emitln(" char = sys.stdin.read(1)")
|
||||
emitln(" trace('char', char)")
|
||||
emitln(" if not char:")
|
||||
emitln(" return eof")
|
||||
emitln(" return char")
|
||||
emitln("")
|
||||
emitln("def peek():")
|
||||
emitln(" global PEEK")
|
||||
emitln(" if PEEK is None:")
|
||||
emitln(" char = sys.stdin.read(1)")
|
||||
emitln(" trace('char', char)")
|
||||
emitln(" if not char:")
|
||||
emitln(" PEEK = eof")
|
||||
emitln(" else:")
|
||||
emitln(" PEEK = char")
|
||||
emitln(" return PEEK")
|
||||
emitln("")
|
||||
emitln("peek()")
|
||||
emitln(" return STDINPEEK")
|
||||
emitln("")
|
||||
emitln("def skip():")
|
||||
emitln(" global LINE")
|
||||
emitln(" global PEEK")
|
||||
emitln(" if eol == PEEK:")
|
||||
emitln(" LINE += 1")
|
||||
emitln(" PEEK = None")
|
||||
emitln(" global STDINCOLNO")
|
||||
emitln(" global STDINLINENO")
|
||||
emitln(" global STDINPEEK")
|
||||
emitln(" if eol == STDINPEEK:")
|
||||
emitln(" STDINLINENO += 1")
|
||||
emitln(" STDINCOLNO = 0")
|
||||
emitln(" STDINCOLNO += 1")
|
||||
emitln(" STDINPEEK = _readchar()")
|
||||
emitln("")
|
||||
emitln("def skipchar(char):")
|
||||
emitln(" global LINE")
|
||||
emitln(" assert char == peek(), (LINE, char, peek())")
|
||||
emitln(" skip()")
|
||||
emitln("def stdinlineno():")
|
||||
emitln(" global STDINLINENO")
|
||||
emitln(" return str(STDINLINENO)")
|
||||
emitln("")
|
||||
emitln("def stdincolno():")
|
||||
emitln(" global STDINCOLNO")
|
||||
emitln(" return str(STDINCOLNO)")
|
||||
emitln("")
|
||||
emitln("skip()")
|
||||
emitln("")
|
||||
|
||||
def emitfooter():
|
||||
|
||||
1
1-lang0py/.gitignore
vendored
1
1-lang0py/.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
/lang0py*.exe
|
||||
/lang0py*.o
|
||||
/lang0py*.py
|
||||
/lang0py*.py.tmp
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
.SUFFIXES:
|
||||
|
||||
PYVERSION=3.10
|
||||
PYVERSION=3.12
|
||||
PYPREFIX=/usr
|
||||
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
||||
CYTHON=cython3
|
||||
@ -18,18 +18,22 @@ all: lang0py.exe
|
||||
$(CYTHON) -3 --embed $<
|
||||
|
||||
lang0py0.py: lang0py.lang0 $(LANG0PY)
|
||||
cat $< | $(LANG0PY) > $@
|
||||
cat $< | $(LANG0PY) > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
lang0py1.py: lang0py.lang0 lang0py0.exe
|
||||
cat $< | ./lang0py0.exe > $@
|
||||
cat $< | ./lang0py0.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
# Cannot diff on the first iteration - platform change
|
||||
|
||||
lang0py2.py: lang0py.lang0 lang0py1.exe
|
||||
cat $< | ./lang0py1.exe > $@
|
||||
cat $< | ./lang0py1.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
-diff lang0py1.py lang0py2.py
|
||||
|
||||
lang0py.py: lang0py.lang0 lang0py2.exe
|
||||
cat $< | ./lang0py2.exe > $@
|
||||
cat $< | ./lang0py2.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
-diff lang0py2.py lang0py.py
|
||||
|
||||
clean:
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
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
|
||||
/
|
||||
|
||||
emitln data:
|
||||
emit data
|
||||
emit eol
|
||||
@ -151,12 +162,96 @@ parsestatreturn indent:
|
||||
calc isspace eq char " "
|
||||
if isspace
|
||||
skip
|
||||
parseexprvarref
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
/
|
||||
emit eol
|
||||
skipchar eol
|
||||
/
|
||||
|
||||
parsestatcheck indent:
|
||||
declare char
|
||||
declare funcname
|
||||
declare iscolon
|
||||
declare isnotquote
|
||||
declare isquote
|
||||
declare notfirst
|
||||
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "assert "
|
||||
|
||||
calc funcname lexident
|
||||
emit funcname
|
||||
emit "("
|
||||
|
||||
set notfirst ""
|
||||
forever
|
||||
skipchar " "
|
||||
calc char peek
|
||||
calc iscolon eq char ":"
|
||||
if iscolon
|
||||
break
|
||||
/
|
||||
|
||||
if notfirst
|
||||
emit ", "
|
||||
/
|
||||
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
|
||||
set notfirst "1"
|
||||
/
|
||||
|
||||
skipchar ":"
|
||||
|
||||
emit "), ("
|
||||
set notfirst ""
|
||||
|
||||
forever
|
||||
skipchar " "
|
||||
|
||||
if notfirst
|
||||
emit ", "
|
||||
/
|
||||
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
if iseol
|
||||
break
|
||||
/
|
||||
|
||||
set notfirst "1"
|
||||
/
|
||||
|
||||
emitln ")"
|
||||
/
|
||||
|
||||
parsestattrace indent:
|
||||
emit indent
|
||||
emit "trace("
|
||||
@ -214,6 +309,11 @@ parsestat indent:
|
||||
parsestattrace indent
|
||||
return
|
||||
/
|
||||
calc ischeck eq call "check"
|
||||
if ischeck
|
||||
parsestatcheck indent
|
||||
return
|
||||
/
|
||||
emit indent
|
||||
emit call
|
||||
emit "("
|
||||
@ -280,16 +380,11 @@ parseblock indent:
|
||||
|
||||
parsefunc:
|
||||
calc funcname lexident
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
if iseoblock
|
||||
return
|
||||
/
|
||||
trace funcname
|
||||
emit "def "
|
||||
emit funcname
|
||||
emit "("
|
||||
set first "1"
|
||||
set isnotfirst ""
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
@ -299,13 +394,11 @@ parsefunc:
|
||||
/
|
||||
skip
|
||||
calc var lexident
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
emit var
|
||||
set first "0"
|
||||
set isnotfirst "1"
|
||||
/
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
@ -339,41 +432,49 @@ emitheader:
|
||||
emitln ""
|
||||
emitln "def emit(string):"
|
||||
emitln " sys.stdout.write(string)"
|
||||
emitln " sys.stdout.flush()"
|
||||
emitln ""
|
||||
emitln "def trace(header, value):"
|
||||
emitln " if os.environ.get('TRACE'):"
|
||||
emitln " sys.stderr.write(f'{header}={value!r}\')"
|
||||
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
||||
emitln ""
|
||||
emitln "eof = chr(0)"
|
||||
emitln "eol = chr(10)"
|
||||
emitln "quote = chr(34)"
|
||||
emitln "PEEK = None"
|
||||
emitln "LINE = 1"
|
||||
emitln ""
|
||||
emitln "STDINCOLNO = 0"
|
||||
emitln "STDINLINENO = 1"
|
||||
emitln "STDINPEEK = None"
|
||||
emitln ""
|
||||
emitln "def _readchar():"
|
||||
emitln " char = sys.stdin.read(1)"
|
||||
emitln " trace('char', char)"
|
||||
emitln " if not char:"
|
||||
emitln " return eof"
|
||||
emitln " return char"
|
||||
emitln ""
|
||||
emitln "def peek():"
|
||||
emitln " global PEEK"
|
||||
emitln " if PEEK is None:"
|
||||
emitln " char = sys.stdin.read(1)"
|
||||
emitln " trace('char', char)"
|
||||
emitln " if not char:"
|
||||
emitln " PEEK = eof"
|
||||
emitln " else:"
|
||||
emitln " PEEK = char"
|
||||
emitln " return PEEK"
|
||||
emitln ""
|
||||
emitln "peek()"
|
||||
emitln " return STDINPEEK"
|
||||
emitln ""
|
||||
emitln "def skip():"
|
||||
emitln " global LINE"
|
||||
emitln " global PEEK"
|
||||
emitln " if eol == PEEK:"
|
||||
emitln " LINE += 1"
|
||||
emitln " PEEK = None"
|
||||
emitln " global STDINCOLNO"
|
||||
emitln " global STDINLINENO"
|
||||
emitln " global STDINPEEK"
|
||||
emitln " if eol == STDINPEEK:"
|
||||
emitln " STDINLINENO += 1"
|
||||
emitln " STDINCOLNO = 0"
|
||||
emitln " STDINCOLNO += 1"
|
||||
emitln " STDINPEEK = _readchar()"
|
||||
emitln ""
|
||||
emitln "def skipchar(char):"
|
||||
emitln " global LINE"
|
||||
emitln " assert char == peek(), (LINE, char, peek())"
|
||||
emitln " skip()"
|
||||
emitln "def stdinlineno():"
|
||||
emitln " global STDINLINENO"
|
||||
emitln " return str(STDINLINENO)"
|
||||
emitln ""
|
||||
emitln "def stdincolno():"
|
||||
emitln " global STDINCOLNO"
|
||||
emitln " return str(STDINCOLNO)"
|
||||
emitln ""
|
||||
emitln "skip()"
|
||||
emitln ""
|
||||
/
|
||||
|
||||
|
||||
1
2-lang0c/.gitignore
vendored
1
2-lang0c/.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
/lang0c*.c
|
||||
/lang0c*.c.tmp
|
||||
/lang0c*.exe
|
||||
/lang0c*.o
|
||||
/lang0c*.py
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
.SUFFIXES:
|
||||
|
||||
PYVERSION=3.10
|
||||
PYVERSION=3.12
|
||||
PYPREFIX=/usr
|
||||
INCLUDES=
|
||||
CYTHON=cython3
|
||||
@ -15,7 +15,8 @@ all: lang0c.exe
|
||||
gcc -c $<
|
||||
|
||||
lang0c0.py: lang0c.lang0 $(LANG0PY)
|
||||
cat $< | $(LANG0PY) > $@
|
||||
cat $< | $(LANG0PY) > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
lang0c0.c: lang0c0.py
|
||||
$(CYTHON) -3 --embed $<
|
||||
@ -27,15 +28,18 @@ lang0c0.exe: lang0c0.o
|
||||
gcc -o $@ $< -lpython$(PYVERSION)
|
||||
|
||||
lang0c1.c: lang0c.lang0 lang0c0.exe
|
||||
cat $< | ./lang0c0.exe > $@
|
||||
cat $< | ./lang0c0.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
# Cannot diff on the first iteration - platform change
|
||||
|
||||
lang0c2.c: lang0c.lang0 lang0c1.exe
|
||||
cat $< | ./lang0c1.exe > $@
|
||||
cat $< | ./lang0c1.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
-diff lang0c1.c lang0c2.c
|
||||
|
||||
lang0c.c: lang0c.lang0 lang0c2.exe
|
||||
cat $< | ./lang0c2.exe > $@
|
||||
cat $< | ./lang0c2.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
-diff lang0c2.c lang0c.c
|
||||
|
||||
clean:
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
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
|
||||
/
|
||||
|
||||
emitln data:
|
||||
emit data
|
||||
emit eol
|
||||
@ -195,6 +206,8 @@ parsestatbreak indent:
|
||||
parsestatreturn indent:
|
||||
declare char
|
||||
declare isspace
|
||||
declare isnotquote
|
||||
declare isquote
|
||||
declare isnotspace
|
||||
emit indent
|
||||
emit "return "
|
||||
@ -203,7 +216,15 @@ parsestatreturn indent:
|
||||
calc isnotspace not isspace
|
||||
if isspace
|
||||
skip
|
||||
parseexprvarref
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
/
|
||||
if isnotspace
|
||||
emit "0"
|
||||
@ -214,6 +235,98 @@ parsestatreturn indent:
|
||||
return
|
||||
/
|
||||
|
||||
parsestatcheck indent:
|
||||
declare char
|
||||
declare funcname
|
||||
declare iscolon
|
||||
declare iseol
|
||||
declare isnotquote
|
||||
declare isquote
|
||||
declare notfirst
|
||||
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "if( 0 == strlen("
|
||||
|
||||
calc funcname lexident
|
||||
emit funcname
|
||||
emit "("
|
||||
|
||||
set notfirst ""
|
||||
forever
|
||||
skipchar " "
|
||||
calc char peek
|
||||
calc iscolon eq char ":"
|
||||
if iscolon
|
||||
break
|
||||
/
|
||||
|
||||
if notfirst
|
||||
emit ", "
|
||||
/
|
||||
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
|
||||
set notfirst "1"
|
||||
/
|
||||
|
||||
skipchar ":"
|
||||
|
||||
emitln ")) )"
|
||||
emit indent
|
||||
emitln "{"
|
||||
|
||||
emit " fprintf(stderr, "
|
||||
emit quote
|
||||
emit "%s"
|
||||
emit quote
|
||||
emit ", "
|
||||
emit quote
|
||||
emit "ERROR:"
|
||||
emit quote
|
||||
emitln ");"
|
||||
|
||||
forever
|
||||
skipchar " "
|
||||
|
||||
emit indent
|
||||
emit " fprintf(stderr, "
|
||||
emit quote
|
||||
emit " %s"
|
||||
emit quote
|
||||
emit ", "
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
emitln ");"
|
||||
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
if iseol
|
||||
break
|
||||
/
|
||||
/
|
||||
|
||||
emit indent
|
||||
emitln " exit(1);"
|
||||
emit indent
|
||||
emitln "}"
|
||||
/
|
||||
|
||||
parsestattrace indent:
|
||||
declare varname
|
||||
emit indent
|
||||
@ -278,6 +391,11 @@ parsestat indent:
|
||||
parsestatreturn indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "check"
|
||||
if iscall
|
||||
parsestatcheck indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "trace"
|
||||
if iscall
|
||||
parsestattrace indent
|
||||
@ -471,35 +589,55 @@ emitheader:
|
||||
emitln " return 0;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "int LINE = 1;"
|
||||
emitln "int STDINCOLNO = 1;"
|
||||
emitln "int STDINLINENO = 1;"
|
||||
emitln "char * STDINPEEK = 0;"
|
||||
emitln ""
|
||||
emitln "char * peek()"
|
||||
emitln "char * _readchar()"
|
||||
emitln "{"
|
||||
emitln " char * res = malloc(2*sizeof(char));"
|
||||
emitln " res[0] = getc(stdin);"
|
||||
emitln " res[1] = 0;"
|
||||
emitln " ungetc(res[0], stdin);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "char * peek()"
|
||||
emitln "{"
|
||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
|
||||
emitln " return STDINPEEK;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "void skip()"
|
||||
emitln "{"
|
||||
emitln " char c = getc(stdin);"
|
||||
emitln " if( c == 10 ) LINE += 1;"
|
||||
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
|
||||
emitln " if( STDINPEEK[0] == 10 ) {"
|
||||
emitln " STDINLINENO += 1;"
|
||||
emitln " STDINCOLNO = 0;"
|
||||
emitln " }"
|
||||
emitln " STDINCOLNO += 1;"
|
||||
emitln " STDINPEEK = _readchar();"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "void skipchar(char * chr)"
|
||||
emitln "char * stdinlineno()"
|
||||
emitln "{"
|
||||
emitln " assert(strlen(chr) == 1);"
|
||||
emitln " char * act = peek();"
|
||||
emitln " assert(strlen(act) == 1);"
|
||||
emitln " if( chr[0] == act[0] ) {skip(); return;};"
|
||||
emit " fprintf(stderr, "
|
||||
emitln " char * res = malloc(8*sizeof(char));"
|
||||
emit " sprintf(res, "
|
||||
emit quote
|
||||
emit "Expected '%c' on line %d but saw '%c' instead%c"
|
||||
emit "%d"
|
||||
emit quote
|
||||
emitln ", chr[0], LINE, act[0], 10);"
|
||||
emitln " exit(1);"
|
||||
emitln ", STDINLINENO);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
emitln "char * stdincolno()"
|
||||
emitln "{"
|
||||
emitln " char * res = malloc(8*sizeof(char));"
|
||||
emit " sprintf(res, "
|
||||
emit quote
|
||||
emit "%d"
|
||||
emit quote
|
||||
emitln ", STDINCOLNO);"
|
||||
emitln " return res;"
|
||||
emitln "}"
|
||||
emitln ""
|
||||
return
|
||||
|
||||
6
3-lang0ll/.gitignore
vendored
Normal file
6
3-lang0ll/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/lang0ll*.c
|
||||
/lang0ll*.exe
|
||||
/lang0ll*.ll
|
||||
/lang0ll*.o
|
||||
/foo.exe
|
||||
/foo.ll
|
||||
42
3-lang0ll/Makefile
Normal file
42
3-lang0ll/Makefile
Normal file
@ -0,0 +1,42 @@
|
||||
.SUFFIXES:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LANG0C=$(CURDIR)/../2-lang0c/lang0c.exe
|
||||
|
||||
all: lang0ll.exe
|
||||
|
||||
%.exe: %.s
|
||||
clang $^ -o $@
|
||||
|
||||
%.s: %.ll
|
||||
llc --relocation-model=pic $^
|
||||
|
||||
lang0ll0.c: lang0ll.lang0 $(LANG0C)
|
||||
cat $< | $(LANG0C) > $@
|
||||
|
||||
lang0ll0.o: lang0ll0.c
|
||||
gcc -c $<
|
||||
|
||||
lang0ll0.exe: lang0ll0.o
|
||||
gcc -o $@ $<
|
||||
|
||||
lang0ll1.ll: lang0ll.lang0 lang0ll0.exe
|
||||
cat $< | ./lang0ll0.exe > $@
|
||||
# Cannot diff on the first iteration - platform change
|
||||
|
||||
lang0ll2.ll: lang0ll.lang0 lang0ll1.exe
|
||||
cat $< | ./lang0ll1.exe > $@
|
||||
-diff lang0ll1.ll lang0ll2.ll
|
||||
|
||||
lang0ll.ll: lang0ll.lang0 lang0ll2.exe
|
||||
cat $< | ./lang0ll2.exe > $@
|
||||
-diff lang0ll2.ll lang0ll.ll
|
||||
|
||||
foo.ll: foo.c
|
||||
clang -S -emit-llvm $^
|
||||
|
||||
clean:
|
||||
rm -f lang0ll*.py lang0ll*.ll lang0ll*.o lang0ll*.exe foo.ll foo.o foo.exe
|
||||
17
3-lang0ll/foo.c
Normal file
17
3-lang0ll/foo.c
Normal file
@ -0,0 +1,17 @@
|
||||
void print(char * x)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int sum(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char * foo = "Hello, world!";
|
||||
print("This is a test.");
|
||||
|
||||
return sum(7, 15);
|
||||
}
|
||||
472
3-lang0ll/lang0ll.lang0
Normal file
472
3-lang0ll/lang0ll.lang0
Normal file
@ -0,0 +1,472 @@
|
||||
increaseindent indent:
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
return indent
|
||||
/
|
||||
|
||||
lexident:
|
||||
declare char
|
||||
declare isbeforea
|
||||
declare isafterz
|
||||
declare word
|
||||
set word ""
|
||||
forever
|
||||
calc char peek
|
||||
calc isbeforea lt char "a"
|
||||
if isbeforea
|
||||
break
|
||||
/
|
||||
calc isafterz lt "z" char
|
||||
if isafterz
|
||||
break
|
||||
/
|
||||
calc word addstringchar word char
|
||||
skip
|
||||
/
|
||||
return word
|
||||
/
|
||||
|
||||
parseconststring:
|
||||
declare char
|
||||
declare iseof
|
||||
declare isquote
|
||||
skipchar quote
|
||||
forever
|
||||
calc char peek
|
||||
calc iseof eq char eof
|
||||
if iseof
|
||||
break
|
||||
/
|
||||
calc isquote eq char quote
|
||||
if isquote
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
skipchar quote
|
||||
emit "i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)"
|
||||
return
|
||||
/
|
||||
|
||||
parseexprvarref:
|
||||
declare varname
|
||||
calc varname lexident
|
||||
emit "i8* %"
|
||||
emit varname
|
||||
return
|
||||
/
|
||||
|
||||
parseexprcall:
|
||||
declare char
|
||||
declare first
|
||||
declare funcname
|
||||
declare isspace
|
||||
declare isnotspace
|
||||
declare isfirst
|
||||
declare isnotfirst
|
||||
declare isquote
|
||||
declare isnotquote
|
||||
calc funcname lexident
|
||||
emit funcname
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
set first "0"
|
||||
/
|
||||
emit ")"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatdeclare indent:
|
||||
declare var
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
emit indent
|
||||
emit "char * var_"
|
||||
emit var
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatset indent:
|
||||
declare var
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "var_"
|
||||
emit var
|
||||
emit " = "
|
||||
parseconststring
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatcalc indent:
|
||||
declare var
|
||||
declare varidx
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "%"
|
||||
emit var
|
||||
calc varidx mapgetkey "funcvarused" var
|
||||
calc varidx intinc varidx
|
||||
mapsetkey "funcvarused" var varidx
|
||||
emit "."
|
||||
emit varidx
|
||||
emit " = call i8* @"
|
||||
parseexprcall
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parseblock indent/
|
||||
|
||||
parsestatif indent:
|
||||
declare indentt
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "if ( 0 < strlen("
|
||||
parseexprvarref
|
||||
emit ") )\n"
|
||||
emit indent
|
||||
emit "{\n"
|
||||
skipchar eol
|
||||
calc indentt increaseindent indent
|
||||
parseblock indentt
|
||||
emit indent
|
||||
emit "}\n"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatforever indent:
|
||||
declare indentt
|
||||
emit indent
|
||||
emit "while (1)\n"
|
||||
emit indent
|
||||
emit "{\n"
|
||||
skipchar eol
|
||||
calc indentt increaseindent indent
|
||||
parseblock indentt
|
||||
emit indent
|
||||
emit "}\n"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatbreak indent:
|
||||
emit indent
|
||||
emit "break;\n"
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatreturn indent:
|
||||
declare char
|
||||
declare isspace
|
||||
declare isnotspace
|
||||
emit indent
|
||||
emit "ret "
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isspace
|
||||
skip
|
||||
parseexprvarref
|
||||
/
|
||||
if isnotspace
|
||||
emit "i18* 0"
|
||||
/
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestattrace indent:
|
||||
declare varname
|
||||
emit indent
|
||||
emit "trace("
|
||||
emit quote
|
||||
skipchar " "
|
||||
calc varname lexident
|
||||
emit varname
|
||||
emit quote
|
||||
emit ", var_"
|
||||
emit varname
|
||||
emit ");\n"
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestat indent:
|
||||
declare call
|
||||
declare char
|
||||
declare first
|
||||
declare iscall
|
||||
declare isfirst
|
||||
declare isspace
|
||||
declare isquote
|
||||
declare isnotfirst
|
||||
declare isnotspace
|
||||
declare isnotquote
|
||||
calc call lexident
|
||||
trace call
|
||||
calc iscall eq call "declare"
|
||||
if iscall
|
||||
parsestatdeclare indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "set"
|
||||
if iscall
|
||||
parsestatset indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "calc"
|
||||
if iscall
|
||||
parsestatcalc indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "if"
|
||||
if iscall
|
||||
parsestatif indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "forever"
|
||||
if iscall
|
||||
parsestatforever indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "break"
|
||||
if iscall
|
||||
parsestatbreak indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "return"
|
||||
if iscall
|
||||
parsestatreturn indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "trace"
|
||||
if iscall
|
||||
parsestattrace indent
|
||||
return
|
||||
/
|
||||
emit indent
|
||||
emit call
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
set first "0"
|
||||
/
|
||||
skipchar eol
|
||||
emit ");\n"
|
||||
return
|
||||
/
|
||||
|
||||
parseblock indent:
|
||||
declare char
|
||||
declare copy
|
||||
declare iseol
|
||||
declare isnoteol
|
||||
declare isdone
|
||||
declare iseoblock
|
||||
forever
|
||||
forever
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
calc isnoteol not iseol
|
||||
if isnoteol
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
set copy " "
|
||||
forever
|
||||
calc isdone eq copy indent
|
||||
if isdone
|
||||
break
|
||||
/
|
||||
skipchar "\t"
|
||||
calc copy increaseindent copy
|
||||
/
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
if iseoblock
|
||||
skip
|
||||
skipchar eol
|
||||
break
|
||||
/
|
||||
skipchar "\t"
|
||||
parsestat indent
|
||||
/
|
||||
return
|
||||
/
|
||||
|
||||
parsefunc:
|
||||
declare char
|
||||
declare first
|
||||
declare funcname
|
||||
declare iseoblock
|
||||
declare isfirst
|
||||
declare isspace
|
||||
declare isnotfirst
|
||||
declare isnotspace
|
||||
declare var
|
||||
mapclear "funcvarused"
|
||||
calc funcname lexident
|
||||
trace funcname
|
||||
emit "define i8* @"
|
||||
emit funcname
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc var lexident
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
emit "i8* %"
|
||||
emit var
|
||||
mapsetkey "funcvarused" "var" "0"
|
||||
emit "_0"
|
||||
set first "0"
|
||||
/
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
if iseoblock
|
||||
skipchar "/"
|
||||
skipchar eol
|
||||
emit ");"
|
||||
emit "\n"
|
||||
return
|
||||
/
|
||||
skipchar ":"
|
||||
skipchar eol
|
||||
emit ")\n{\n"
|
||||
parseblock " "
|
||||
emit "}\n\n"
|
||||
return
|
||||
/
|
||||
|
||||
emitheader:
|
||||
emit "target datalayout = "
|
||||
emit quote
|
||||
emit "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
emit quote
|
||||
emit eol
|
||||
|
||||
emit "target triple = "
|
||||
emit quote
|
||||
emit "x86_64-pc-linux-gnu"
|
||||
emit quote
|
||||
emit eol
|
||||
|
||||
emit eol
|
||||
|
||||
emit "define i8* @addstringchar(i8* %0, i8* %1)"
|
||||
emit eol
|
||||
emit "{"
|
||||
emit eol
|
||||
emit " ; todo"
|
||||
emit eol
|
||||
emit " ret i8* %0;"
|
||||
emit eol
|
||||
emit "}"
|
||||
emit eol
|
||||
|
||||
emit eol
|
||||
|
||||
return
|
||||
/
|
||||
|
||||
emitfooter:
|
||||
emit ""
|
||||
return
|
||||
/
|
||||
|
||||
main:
|
||||
declare char
|
||||
declare iseof
|
||||
declare iseol
|
||||
declare isnoteol
|
||||
emitheader
|
||||
forever
|
||||
calc char peek
|
||||
calc iseof eq char eof
|
||||
if iseof
|
||||
break
|
||||
/
|
||||
forever
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
calc isnoteol not iseol
|
||||
if isnoteol
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
parsefunc
|
||||
/
|
||||
emitfooter
|
||||
return
|
||||
/
|
||||
19
3-lang0ll/notes.ll
Normal file
19
3-lang0ll/notes.ll
Normal file
@ -0,0 +1,19 @@
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
define i8* @addstringchar(i8* %0, i8* %1)
|
||||
{
|
||||
; todo
|
||||
ret i8* %0;
|
||||
}
|
||||
|
||||
define i8* @increaseindent(i8* %indent)
|
||||
{
|
||||
%indent.1 = call i8* @addstringchar(i8* %indent, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.2 = call i8* @addstringchar(i8* %indent.1, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.3 = call i8* @addstringchar(i8* %indent.2, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.4 = call i8* @addstringchar(i8* %indent.3, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
ret i8* %indent.4;
|
||||
}
|
||||
|
||||
@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1
|
||||
44
README.md
44
README.md
@ -113,6 +113,10 @@ Returns the given value. You can not give an argument if your function is never
|
||||
|
||||
### Builtins
|
||||
|
||||
#### check func [arg0..] : msg [arg0..]
|
||||
|
||||
Calls the given function with the given arguments. If the function's return value is not found to be true, outputs the given `msg` and halts the program.
|
||||
|
||||
#### trace
|
||||
|
||||
Writes the name and value of the variable passed to stderr if the TRACE environment variable is set.
|
||||
@ -133,12 +137,44 @@ Writes the given string to standard output.
|
||||
|
||||
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
|
||||
|
||||
`a` and `b` are expected to have length 1.
|
||||
|
||||
Return true if a would sort before b.
|
||||
|
||||
#### mapclear mapname
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Clears all values set in the map named `mapname`.
|
||||
|
||||
#### mapgetkey mapname key
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Looks up `key` in the map named `mapname` and returns it.
|
||||
If not found, returns an empty string.
|
||||
|
||||
#### mapsetkey mapname key value
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Adds a mapping from `key` to `value` to the map named `mapname`.
|
||||
|
||||
#### peek
|
||||
|
||||
Checks stdin for the next character and returns it.
|
||||
@ -147,9 +183,13 @@ Checks stdin for the next character and returns it.
|
||||
|
||||
Advances stdin a single character.
|
||||
|
||||
#### skipchar a
|
||||
#### stdincolno
|
||||
|
||||
Advances stdin a single character, if it matches the first character of `a`. Otherwise, exits the program.
|
||||
Returns the column number for stdin (starting at 1)
|
||||
|
||||
#### stdinlineno
|
||||
|
||||
Returns the line number for stdin (starting at 1)
|
||||
|
||||
### Typing
|
||||
|
||||
|
||||
@ -1,29 +1,35 @@
|
||||
.SUFFIXES:
|
||||
.PHONY: all clean
|
||||
.PRECIOUS: build/%.it0.py build/%.it0.c
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
PYVERSION=3.10
|
||||
PYVERSION=3.12
|
||||
PYPREFIX=/usr
|
||||
CYTHON=cython3
|
||||
CC=gcc
|
||||
|
||||
TESTLIST=$(shell ls *.lang0 | sed 's/.lang0//')
|
||||
# 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//')
|
||||
|
||||
all: check
|
||||
|
||||
check: all-it0.results all-it1.results all-it2.results
|
||||
! grep -v 'Success' $^
|
||||
|
||||
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST)))
|
||||
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST))) build/builtincheckfalse.it0
|
||||
-rm -f $@
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
|
||||
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)))
|
||||
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it1
|
||||
-rm -f $@
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
|
||||
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)))
|
||||
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it2
|
||||
-rm -f $@
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
|
||||
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:
|
||||
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
||||
@ -31,8 +37,12 @@ clean:
|
||||
###
|
||||
# it0
|
||||
|
||||
../0-lang0py/lang0py.exe: ../0-lang0py/lang0py.py
|
||||
$(MAKE) -C ../0-lang0py
|
||||
|
||||
build/%.it0.py: %.lang0 ../0-lang0py/lang0py.exe
|
||||
cat $< | ../0-lang0py/lang0py.exe > $@
|
||||
cat $< | ../0-lang0py/lang0py.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
build/%.it0.c: build/%.it0.py
|
||||
$(CYTHON) -3 --embed -o $@ $^
|
||||
@ -46,8 +56,12 @@ build/%.it0: build/%.it0.o
|
||||
###
|
||||
# it1
|
||||
|
||||
../1-lang0py/lang0py.exe: ../0-lang0py/lang0py.exe ../1-lang0py/lang0py.lang0
|
||||
$(MAKE) -C ../1-lang0py
|
||||
|
||||
build/%.it1.py: %.lang0 ../1-lang0py/lang0py.exe
|
||||
cat $< | ../1-lang0py/lang0py.exe > $@
|
||||
cat $< | ../1-lang0py/lang0py.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
build/%.it1.c: build/%.it1.py
|
||||
$(CYTHON) -3 --embed -o $@ $^
|
||||
@ -61,8 +75,12 @@ build/%.it1: build/%.it1.o
|
||||
###
|
||||
# it2
|
||||
|
||||
../2-lang0c/lang0c.exe: ../0-lang0py/lang0py.exe ../1-lang0py/lang0py.exe ../2-lang0c/lang0c.lang0
|
||||
$(MAKE) -C ../2-lang0c
|
||||
|
||||
build/%.it2.c: %.lang0 ../2-lang0c/lang0c.exe
|
||||
cat $< | ../2-lang0c/lang0c.exe > $@
|
||||
cat $< | ../2-lang0c/lang0c.exe > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
build/%.it2.o: build/%.it2.c
|
||||
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
||||
|
||||
3
tests/build/.gitignore
vendored
3
tests/build/.gitignore
vendored
@ -2,10 +2,13 @@
|
||||
/*.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
|
||||
|
||||
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"
|
||||
/
|
||||
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,11 +0,0 @@
|
||||
func result/
|
||||
|
||||
main:
|
||||
declare result
|
||||
calc result func "Success"
|
||||
emit result
|
||||
/
|
||||
|
||||
func result:
|
||||
return result
|
||||
/
|
||||
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"
|
||||
/
|
||||
@ -1,5 +1,6 @@
|
||||
main:
|
||||
declare result
|
||||
calc result addstringchar "Succes" "s"
|
||||
emit result
|
||||
calc result addstringchar "abc" "d"
|
||||
check eq result "abcd" : "Adding abc and d should be abcd"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
main:
|
||||
declare bool
|
||||
calc bool eq "1" "2"
|
||||
if bool
|
||||
return
|
||||
/
|
||||
check not bool : "1 should not equal 2"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
main:
|
||||
declare bool
|
||||
calc bool eq "1" "1"
|
||||
if bool
|
||||
emit "Success"
|
||||
/
|
||||
check eq "1" "1" : "1 should equal 1"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
main:
|
||||
declare bool
|
||||
calc bool lt "b" "a"
|
||||
if bool
|
||||
return
|
||||
/
|
||||
check not bool : "a should should sort before b"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
main:
|
||||
declare bool
|
||||
calc bool lt "a" "b"
|
||||
if bool
|
||||
emit "Success"
|
||||
/
|
||||
check lt "a" "b" : "a should should sort before b"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
main:
|
||||
declare char
|
||||
declare ish
|
||||
calc char peek
|
||||
calc ish eq char "H"
|
||||
if ish
|
||||
emit "Success"
|
||||
/
|
||||
check eq char "H" : "The first byte we're passed is expected to be an 'H'"
|
||||
emit "Success"
|
||||
/
|
||||
|
||||
@ -1,24 +1,12 @@
|
||||
main:
|
||||
declare char
|
||||
declare ish
|
||||
declare iso
|
||||
declare notish
|
||||
declare notiso
|
||||
skip
|
||||
calc char peek
|
||||
calc ish eq char "e"
|
||||
calc notish not ish
|
||||
if notish
|
||||
return
|
||||
/
|
||||
check eq char "e" : "The second byte we're passed is expected to be an 'e'"
|
||||
skip
|
||||
skip
|
||||
skip
|
||||
calc char peek
|
||||
calc iso eq char "o"
|
||||
calc notiso not iso
|
||||
if notish
|
||||
return
|
||||
/
|
||||
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.
|
||||
Loading…
x
Reference in New Issue
Block a user