Added a number of tests

Fix: skip() would not work without peek() on iteration 0 or 1.
This commit is contained in:
Johan B.W. de Vries 2025-02-02 15:13:03 +01:00
parent ad99832959
commit 17841954de
23 changed files with 237 additions and 64 deletions

View File

@ -27,6 +27,8 @@ def peek():
return PEEK return PEEK
peek()
def skip(): def skip():
global LINE global LINE
global PEEK global PEEK
@ -316,6 +318,8 @@ def emitheader():
emit(" PEEK = char\n") emit(" PEEK = char\n")
emit(" return PEEK\n") emit(" return PEEK\n")
emit("\n") emit("\n")
emit("peek()\n")
emit("\n")
emit("def skip():\n") emit("def skip():\n")
emit(" global LINE\n") emit(" global LINE\n")
emit(" global PEEK\n") emit(" global PEEK\n")

View File

@ -309,42 +309,42 @@ parsefunc:
skipchar eol skipchar eol
emit "):\n" emit "):\n"
emit " pass # ahead declaration\n" emit " pass # ahead declaration\n"
emit "\n" emit eol
return return
/ /
skipchar ":" skipchar ":"
skipchar eol skipchar eol
emit "):\n" emit "):\n"
parseblock " " parseblock " "
emit "\n" emit eol
/ /
emitheader: emitheader:
emit "import os\n" emit "import os\n"
emit "import sys\n" emit "import sys\n"
emit "\n" emit eol
emit "def eq(a, b):\n" emit "def eq(a, b):\n"
emit " return a == b\n" emit " return a == b\n"
emit "\n" emit eol
emit "def lt(a, b):\n" emit "def lt(a, b):\n"
emit " return a[0] < b[0]\n" emit " return a[0] < b[0]\n"
emit "\n" emit eol
emit "def addstringchar(a, b):\n" emit "def addstringchar(a, b):\n"
emit " return a + b[0]\n" emit " return a + b[0]\n"
emit "\n" emit eol
emit "def emit(string):\n" emit "def emit(string):\n"
emit " sys.stdout.write(string)\n" emit " sys.stdout.write(string)\n"
emit "\n" emit eol
emit "def trace(header, value):\n" emit "def trace(header, value):\n"
emit " if os.environ.get('TRACE'):\n" emit " if os.environ.get('TRACE'):\n"
emit " sys.stderr.write(f'{header}={value!r}\\n')\n" emit " sys.stderr.write(f'{header}={value!r}\\n')\n"
emit "\n" emit eol
emit "eof = chr(0)\n" emit "eof = chr(0)\n"
emit "eol = chr(10)\n" emit "eol = chr(10)\n"
emit "quote = chr(34)\n" emit "quote = chr(34)\n"
emit "PEEK = None\n" emit "PEEK = None\n"
emit "LINE = 1\n" emit "LINE = 1\n"
emit "\n" emit eol
emit "def peek():\n" emit "def peek():\n"
emit " global PEEK\n" emit " global PEEK\n"
emit " if PEEK is None:\n" emit " if PEEK is None:\n"
@ -355,19 +355,21 @@ emitheader:
emit " else:\n" emit " else:\n"
emit " PEEK = char\n" emit " PEEK = char\n"
emit " return PEEK\n" emit " return PEEK\n"
emit "\n" emit eol
emit "peek()\n"
emit eol
emit "def skip():\n" emit "def skip():\n"
emit " global LINE\n" emit " global LINE\n"
emit " global PEEK\n" emit " global PEEK\n"
emit " if eol == PEEK:\n" emit " if eol == PEEK:\n"
emit " LINE += 1\n" emit " LINE += 1\n"
emit " PEEK = None\n" emit " PEEK = None\n"
emit "\n" emit eol
emit "def skipchar(char):\n" emit "def skipchar(char):\n"
emit " global LINE\n" emit " global LINE\n"
emit " assert char == peek(), (LINE, char, peek())\n" emit " assert char == peek(), (LINE, char, peek())\n"
emit " skip()\n" emit " skip()\n"
emit "\n" emit eol
/ /
emitfooter: emitfooter:

View File

@ -49,6 +49,32 @@ Indentation is done using tabs.
### Parsing ### Parsing
#### Pre declaration (functions)
Functions need to be pre-declared if you intend to use them before you have defined them:
```
func result/
...
func result:
return result
/
```
#### Pre declaration (variables)
Variables will need to be declared before you can use them:
```
func:
declare result
set result "Result"
return result
/
```
### Variables ### Variables
#### calc var func args* #### calc var func args*
@ -69,6 +95,10 @@ Sets var to "const".
Exits the deepest `forever` loop. Exits the deepest `forever` loop.
#### func args*
Calls the function name `func` with the given arguments. The result, if any, is ignored.
#### if arg #### if arg
Evaluates arg. If found to be true, descends in the block. Otherwise, skips the block Evaluates arg. If found to be true, descends in the block. Otherwise, skips the block
@ -81,27 +111,13 @@ Repeats the block until `break` or `return` is called.
Returns the given value. You can not give an argument if your function is never used in `call`. Returns the given value. You can not give an argument if your function is never used in `call`.
#### func args*
Calls the given function with the given arguments. The result, if any, is ignored.
### Builtins ### Builtins
#### 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.
#### Standard library functions ### Standard library functions
#### eq a b
Return true if the given strings are the same.
#### lt a b
`a` and `b` are expected to have length 1.
Return true if a would sort before b.
#### addstringchar a b #### addstringchar a b
@ -113,6 +129,16 @@ Creates a new string with `b` appended to `a`.
Writes the given string to standard output. Writes the given string to standard output.
#### eq a b
Return true if the given strings are the same.
#### lt a b
`a` and `b` are expected to have length 1.
Return true if a would sort before b.
#### peek #### peek
Checks stdin for the next character and returns it. Checks stdin for the next character and returns it.

11
tests/.gitignore vendored
View File

@ -1,12 +1 @@
/*.it0
/*.it0.c
/*.it0.o
/*.it0.py
/*.it1
/*.it1.c
/*.it1.o
/*.it1.py
/*.it2
/*.it2.c
/*.it2.o
/*.results /*.results

View File

@ -8,64 +8,64 @@ CC=gcc
TESTLIST=$(shell ls *.lang0 | sed 's/.lang0//') TESTLIST=$(shell ls *.lang0 | sed 's/.lang0//')
all: all-it0.results all-it1.results all-it2.results all: check
all-it0.results: $(addsuffix .it0, $(TESTLIST)) check: all-it0.results all-it1.results all-it2.results
-rm -f $@ ! grep -v 'Success' $^
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; ./$(test).it0 >> $@ ; echo "" >> $@)
! grep -v 'Success' $@
all-it1.results: $(addsuffix .it1, $(TESTLIST)) all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST)))
-rm -f $@ -rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; ./$(test).it1 >> $@ ; echo "" >> $@) $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
! grep -v 'Success' $@
all-it2.results: $(addsuffix .it2, $(TESTLIST)) all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST)))
-rm -f $@ -rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; ./$(test).it2 >> $@ ; echo "" >> $@) $(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
! grep -v 'Success' $@
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST)))
-rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
clean: clean:
-rm -f *.result *.it0* *.it1* *.it2* -rm -f *.results build/*.it0* build/*.it1* build/*.it2*
### ###
# it0 # it0
%.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 > $@
%.it0.c: %.it0.py build/%.it0.c: build/%.it0.py
$(CYTHON) -3 --embed -o $@ $^ $(CYTHON) -3 --embed -o $@ $^
%.it0.o: %.it0.c build/%.it0.o: build/%.it0.c
$(CC) -c $^ -I$(PYPREFIX)/include/python$(PYVERSION) $(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
%.it0: %.it0.o build/%.it0: build/%.it0.o
$(CC) -o $@ $^ -lpython$(PYVERSION) $(CC) -o $@ $^ -lpython$(PYVERSION)
### ###
# it1 # it1
%.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 > $@
%.it1.c: %.it1.py build/%.it1.c: build/%.it1.py
$(CYTHON) -3 --embed -o $@ $^ $(CYTHON) -3 --embed -o $@ $^
%.it1.o: %.it1.c build/%.it1.o: build/%.it1.c
$(CC) -c $^ -I$(PYPREFIX)/include/python$(PYVERSION) $(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
%.it1: %.it1.o build/%.it1: build/%.it1.o
$(CC) -o $@ $^ -lpython$(PYVERSION) $(CC) -o $@ $^ -lpython$(PYVERSION)
### ###
# it2 # it2
%.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 > $@
%.it2.o: %.it2.c build/%.it2.o: build/%.it2.c
$(CC) -c $^ -I$(PYPREFIX)/include/python$(PYVERSION) $(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
%.it2: %.it2.o build/%.it2: build/%.it2.o
$(CC) -o $@ $^ -lpython$(PYVERSION) $(CC) -o $@ $^ -lpython$(PYVERSION)

11
tests/build/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/*.it0
/*.it0.c
/*.it0.o
/*.it0.py
/*.it1
/*.it1.c
/*.it1.o
/*.it1.py
/*.it2
/*.it2.c
/*.it2.o

6
tests/flowbreak.lang0 Normal file
View File

@ -0,0 +1,6 @@
main:
forever
break
/
emit "Success"
/

8
tests/flowcall.lang0 Normal file
View File

@ -0,0 +1,8 @@
func:
emit "Success"
return
/
main:
func
/

8
tests/flowiffalse.lang0 Normal file
View File

@ -0,0 +1,8 @@
main:
declare bool
set bool ""
if bool
return
/
emit "Success"
/

7
tests/flowiftrue.lang0 Normal file
View File

@ -0,0 +1,7 @@
main:
declare bool
set bool "1"
if bool
emit "Success"
/
/

View File

@ -0,0 +1,8 @@
func:
return
/
main:
func
emit "Success"
/

View File

@ -0,0 +1,11 @@
func:
declare result
set result "Success"
return result
/
main:
declare result
calc result func
emit result
/

View File

@ -0,0 +1,11 @@
func result/
main:
declare result
calc result func "Success"
emit result
/
func result:
return result
/

View File

@ -0,0 +1,5 @@
main:
declare result
calc result addstringchar "Succes" "s"
emit result
/

View File

@ -0,0 +1,8 @@
main:
declare bool
calc bool eq "1" "2"
if bool
return
/
emit "Success"
/

7
tests/stdlibeqtrue.lang0 Normal file
View File

@ -0,0 +1,7 @@
main:
declare bool
calc bool eq "1" "1"
if bool
emit "Success"
/
/

View File

@ -0,0 +1,8 @@
main:
declare bool
calc bool lt "b" "a"
if bool
return
/
emit "Success"
/

7
tests/stdliblttrue.lang0 Normal file
View File

@ -0,0 +1,7 @@
main:
declare bool
calc bool lt "a" "b"
if bool
emit "Success"
/
/

9
tests/stdlibpeek.lang0 Normal file
View File

@ -0,0 +1,9 @@
main:
declare char
declare ish
calc char peek
calc ish eq char "H"
if ish
emit "Success"
/
/

24
tests/stdlibskip.lang0 Normal file
View File

@ -0,0 +1,24 @@
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
/
skip
skip
skip
calc char peek
calc iso eq char "o"
calc notiso not iso
if notish
return
/
emit "Success"
/

View File

@ -0,0 +1,9 @@
func result:
return result
/
main:
declare result
calc result func "Success"
emit result
/

5
tests/variablesset.lang0 Normal file
View File

@ -0,0 +1,5 @@
main:
declare result
set result "Success"
emit result
/