diff --git a/0-lang0py/lang0py.py b/0-lang0py/lang0py.py index f990edb..089888f 100644 --- a/0-lang0py/lang0py.py +++ b/0-lang0py/lang0py.py @@ -166,6 +166,53 @@ def parsestatreturn(indent): 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) @@ -211,6 +258,10 @@ def parsestat(indent): parsestatreturn(indent) return + if call == "check": + parsestatcheck(indent) + return + if call == "trace": parsestattrace(indent) return diff --git a/1-lang0py/lang0py.lang0 b/1-lang0py/lang0py.lang0 index 929b837..0628b7b 100644 --- a/1-lang0py/lang0py.lang0 +++ b/1-lang0py/lang0py.lang0 @@ -157,6 +157,82 @@ parsestatreturn indent: 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 +290,11 @@ parsestat indent: parsestattrace indent return / + calc ischeck eq call "check" + if ischeck + parsestatcheck indent + return + / emit indent emit call emit "(" diff --git a/2-lang0c/lang0c.lang0 b/2-lang0c/lang0c.lang0 index fdf9287..7b6cbca 100644 --- a/2-lang0c/lang0c.lang0 +++ b/2-lang0c/lang0c.lang0 @@ -214,6 +214,88 @@ 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 "{" + + 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 +360,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 diff --git a/README.md b/README.md index d14e8ea..082ac23 100644 --- a/README.md +++ b/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. diff --git a/tests/Makefile b/tests/Makefile index 510228f..030c87c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,23 +8,27 @@ 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 $@ + echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success' $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;) -all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) +all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it0 -rm -f $@ + echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success' $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;) -all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) +all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it0 -rm -f $@ + echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success' $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;) clean: diff --git a/tests/builtincheckfalse.lang0 b/tests/builtincheckfalse.lang0 new file mode 100644 index 0000000..a433392 --- /dev/null +++ b/tests/builtincheckfalse.lang0 @@ -0,0 +1,3 @@ +main: + check not "1" : "Success" +/ diff --git a/tests/builtinchecktrue.lang0 b/tests/builtinchecktrue.lang0 new file mode 100644 index 0000000..3566241 --- /dev/null +++ b/tests/builtinchecktrue.lang0 @@ -0,0 +1,4 @@ +main: + check not "" : "Failure" + emit "Success" +/ diff --git a/tests/stdlibaddstringchar.lang0 b/tests/stdlibaddstringchar.lang0 index 5d83c80..991f778 100644 --- a/tests/stdlibaddstringchar.lang0 +++ b/tests/stdlibaddstringchar.lang0 @@ -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" / diff --git a/tests/stdlibeqfalse.lang0 b/tests/stdlibeqfalse.lang0 index e2e52d3..5c66e3c 100644 --- a/tests/stdlibeqfalse.lang0 +++ b/tests/stdlibeqfalse.lang0 @@ -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" / diff --git a/tests/stdlibeqtrue.lang0 b/tests/stdlibeqtrue.lang0 index dd44ca0..f495e10 100644 --- a/tests/stdlibeqtrue.lang0 +++ b/tests/stdlibeqtrue.lang0 @@ -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" / diff --git a/tests/stdlibltfalse.lang0 b/tests/stdlibltfalse.lang0 index 0a7ad58..4963cfc 100644 --- a/tests/stdlibltfalse.lang0 +++ b/tests/stdlibltfalse.lang0 @@ -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" / diff --git a/tests/stdliblttrue.lang0 b/tests/stdliblttrue.lang0 index f3f3433..8c3ca69 100644 --- a/tests/stdliblttrue.lang0 +++ b/tests/stdliblttrue.lang0 @@ -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" / diff --git a/tests/stdlibpeek.lang0 b/tests/stdlibpeek.lang0 index 9455c7b..713f261 100644 --- a/tests/stdlibpeek.lang0 +++ b/tests/stdlibpeek.lang0 @@ -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" / diff --git a/tests/stdlibskip.lang0 b/tests/stdlibskip.lang0 index 1392458..e6e4ae0 100644 --- a/tests/stdlibskip.lang0 +++ b/tests/stdlibskip.lang0 @@ -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" /