Adds check builtin

This commit is contained in:
Johan B.W. de Vries 2025-02-09 15:02:25 +01:00
parent 931a861fef
commit 5fa042c5cd
14 changed files with 251 additions and 39 deletions

View File

@ -166,6 +166,53 @@ def parsestatreturn(indent):
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)
@ -211,6 +258,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

View File

@ -157,6 +157,82 @@ parsestatreturn indent:
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 +290,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 "("

View File

@ -214,6 +214,88 @@ 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 "{"
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 +360,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

View File

@ -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.

View File

@ -8,23 +8,27 @@ 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 $@
echo "Hello" | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;) $(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 $@ -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 "" >> $@ ;) $(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 $@ -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 "" >> $@ ;) $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
clean: clean:

View File

@ -0,0 +1,3 @@
main:
check not "1" : "Success"
/

View File

@ -0,0 +1,4 @@
main:
check not "" : "Failure"
emit "Success"
/

View File

@ -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"
/ /

View File

@ -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"
/ /

View File

@ -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"
/
/ /

View File

@ -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"
/ /

View File

@ -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"
/
/ /

View File

@ -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"
/
/ /

View File

@ -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"
/ /