Compare commits
8 Commits
05eb2d3be7
...
c318c780da
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c318c780da | ||
|
|
1b8333fcfa | ||
|
|
2eaa763a2c | ||
|
|
ed09d37213 | ||
|
|
a184d4c5e3 | ||
|
|
5fa042c5cd | ||
|
|
931a861fef | ||
|
|
7568a15093 |
@ -1,6 +1,6 @@
|
|||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
PYVERSION=3.10
|
PYVERSION=3.12
|
||||||
PYPREFIX=/usr
|
PYPREFIX=/usr
|
||||||
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
||||||
CYTHON=cython3
|
CYTHON=cython3
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import sys
|
|||||||
|
|
||||||
def emit(string):
|
def emit(string):
|
||||||
sys.stdout.write(string)
|
sys.stdout.write(string)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
def trace(header, value):
|
def trace(header, value):
|
||||||
if os.environ.get('TRACE'):
|
if os.environ.get('TRACE'):
|
||||||
@ -38,11 +39,6 @@ def skip():
|
|||||||
|
|
||||||
PEEK = None
|
PEEK = None
|
||||||
|
|
||||||
def skipchar(char):
|
|
||||||
global LINE
|
|
||||||
assert char == peek(), (LINE, char, peek())
|
|
||||||
skip()
|
|
||||||
|
|
||||||
def emitln(data):
|
def emitln(data):
|
||||||
emit(data)
|
emit(data)
|
||||||
emit(eol)
|
emit(eol)
|
||||||
@ -60,6 +56,11 @@ def lexident():
|
|||||||
|
|
||||||
return word
|
return word
|
||||||
|
|
||||||
|
def skipchar(char):
|
||||||
|
global LINE
|
||||||
|
assert char == peek(), (LINE, char, peek())
|
||||||
|
skip()
|
||||||
|
|
||||||
def parseconststring():
|
def parseconststring():
|
||||||
skipchar(quote)
|
skipchar(quote)
|
||||||
emit(quote)
|
emit(quote)
|
||||||
@ -161,10 +162,60 @@ def parsestatreturn(indent):
|
|||||||
emit('return ')
|
emit('return ')
|
||||||
if ' ' == peek():
|
if ' ' == peek():
|
||||||
skip()
|
skip()
|
||||||
|
if quote == peek():
|
||||||
|
parseconststring()
|
||||||
|
else:
|
||||||
parseexprvarref()
|
parseexprvarref()
|
||||||
emit(eol)
|
emit(eol)
|
||||||
skipchar(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):
|
def parsestattrace(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
@ -210,6 +261,10 @@ def parsestat(indent):
|
|||||||
parsestatreturn(indent)
|
parsestatreturn(indent)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if call == "check":
|
||||||
|
parsestatcheck(indent)
|
||||||
|
return
|
||||||
|
|
||||||
if call == "trace":
|
if call == "trace":
|
||||||
parsestattrace(indent)
|
parsestattrace(indent)
|
||||||
return
|
return
|
||||||
@ -300,6 +355,7 @@ def emitheader():
|
|||||||
emitln("")
|
emitln("")
|
||||||
emitln("def emit(string):")
|
emitln("def emit(string):")
|
||||||
emitln(" sys.stdout.write(string)")
|
emitln(" sys.stdout.write(string)")
|
||||||
|
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'):")
|
||||||
@ -308,32 +364,39 @@ def emitheader():
|
|||||||
emitln("eof = chr(0)")
|
emitln("eof = chr(0)")
|
||||||
emitln("eol = chr(10)")
|
emitln("eol = chr(10)")
|
||||||
emitln("quote = chr(34)")
|
emitln("quote = chr(34)")
|
||||||
emitln("PEEK = None")
|
|
||||||
emitln("LINE = 1")
|
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def peek():")
|
emitln("STDINCOLNO = 0")
|
||||||
emitln(" global PEEK")
|
emitln("STDINLINENO = 1")
|
||||||
emitln(" if PEEK is None:")
|
emitln("STDINPEEK = None")
|
||||||
|
emitln("")
|
||||||
|
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(" PEEK = eof")
|
emitln(" return eof")
|
||||||
emitln(" else:")
|
emitln(" return char")
|
||||||
emitln(" PEEK = char")
|
|
||||||
emitln(" return PEEK")
|
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("peek()")
|
emitln("def peek():")
|
||||||
|
emitln(" return STDINPEEK")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def skip():")
|
emitln("def skip():")
|
||||||
emitln(" global LINE")
|
emitln(" global STDINCOLNO")
|
||||||
emitln(" global PEEK")
|
emitln(" global STDINLINENO")
|
||||||
emitln(" if eol == PEEK:")
|
emitln(" global STDINPEEK")
|
||||||
emitln(" LINE += 1")
|
emitln(" if eol == STDINPEEK:")
|
||||||
emitln(" PEEK = None")
|
emitln(" STDINLINENO += 1")
|
||||||
|
emitln(" STDINCOLNO = 0")
|
||||||
|
emitln(" STDINCOLNO += 1")
|
||||||
|
emitln(" STDINPEEK = _readchar()")
|
||||||
|
emitln("")
|
||||||
|
emitln("def stdinlineno():")
|
||||||
|
emitln(" global STDINLINENO")
|
||||||
|
emitln(" return str(STDINLINENO)")
|
||||||
|
emitln("")
|
||||||
|
emitln("def stdincolno():")
|
||||||
|
emitln(" global STDINCOLNO")
|
||||||
|
emitln(" return str(STDINCOLNO)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def skipchar(char):")
|
|
||||||
emitln(" global LINE")
|
|
||||||
emitln(" assert char == peek(), (LINE, char, peek())")
|
|
||||||
emitln("skip()")
|
emitln("skip()")
|
||||||
emitln("")
|
emitln("")
|
||||||
|
|
||||||
|
|||||||
1
1-lang0py/.gitignore
vendored
1
1-lang0py/.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
/lang0py*.exe
|
/lang0py*.exe
|
||||||
/lang0py*.o
|
/lang0py*.o
|
||||||
/lang0py*.py
|
/lang0py*.py
|
||||||
|
/lang0py*.py.tmp
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
PYVERSION=3.10
|
PYVERSION=3.12
|
||||||
PYPREFIX=/usr
|
PYPREFIX=/usr
|
||||||
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
|
||||||
CYTHON=cython3
|
CYTHON=cython3
|
||||||
@ -18,18 +18,22 @@ all: lang0py.exe
|
|||||||
$(CYTHON) -3 --embed $<
|
$(CYTHON) -3 --embed $<
|
||||||
|
|
||||||
lang0py0.py: lang0py.lang0 $(LANG0PY)
|
lang0py0.py: lang0py.lang0 $(LANG0PY)
|
||||||
cat $< | $(LANG0PY) > $@
|
cat $< | $(LANG0PY) > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
|
|
||||||
lang0py1.py: lang0py.lang0 lang0py0.exe
|
lang0py1.py: lang0py.lang0 lang0py0.exe
|
||||||
cat $< | ./lang0py0.exe > $@
|
cat $< | ./lang0py0.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
# Cannot diff on the first iteration - platform change
|
# Cannot diff on the first iteration - platform change
|
||||||
|
|
||||||
lang0py2.py: lang0py.lang0 lang0py1.exe
|
lang0py2.py: lang0py.lang0 lang0py1.exe
|
||||||
cat $< | ./lang0py1.exe > $@
|
cat $< | ./lang0py1.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
-diff lang0py1.py lang0py2.py
|
-diff lang0py1.py lang0py2.py
|
||||||
|
|
||||||
lang0py.py: lang0py.lang0 lang0py2.exe
|
lang0py.py: lang0py.lang0 lang0py2.exe
|
||||||
cat $< | ./lang0py2.exe > $@
|
cat $< | ./lang0py2.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
-diff lang0py2.py lang0py.py
|
-diff lang0py2.py lang0py.py
|
||||||
|
|
||||||
clean:
|
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:
|
emitln data:
|
||||||
emit data
|
emit data
|
||||||
emit eol
|
emit eol
|
||||||
@ -151,12 +162,96 @@ parsestatreturn indent:
|
|||||||
calc isspace eq char " "
|
calc isspace eq char " "
|
||||||
if isspace
|
if isspace
|
||||||
skip
|
skip
|
||||||
|
calc char peek
|
||||||
|
calc isquote eq char quote
|
||||||
|
calc isnotquote not isquote
|
||||||
|
if isquote
|
||||||
|
parseconststring
|
||||||
|
/
|
||||||
|
if isnotquote
|
||||||
parseexprvarref
|
parseexprvarref
|
||||||
/
|
/
|
||||||
|
/
|
||||||
emit eol
|
emit eol
|
||||||
skipchar 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:
|
parsestattrace indent:
|
||||||
emit indent
|
emit indent
|
||||||
emit "trace("
|
emit "trace("
|
||||||
@ -214,6 +309,11 @@ parsestat indent:
|
|||||||
parsestattrace indent
|
parsestattrace indent
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
calc ischeck eq call "check"
|
||||||
|
if ischeck
|
||||||
|
parsestatcheck indent
|
||||||
|
return
|
||||||
|
/
|
||||||
emit indent
|
emit indent
|
||||||
emit call
|
emit call
|
||||||
emit "("
|
emit "("
|
||||||
@ -280,16 +380,11 @@ parseblock indent:
|
|||||||
|
|
||||||
parsefunc:
|
parsefunc:
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
calc char peek
|
|
||||||
calc iseoblock eq char "/"
|
|
||||||
if iseoblock
|
|
||||||
return
|
|
||||||
/
|
|
||||||
trace funcname
|
trace funcname
|
||||||
emit "def "
|
emit "def "
|
||||||
emit funcname
|
emit funcname
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set isnotfirst ""
|
||||||
forever
|
forever
|
||||||
calc char peek
|
calc char peek
|
||||||
calc isspace eq char " "
|
calc isspace eq char " "
|
||||||
@ -299,13 +394,11 @@ parsefunc:
|
|||||||
/
|
/
|
||||||
skip
|
skip
|
||||||
calc var lexident
|
calc var lexident
|
||||||
calc isfirst eq first "1"
|
|
||||||
calc isnotfirst not isfirst
|
|
||||||
if isnotfirst
|
if isnotfirst
|
||||||
emit ", "
|
emit ", "
|
||||||
/
|
/
|
||||||
emit var
|
emit var
|
||||||
set first "0"
|
set isnotfirst "1"
|
||||||
/
|
/
|
||||||
calc char peek
|
calc char peek
|
||||||
calc iseoblock eq char "/"
|
calc iseoblock eq char "/"
|
||||||
@ -339,40 +432,48 @@ emitheader:
|
|||||||
emitln ""
|
emitln ""
|
||||||
emitln "def emit(string):"
|
emitln "def emit(string):"
|
||||||
emitln " sys.stdout.write(string)"
|
emitln " sys.stdout.write(string)"
|
||||||
|
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}\')"
|
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "eof = chr(0)"
|
emitln "eof = chr(0)"
|
||||||
emitln "eol = chr(10)"
|
emitln "eol = chr(10)"
|
||||||
emitln "quote = chr(34)"
|
emitln "quote = chr(34)"
|
||||||
emitln "PEEK = None"
|
|
||||||
emitln "LINE = 1"
|
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def peek():"
|
emitln "STDINCOLNO = 0"
|
||||||
emitln " global PEEK"
|
emitln "STDINLINENO = 1"
|
||||||
emitln " if PEEK is None:"
|
emitln "STDINPEEK = None"
|
||||||
|
emitln ""
|
||||||
|
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 " PEEK = eof"
|
emitln " return eof"
|
||||||
emitln " else:"
|
emitln " return char"
|
||||||
emitln " PEEK = char"
|
|
||||||
emitln " return PEEK"
|
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "peek()"
|
emitln "def peek():"
|
||||||
|
emitln " return STDINPEEK"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def skip():"
|
emitln "def skip():"
|
||||||
emitln " global LINE"
|
emitln " global STDINCOLNO"
|
||||||
emitln " global PEEK"
|
emitln " global STDINLINENO"
|
||||||
emitln " if eol == PEEK:"
|
emitln " global STDINPEEK"
|
||||||
emitln " LINE += 1"
|
emitln " if eol == STDINPEEK:"
|
||||||
emitln " PEEK = None"
|
emitln " STDINLINENO += 1"
|
||||||
|
emitln " STDINCOLNO = 0"
|
||||||
|
emitln " STDINCOLNO += 1"
|
||||||
|
emitln " STDINPEEK = _readchar()"
|
||||||
|
emitln ""
|
||||||
|
emitln "def stdinlineno():"
|
||||||
|
emitln " global STDINLINENO"
|
||||||
|
emitln " return str(STDINLINENO)"
|
||||||
|
emitln ""
|
||||||
|
emitln "def stdincolno():"
|
||||||
|
emitln " global STDINCOLNO"
|
||||||
|
emitln " return str(STDINCOLNO)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def skipchar(char):"
|
|
||||||
emitln " global LINE"
|
|
||||||
emitln " assert char == peek(), (LINE, char, peek())"
|
|
||||||
emitln "skip()"
|
emitln "skip()"
|
||||||
emitln ""
|
emitln ""
|
||||||
/
|
/
|
||||||
|
|||||||
1
2-lang0c/.gitignore
vendored
1
2-lang0c/.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
/lang0c*.c
|
/lang0c*.c
|
||||||
|
/lang0c*.c.tmp
|
||||||
/lang0c*.exe
|
/lang0c*.exe
|
||||||
/lang0c*.o
|
/lang0c*.o
|
||||||
/lang0c*.py
|
/lang0c*.py
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
PYVERSION=3.10
|
PYVERSION=3.12
|
||||||
PYPREFIX=/usr
|
PYPREFIX=/usr
|
||||||
INCLUDES=
|
INCLUDES=
|
||||||
CYTHON=cython3
|
CYTHON=cython3
|
||||||
@ -15,7 +15,8 @@ all: lang0c.exe
|
|||||||
gcc -c $<
|
gcc -c $<
|
||||||
|
|
||||||
lang0c0.py: lang0c.lang0 $(LANG0PY)
|
lang0c0.py: lang0c.lang0 $(LANG0PY)
|
||||||
cat $< | $(LANG0PY) > $@
|
cat $< | $(LANG0PY) > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
|
|
||||||
lang0c0.c: lang0c0.py
|
lang0c0.c: lang0c0.py
|
||||||
$(CYTHON) -3 --embed $<
|
$(CYTHON) -3 --embed $<
|
||||||
@ -27,15 +28,18 @@ lang0c0.exe: lang0c0.o
|
|||||||
gcc -o $@ $< -lpython$(PYVERSION)
|
gcc -o $@ $< -lpython$(PYVERSION)
|
||||||
|
|
||||||
lang0c1.c: lang0c.lang0 lang0c0.exe
|
lang0c1.c: lang0c.lang0 lang0c0.exe
|
||||||
cat $< | ./lang0c0.exe > $@
|
cat $< | ./lang0c0.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
# Cannot diff on the first iteration - platform change
|
# Cannot diff on the first iteration - platform change
|
||||||
|
|
||||||
lang0c2.c: lang0c.lang0 lang0c1.exe
|
lang0c2.c: lang0c.lang0 lang0c1.exe
|
||||||
cat $< | ./lang0c1.exe > $@
|
cat $< | ./lang0c1.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
-diff lang0c1.c lang0c2.c
|
-diff lang0c1.c lang0c2.c
|
||||||
|
|
||||||
lang0c.c: lang0c.lang0 lang0c2.exe
|
lang0c.c: lang0c.lang0 lang0c2.exe
|
||||||
cat $< | ./lang0c2.exe > $@
|
cat $< | ./lang0c2.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
-diff lang0c2.c lang0c.c
|
-diff lang0c2.c lang0c.c
|
||||||
|
|
||||||
clean:
|
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:
|
emitln data:
|
||||||
emit data
|
emit data
|
||||||
emit eol
|
emit eol
|
||||||
@ -195,6 +206,8 @@ parsestatbreak indent:
|
|||||||
parsestatreturn indent:
|
parsestatreturn indent:
|
||||||
declare char
|
declare char
|
||||||
declare isspace
|
declare isspace
|
||||||
|
declare isnotquote
|
||||||
|
declare isquote
|
||||||
declare isnotspace
|
declare isnotspace
|
||||||
emit indent
|
emit indent
|
||||||
emit "return "
|
emit "return "
|
||||||
@ -203,8 +216,16 @@ parsestatreturn indent:
|
|||||||
calc isnotspace not isspace
|
calc isnotspace not isspace
|
||||||
if isspace
|
if isspace
|
||||||
skip
|
skip
|
||||||
|
calc char peek
|
||||||
|
calc isquote eq char quote
|
||||||
|
calc isnotquote not isquote
|
||||||
|
if isquote
|
||||||
|
parseconststring
|
||||||
|
/
|
||||||
|
if isnotquote
|
||||||
parseexprvarref
|
parseexprvarref
|
||||||
/
|
/
|
||||||
|
/
|
||||||
if isnotspace
|
if isnotspace
|
||||||
emit "0"
|
emit "0"
|
||||||
/
|
/
|
||||||
@ -214,6 +235,98 @@ parsestatreturn indent:
|
|||||||
return
|
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:
|
parsestattrace indent:
|
||||||
declare varname
|
declare varname
|
||||||
emit indent
|
emit indent
|
||||||
@ -278,6 +391,11 @@ parsestat indent:
|
|||||||
parsestatreturn indent
|
parsestatreturn indent
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
calc iscall eq call "check"
|
||||||
|
if iscall
|
||||||
|
parsestatcheck indent
|
||||||
|
return
|
||||||
|
/
|
||||||
calc iscall eq call "trace"
|
calc iscall eq call "trace"
|
||||||
if iscall
|
if iscall
|
||||||
parsestattrace indent
|
parsestattrace indent
|
||||||
@ -471,35 +589,55 @@ emitheader:
|
|||||||
emitln " return 0;"
|
emitln " return 0;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "int LINE = 1;"
|
emitln "int STDINCOLNO = 1;"
|
||||||
|
emitln "int STDINLINENO = 1;"
|
||||||
|
emitln "char * STDINPEEK = 0;"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "char * peek()"
|
emitln "char * _readchar()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " char * res = malloc(2*sizeof(char));"
|
emitln " char * res = malloc(2*sizeof(char));"
|
||||||
emitln " res[0] = getc(stdin);"
|
emitln " res[0] = getc(stdin);"
|
||||||
emitln " res[1] = 0;"
|
emitln " res[1] = 0;"
|
||||||
emitln " ungetc(res[0], stdin);"
|
|
||||||
emitln " return res;"
|
emitln " return res;"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
|
emitln "char * peek()"
|
||||||
|
emitln "{"
|
||||||
|
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
|
||||||
|
emitln " return STDINPEEK;"
|
||||||
|
emitln "}"
|
||||||
|
emitln ""
|
||||||
emitln "void skip()"
|
emitln "void skip()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " char c = getc(stdin);"
|
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
|
||||||
emitln " if( c == 10 ) LINE += 1;"
|
emitln " if( STDINPEEK[0] == 10 ) {"
|
||||||
|
emitln " STDINLINENO += 1;"
|
||||||
|
emitln " STDINCOLNO = 0;"
|
||||||
|
emitln " }"
|
||||||
|
emitln " STDINCOLNO += 1;"
|
||||||
|
emitln " STDINPEEK = _readchar();"
|
||||||
emitln "}"
|
emitln "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "void skipchar(char * chr)"
|
emitln "char * stdinlineno()"
|
||||||
emitln "{"
|
emitln "{"
|
||||||
emitln " assert(strlen(chr) == 1);"
|
emitln " char * res = malloc(8*sizeof(char));"
|
||||||
emitln " char * act = peek();"
|
emit " sprintf(res, "
|
||||||
emitln " assert(strlen(act) == 1);"
|
|
||||||
emitln " if( chr[0] == act[0] ) {skip(); return;};"
|
|
||||||
emit " fprintf(stderr, "
|
|
||||||
emit quote
|
emit quote
|
||||||
emit "Expected '%c' on line %d but saw '%c' instead%c"
|
emit "%d"
|
||||||
emit quote
|
emit quote
|
||||||
emitln ", chr[0], LINE, act[0], 10);"
|
emitln ", STDINLINENO);"
|
||||||
emitln " exit(1);"
|
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 "}"
|
||||||
emitln ""
|
emitln ""
|
||||||
return
|
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
|
### 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
|
#### trace
|
||||||
|
|
||||||
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.
|
||||||
@ -133,12 +137,44 @@ 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.
|
||||||
|
|
||||||
Return true if a would sort before b.
|
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
|
#### peek
|
||||||
|
|
||||||
Checks stdin for the next character and returns it.
|
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.
|
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
|
### Typing
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +1,35 @@
|
|||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
.PRECIOUS: build/%.it0.py build/%.it0.c
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
PYVERSION=3.10
|
PYVERSION=3.12
|
||||||
PYPREFIX=/usr
|
PYPREFIX=/usr
|
||||||
CYTHON=cython3
|
CYTHON=cython3
|
||||||
CC=gcc
|
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
|
all: check
|
||||||
|
|
||||||
check: all-it0.results all-it1.results all-it2.results
|
check: all-it0.results all-it1.results all-it2.results
|
||||||
! grep -v 'Success' $^
|
! grep -v 'Success' $^
|
||||||
|
|
||||||
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST)))
|
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST))) build/builtincheckfalse.it0
|
||||||
-rm -f $@
|
-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 $@
|
-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 $@
|
-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:
|
clean:
|
||||||
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
||||||
@ -31,8 +37,12 @@ clean:
|
|||||||
###
|
###
|
||||||
# it0
|
# it0
|
||||||
|
|
||||||
|
../0-lang0py/lang0py.exe: ../0-lang0py/lang0py.py
|
||||||
|
$(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 > $@
|
cat $< | ../0-lang0py/lang0py.exe > $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
|
|
||||||
build/%.it0.c: build/%.it0.py
|
build/%.it0.c: build/%.it0.py
|
||||||
$(CYTHON) -3 --embed -o $@ $^
|
$(CYTHON) -3 --embed -o $@ $^
|
||||||
@ -46,8 +56,12 @@ build/%.it0: build/%.it0.o
|
|||||||
###
|
###
|
||||||
# it1
|
# 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
|
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
|
build/%.it1.c: build/%.it1.py
|
||||||
$(CYTHON) -3 --embed -o $@ $^
|
$(CYTHON) -3 --embed -o $@ $^
|
||||||
@ -61,8 +75,12 @@ build/%.it1: build/%.it1.o
|
|||||||
###
|
###
|
||||||
# it2
|
# 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
|
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
|
build/%.it2.o: build/%.it2.c
|
||||||
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
|
$(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.c
|
||||||
/*.it0.o
|
/*.it0.o
|
||||||
/*.it0.py
|
/*.it0.py
|
||||||
|
/*.it0.py.tmp
|
||||||
/*.it1
|
/*.it1
|
||||||
/*.it1.c
|
/*.it1.c
|
||||||
/*.it1.o
|
/*.it1.o
|
||||||
/*.it1.py
|
/*.it1.py
|
||||||
|
/*.it1.py.tmp
|
||||||
/*.it2
|
/*.it2
|
||||||
/*.it2.c
|
/*.it2.c
|
||||||
|
/*.it2.c.tmp
|
||||||
/*.it2.o
|
/*.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:
|
main:
|
||||||
declare result
|
declare result
|
||||||
calc result addstringchar "Succes" "s"
|
calc result addstringchar "abc" "d"
|
||||||
emit result
|
check eq result "abcd" : "Adding abc and d should be abcd"
|
||||||
|
emit "Success"
|
||||||
/
|
/
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
main:
|
main:
|
||||||
declare bool
|
declare bool
|
||||||
calc bool eq "1" "2"
|
calc bool eq "1" "2"
|
||||||
if bool
|
check not bool : "1 should not equal 2"
|
||||||
return
|
|
||||||
/
|
|
||||||
emit "Success"
|
emit "Success"
|
||||||
/
|
/
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
main:
|
main:
|
||||||
declare bool
|
declare bool
|
||||||
calc bool eq "1" "1"
|
check eq "1" "1" : "1 should equal 1"
|
||||||
if bool
|
|
||||||
emit "Success"
|
emit "Success"
|
||||||
/
|
/
|
||||||
/
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
main:
|
main:
|
||||||
declare bool
|
declare bool
|
||||||
calc bool lt "b" "a"
|
calc bool lt "b" "a"
|
||||||
if bool
|
check not bool : "a should should sort before b"
|
||||||
return
|
|
||||||
/
|
|
||||||
emit "Success"
|
emit "Success"
|
||||||
/
|
/
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
main:
|
main:
|
||||||
declare bool
|
declare bool
|
||||||
calc bool lt "a" "b"
|
check lt "a" "b" : "a should should sort before b"
|
||||||
if bool
|
|
||||||
emit "Success"
|
emit "Success"
|
||||||
/
|
/
|
||||||
/
|
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
main:
|
main:
|
||||||
declare char
|
declare char
|
||||||
declare ish
|
|
||||||
calc char peek
|
calc char peek
|
||||||
calc ish eq char "H"
|
check eq char "H" : "The first byte we're passed is expected to be an 'H'"
|
||||||
if ish
|
|
||||||
emit "Success"
|
emit "Success"
|
||||||
/
|
/
|
||||||
/
|
|
||||||
|
|||||||
@ -1,24 +1,12 @@
|
|||||||
main:
|
main:
|
||||||
declare char
|
declare char
|
||||||
declare ish
|
|
||||||
declare iso
|
|
||||||
declare notish
|
|
||||||
declare notiso
|
|
||||||
skip
|
skip
|
||||||
calc char peek
|
calc char peek
|
||||||
calc ish eq char "e"
|
check eq char "e" : "The second byte we're passed is expected to be an 'e'"
|
||||||
calc notish not ish
|
|
||||||
if notish
|
|
||||||
return
|
|
||||||
/
|
|
||||||
skip
|
skip
|
||||||
skip
|
skip
|
||||||
skip
|
skip
|
||||||
calc char peek
|
calc char peek
|
||||||
calc iso eq char "o"
|
check eq char "o" : "The fifth byte we're passed is expected to be an 'o'"
|
||||||
calc notiso not iso
|
|
||||||
if notish
|
|
||||||
return
|
|
||||||
/
|
|
||||||
emit "Success"
|
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