Compare commits

...

4 Commits

Author SHA1 Message Date
Johan B.W. de Vries
9ddd04dfa4 Start on llvm IR target
# Conflicts:
#	0-lang0py/lang0py.py
#	1-lang0py/lang0py.lang0
#	2-lang0c/lang0c.lang0
#	Makefile
#	README.md
2025-02-02 15:43:37 +01:00
Johan B.W. de Vries
a08084230e Adds emitln to reduce complexity 2025-02-02 15:30:40 +01:00
Johan B.W. de Vries
17841954de Added a number of tests
Fix: skip() would not work without peek() on iteration 0 or 1.
2025-02-02 15:13:03 +01:00
Johan B.W. de Vries
ad99832959 Reworked the directory structure, added start of test framework 2025-02-02 14:25:16 +01:00
42 changed files with 2058 additions and 484 deletions

4
0-lang0py/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/lang0py
/lang0py.c
/lang0py.exe
/lang0py.o

21
0-lang0py/Makefile Normal file
View File

@ -0,0 +1,21 @@
.SUFFIXES:
PYVERSION=3.10
PYPREFIX=/usr
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
CYTHON=cython3
# No previous iteration to reference
all: lang0py.exe
%.exe: %.o
gcc -o $@ $< -lpython$(PYVERSION)
%.o: %.c
gcc -c $< $(INCLUDES)
%.c: %.py
$(CYTHON) -3 --embed $<
clean:
rm -f lang0py.c lang0py.o lang0py.exe

4
0-lang0py/lang0py.lang0 Normal file
View File

@ -0,0 +1,4 @@
; This file does not exit
; Iteration 0 is always writing a compiler in an existing environment
; Sometimes that means binary, sometimes that means assembly
; Luckily, for us this means we can use Python.

View File

@ -27,6 +27,8 @@ def peek():
return PEEK
peek()
def skip():
global LINE
global PEEK
@ -41,6 +43,10 @@ def skipchar(char):
assert char == peek(), (LINE, char, peek())
skip()
def emitln(data):
emit(data)
emit(eol)
def lexident():
word = ''
while True:
@ -133,21 +139,21 @@ def parsestatif(indent):
emit(' ' * indent)
emit('if ')
parseexprvarref()
emit(':\n')
emitln(':')
skipchar(eol)
parseblock(indent + 1)
def parsestatforever(indent):
emit(' ' * indent)
emit('while True:\n')
emitln('while True:')
skipchar(eol)
parseblock(indent + 1)
def parsestatbreak(indent):
emit(' ' * indent)
emit('break\n')
emitln('break')
skipchar(eol)
def parsestatreturn(indent):
@ -170,7 +176,7 @@ def parsestattrace(indent):
emit(var_name)
emit('", ')
emit(var_name)
emit(')\n')
emitln(')')
def parsestat(indent):
call = lexident()
@ -225,7 +231,7 @@ def parsestat(indent):
skipchar(eol)
emit(')\n')
emitln(')')
def parseblock(indent):
while True:
@ -265,69 +271,71 @@ def parsefunc():
# Ahead declaration
skipchar('/')
skipchar(eol)
emit("):\n")
emit(" pass # ahead declaration\n")
emit("\n")
emitln("):")
emitln(" pass # ahead declaration")
emit(eol)
return
skipchar(':')
skipchar(eol)
emit('):\n')
emitln('):')
parseblock(1)
emit("\n")
emit(eol)
def emitheader():
emit("import os\n")
emit("import sys\n")
emit("\n")
emit("def eq(a, b):\n")
emit(" return a == b\n")
emit("\n")
emit("def lt(a, b):\n")
emit(" return a[0] < b[0]\n")
emit("\n")
emit("def addstringchar(a, b):\n")
emit(" return a + b[0]\n")
emit("\n")
emit("def emit(string):\n")
emit(" sys.stdout.write(string)\n")
emit("\n")
emit("def trace(header, value):\n")
emit(" if os.environ.get('TRACE'):\n")
emit(" sys.stderr.write(f'{header}={value!r}\\n')\n")
emit("\n")
emit("eof = chr(0)\n")
emit("eol = chr(10)\n")
emit("quote = chr(34)\n")
emit("PEEK = None\n")
emit("LINE = 1\n")
emit("\n")
emit("def peek():\n")
emit(" global PEEK\n")
emit(" if PEEK is None:\n")
emit(" char = sys.stdin.read(1)\n")
emit(" trace('char', char)\n")
emit(" if not char:\n")
emit(" PEEK = eof\n")
emit(" else:\n")
emit(" PEEK = char\n")
emit(" return PEEK\n")
emit("\n")
emit("def skip():\n")
emit(" global LINE\n")
emit(" global PEEK\n")
emit(" if eol == PEEK:\n")
emit(" LINE += 1\n")
emit(" PEEK = None\n")
emit("\n")
emit("def skipchar(char):\n")
emit(" global LINE\n")
emit(" assert char == peek(), (LINE, char, peek())\n")
emit(" skip()\n")
emit("\n")
emitln("import os")
emitln("import sys")
emitln("")
emitln("def eq(a, b):")
emitln(" return a == b")
emitln("")
emitln("def lt(a, b):")
emitln(" return a[0] < b[0]")
emitln("")
emitln("def addstringchar(a, b):")
emitln(" return a + b[0]")
emitln("")
emitln("def emit(string):")
emitln(" sys.stdout.write(string)")
emitln("")
emitln("def trace(header, value):")
emitln(" if os.environ.get('TRACE'):")
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("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("")
emitln("def skip():")
emitln(" global LINE")
emitln(" global PEEK")
emitln(" if eol == PEEK:")
emitln(" LINE += 1")
emitln(" PEEK = None")
emitln("")
emitln("def skipchar(char):")
emitln(" global LINE")
emitln(" assert char == peek(), (LINE, char, peek())")
emitln(" skip()")
emitln("")
def emitfooter():
emit("if __name__ == '__main__':\n")

4
1-lang0py/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/lang0py*.c
/lang0py*.exe
/lang0py*.o
/lang0py*.py

36
1-lang0py/Makefile Normal file
View File

@ -0,0 +1,36 @@
.SUFFIXES:
PYVERSION=3.10
PYPREFIX=/usr
INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
CYTHON=cython3
LANG0PY=$(CURDIR)/../0-lang0py/lang0py.exe
all: lang0py.exe
%.exe: %.o
gcc -o $@ $< -lpython$(PYVERSION)
%.o: %.c
gcc -c $< $(INCLUDES)
%.c: %.py
$(CYTHON) -3 --embed $<
lang0py0.py: lang0py.lang0 $(LANG0PY)
cat $< | $(LANG0PY) > $@
lang0py1.py: lang0py.lang0 lang0py0.exe
cat $< | ./lang0py0.exe > $@
# Cannot diff on the first iteration - platform change
lang0py2.py: lang0py.lang0 lang0py1.exe
cat $< | ./lang0py1.exe > $@
-diff lang0py1.py lang0py2.py
lang0py.py: lang0py.lang0 lang0py2.exe
cat $< | ./lang0py2.exe > $@
-diff lang0py2.py lang0py.py
clean:
rm -f lang0py*.py lang0py*.c lang0py*.o lang0py*.exe

View File

@ -1,3 +1,8 @@
emitln data:
emit data
emit eol
/
increaseindent indent:
calc indent addstringchar indent " "
calc indent addstringchar indent " "
@ -119,7 +124,7 @@ parsestatif indent:
emit indent
emit "if "
parseexprvarref
emit ":\n"
emitln ":"
skipchar eol
calc indent increaseindent indent
parseblock indent
@ -127,7 +132,7 @@ parsestatif indent:
parsestatforever indent:
emit indent
emit "while True:\n"
emitln "while True:"
skipchar eol
calc indent increaseindent indent
parseblock indent
@ -135,7 +140,7 @@ parsestatforever indent:
parsestatbreak indent:
emit indent
emit "break\n"
emitln "break"
skipchar eol
/
@ -162,7 +167,7 @@ parsestattrace indent:
emit quote
emit ", "
emit varname
emit ")\n"
emitln ")"
skipchar eol
/
@ -238,7 +243,7 @@ parsestat indent:
set first "0"
/
skipchar eol
emit ")\n"
emitln ")"
/
parseblock indent:
@ -307,72 +312,74 @@ parsefunc:
if iseoblock
skipchar "/"
skipchar eol
emit "):\n"
emit " pass # ahead declaration\n"
emit "\n"
emitln "):"
emitln " pass # ahead declaration"
emit eol
return
/
skipchar ":"
skipchar eol
emit "):\n"
emitln "):"
parseblock " "
emit "\n"
emit eol
/
emitheader:
emit "import os\n"
emit "import sys\n"
emit "\n"
emit "def eq(a, b):\n"
emit " return a == b\n"
emit "\n"
emit "def lt(a, b):\n"
emit " return a[0] < b[0]\n"
emit "\n"
emit "def addstringchar(a, b):\n"
emit " return a + b[0]\n"
emit "\n"
emit "def emit(string):\n"
emit " sys.stdout.write(string)\n"
emit "\n"
emit "def trace(header, value):\n"
emit " if os.environ.get('TRACE'):\n"
emit " sys.stderr.write(f'{header}={value!r}\\n')\n"
emit "\n"
emit "eof = chr(0)\n"
emit "eol = chr(10)\n"
emit "quote = chr(34)\n"
emit "PEEK = None\n"
emit "LINE = 1\n"
emit "\n"
emit "def peek():\n"
emit " global PEEK\n"
emit " if PEEK is None:\n"
emit " char = sys.stdin.read(1)\n"
emit " trace('char', char)\n"
emit " if not char:\n"
emit " PEEK = eof\n"
emit " else:\n"
emit " PEEK = char\n"
emit " return PEEK\n"
emit "\n"
emit "def skip():\n"
emit " global LINE\n"
emit " global PEEK\n"
emit " if eol == PEEK:\n"
emit " LINE += 1\n"
emit " PEEK = None\n"
emit "\n"
emit "def skipchar(char):\n"
emit " global LINE\n"
emit " assert char == peek(), (LINE, char, peek())\n"
emit " skip()\n"
emit "\n"
emitln "import os"
emitln "import sys"
emitln ""
emitln "def eq(a, b):"
emitln " return a == b"
emitln ""
emitln "def lt(a, b):"
emitln " return a[0] < b[0]"
emitln ""
emitln "def addstringchar(a, b):"
emitln " return a + b[0]"
emitln ""
emitln "def emit(string):"
emitln " sys.stdout.write(string)"
emitln ""
emitln "def trace(header, value):"
emitln " if os.environ.get('TRACE'):"
emitln " sys.stderr.write(f'{header}={value!r}\')"
emitln ""
emitln "eof = chr(0)"
emitln "eol = chr(10)"
emitln "quote = chr(34)"
emitln "PEEK = None"
emitln "LINE = 1"
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 ""
emitln "def skip():"
emitln " global LINE"
emitln " global PEEK"
emitln " if eol == PEEK:"
emitln " LINE += 1"
emitln " PEEK = None"
emitln ""
emitln "def skipchar(char):"
emitln " global LINE"
emitln " assert char == peek(), (LINE, char, peek())"
emitln " skip()"
emitln ""
/
emitfooter:
emit "if __name__ == '__main__':\n"
emit " main()\n"
emitln "if __name__ == '__main__':"
emitln " main()"
/
main:

4
2-lang0c/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/lang0c*.c
/lang0c*.exe
/lang0c*.o
/lang0c*.py

42
2-lang0c/Makefile Normal file
View File

@ -0,0 +1,42 @@
.SUFFIXES:
PYVERSION=3.10
PYPREFIX=/usr
INCLUDES=
CYTHON=cython3
LANG0PY=$(CURDIR)/../1-lang0py/lang0py.exe
all: lang0c.exe
%.exe: %.o
gcc -o $@ $<
%.o: %.c
gcc -c $<
lang0c0.py: lang0c.lang0 $(LANG0PY)
cat $< | $(LANG0PY) > $@
lang0c0.c: lang0c0.py
$(CYTHON) -3 --embed $<
lang0c0.o: lang0c0.c
gcc -c $< -I$(PYPREFIX)/include/python$(PYVERSION)
lang0c0.exe: lang0c0.o
gcc -o $@ $< -lpython$(PYVERSION)
lang0c1.c: lang0c.lang0 lang0c0.exe
cat $< | ./lang0c0.exe > $@
# Cannot diff on the first iteration - platform change
lang0c2.c: lang0c.lang0 lang0c1.exe
cat $< | ./lang0c1.exe > $@
-diff lang0c1.c lang0c2.c
lang0c.c: lang0c.lang0 lang0c2.exe
cat $< | ./lang0c2.exe > $@
-diff lang0c2.c lang0c.c
clean:
rm -f lang0c*.py lang0c*.c lang0c*.o lang0c*.exe

View File

@ -1,3 +1,8 @@
emitln data:
emit data
emit eol
/
increaseindent indent:
calc indent addstringchar indent " "
calc indent addstringchar indent " "
@ -155,34 +160,34 @@ parsestatif indent:
emit indent
emit "if ( 0 < strlen("
parseexprvarref
emit ") )\n"
emitln ") )"
emit indent
emit "{\n"
emitln "{"
skipchar eol
calc indentt increaseindent indent
parseblock indentt
emit indent
emit "}\n"
emitln "}"
return
/
parsestatforever indent:
declare indentt
emit indent
emit "while (1)\n"
emitln "while (1)"
emit indent
emit "{\n"
emitln "{"
skipchar eol
calc indentt increaseindent indent
parseblock indentt
emit indent
emit "}\n"
emitln "}"
return
/
parsestatbreak indent:
emit indent
emit "break;\n"
emitln "break;"
skipchar eol
return
/
@ -220,7 +225,7 @@ parsestattrace indent:
emit quote
emit ", var_"
emit varname
emit ");\n"
emitln ");"
skipchar eol
return
/
@ -307,7 +312,7 @@ parsestat indent:
set first "0"
/
skipchar eol
emit ");\n"
emitln ");"
return
/
@ -389,113 +394,114 @@ parsefunc:
if iseoblock
skipchar "/"
skipchar eol
emit ");"
emit "\n"
emitln ");"
return
/
skipchar ":"
skipchar eol
emit ")\n{\n"
emitln ")"
emitln "{"
parseblock " "
emit "}\n\n"
emitln "}"
emit eol
return
/
emitheader:
emit "#include <assert.h>\n"
emit "#include <stdio.h>\n"
emit "#include <stdlib.h>\n"
emit "#include <string.h>\n"
emit eol
emit eol
emit "char var_eof[2] = {-1, 0};\n"
emit "char var_eol[2] = {10, 0};\n"
emit "char var_quote[2] = {34, 0};\n"
emit "char var_false[1] = {0};\n"
emit "char var_true[2] = {'1', 0};\n"
emit eol
emit eol
emit "char * eq(char * a, char * b)\n"
emit "{\n"
emit " return (strcmp(a, b) == 0) ? var_true : var_false;\n"
emit "}\n"
emit "\n"
emit "char * lt(char * a, char * b)\n"
emit "{\n"
emit " return (strcmp(a, b) < 0) ? var_true : var_false;\n"
emit "}\n"
emit "char * not(char * a)\n"
emit "{\n"
emit " return (strcmp(a, var_true) != 0) ? var_true : var_false;\n"
emit "}\n"
emit "\n"
emit "char * addstringchar(char * str, char * chr)\n"
emit "{\n"
emit " int str_len = strlen(str);\n"
emit " assert(strlen(chr) == 1);\n"
emit " char * res = malloc((str_len + 2) * sizeof(char));\n"
emit " strcpy(res, str);\n"
emit " res[str_len + 0] = chr[0];\n"
emit " res[str_len + 1] = 0;\n"
emit " return res;\n"
emit "}\n"
emit "\n"
emit "char * emit(char * str)\n"
emit "{\n"
emit " fputs(str, stdout);\n"
emit " return 0;\n"
emit "}\n"
emit "\n"
emit "char * trace(char * var_name, char * var_value)\n"
emit "{\n"
emitln "#include <assert.h>"
emitln "#include <stdio.h>"
emitln "#include <stdlib.h>"
emitln "#include <string.h>"
emitln ""
emitln ""
emitln "char var_eof[2] = {-1, 0};"
emitln "char var_eol[2] = {10, 0};"
emitln "char var_quote[2] = {34, 0};"
emitln "char var_false[1] = {0};"
emitln "char var_true[2] = {'1', 0};"
emitln ""
emitln ""
emitln "char * eq(char * a, char * b)"
emitln "{"
emitln " return (strcmp(a, b) == 0) ? var_true : var_false;"
emitln "}"
emitln ""
emitln "char * lt(char * a, char * b)"
emitln "{"
emitln " return (strcmp(a, b) < 0) ? var_true : var_false;"
emitln "}"
emitln "char * not(char * a)"
emitln "{"
emitln " return (strcmp(a, var_true) != 0) ? var_true : var_false;"
emitln "}"
emitln ""
emitln "char * addstringchar(char * str, char * chr)"
emitln "{"
emitln " int str_len = strlen(str);"
emitln " assert(strlen(chr) == 1);"
emitln " char * res = malloc((str_len + 2) * sizeof(char));"
emitln " strcpy(res, str);"
emitln " res[str_len + 0] = chr[0];"
emitln " res[str_len + 1] = 0;"
emitln " return res;"
emitln "}"
emitln ""
emitln "char * emit(char * str)"
emitln "{"
emitln " fputs(str, stdout);"
emitln " return 0;"
emitln "}"
emitln ""
emitln "char * trace(char * var_name, char * var_value)"
emitln "{"
emit " const char * env_trace = getenv("
emit quote
emit "TRACE"
emit quote
emit ");\n"
emit " if( !env_trace ) return 0;\n"
emit " fputs(var_name, stderr);\n"
emitln ");"
emitln " if( !env_trace ) return 0;"
emitln " fputs(var_name, stderr);"
emit " fputs("
emit quote
emit "="
emit quote
emit ", stderr);\n"
emit " fputs(var_value, stderr);\n"
emit " fputs(var_eol, stderr);\n"
emit " return 0;\n"
emit "}\n"
emit eol
emit "int LINE = 1;\n"
emit eol
emit "char * peek()\n"
emit "{\n"
emit " char * res = malloc(2*sizeof(char));\n"
emit " res[0] = getc(stdin);\n"
emit " res[1] = 0;\n"
emit " ungetc(res[0], stdin);\n"
emit " return res;\n"
emit "}\n"
emit "\n"
emit "void skip()\n"
emit "{\n"
emit " char c = getc(stdin);\n"
emit " if( c == 10 ) LINE += 1;\n"
emit "}\n"
emit "\n"
emit "void skipchar(char * chr)\n"
emit "{\n"
emit " assert(strlen(chr) == 1);\n"
emit " char * act = peek();\n"
emit " assert(strlen(act) == 1);\n"
emit " if( chr[0] == act[0] ) {skip(); return;};\n"
emitln ", stderr);"
emitln " fputs(var_value, stderr);"
emitln " fputs(var_eol, stderr);"
emitln " return 0;"
emitln "}"
emitln ""
emitln "int LINE = 1;"
emitln ""
emitln "char * peek()"
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 "void skip()"
emitln "{"
emitln " char c = getc(stdin);"
emitln " if( c == 10 ) LINE += 1;"
emitln "}"
emitln ""
emitln "void skipchar(char * chr)"
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, "
emit quote
emit "Expected '%c' on line %d but saw '%c' instead%c"
emit quote
emit ", chr[0], LINE, act[0], 10);\n"
emit " exit(1);\n"
emit "}\n"
emit "\n"
emitln ", chr[0], LINE, act[0], 10);"
emitln " exit(1);"
emitln "}"
emitln ""
return
/

4
3-lang0ll/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/lang0c*.c
/lang0c*.exe
/lang0c*.ll
/lang0c*.o

42
3-lang0ll/Makefile Normal file
View 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
View 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);
}

BIN
3-lang0ll/foo.exe Executable file

Binary file not shown.

49
3-lang0ll/foo.ll Normal file
View File

@ -0,0 +1,49 @@
; ModuleID = 'foo.c'
source_filename = "foo.c"
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"
@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1
@.str.1 = private unnamed_addr constant [16 x i8] c"This is a test.\00", align 1
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @print(i8* noundef %0) #0 {
%2 = alloca i8*, align 8
store i8* %0, i8** %2, align 8
ret void
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @sum(i32 noundef %0, i32 noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
ret i32 %7
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i8*, align 8
store i32 0, i32* %1, align 4
store i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0), i8** %2, align 8
call void @print(i8* noundef getelementptr inbounds ([16 x i8], [16 x i8]* @.str.1, i64 0, i64 0))
%3 = call i32 @sum(i32 noundef 7, i32 noundef 15)
ret i32 %3
}
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 1}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"}

472
3-lang0ll/lang0ll.lang0 Normal file
View 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
/

608
3-lang0ll/lang0ll0.c Normal file
View File

@ -0,0 +1,608 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char var_eof[2] = {-1, 0};
char var_eol[2] = {10, 0};
char var_quote[2] = {34, 0};
char var_false[1] = {0};
char var_true[2] = {'1', 0};
char * eq(char * a, char * b)
{
return (strcmp(a, b) == 0) ? var_true : var_false;
}
char * lt(char * a, char * b)
{
return (strcmp(a, b) < 0) ? var_true : var_false;
}
char * not(char * a)
{
return (strcmp(a, var_true) != 0) ? var_true : var_false;
}
char * addstringchar(char * str, char * chr)
{
int str_len = strlen(str);
assert(strlen(chr) == 1);
char * res = malloc((str_len + 2) * sizeof(char));
strcpy(res, str);
res[str_len + 0] = chr[0];
res[str_len + 1] = 0;
return res;
}
char * emit(char * str)
{
fputs(str, stdout);
return 0;
}
char * trace(char * var_name, char * var_value)
{
const char * env_trace = getenv("TRACE");
if( !env_trace ) return 0;
fputs(var_name, stderr);
fputs("=", stderr);
fputs(var_value, stderr);
fputs(var_eol, stderr);
return 0;
}
int LINE = 1;
char * peek()
{
char * res = malloc(2*sizeof(char));
res[0] = getc(stdin);
res[1] = 0;
ungetc(res[0], stdin);
return res;
}
void skip()
{
char c = getc(stdin);
if( c == 10 ) LINE += 1;
}
void skipchar(char * chr)
{
assert(strlen(chr) == 1);
char * act = peek();
assert(strlen(act) == 1);
if( chr[0] == act[0] ) {skip(); return;};
fprintf(stderr, "Expected '%c' on line %d but saw '%c' instead%c", chr[0], LINE, act[0], 10);
exit(1);
}
char * increaseindent(char * var_indent)
{
var_indent = addstringchar(var_indent, " ");
var_indent = addstringchar(var_indent, " ");
var_indent = addstringchar(var_indent, " ");
var_indent = addstringchar(var_indent, " ");
return var_indent;
}
char * lexident()
{
char * var_char;
char * var_isbeforea;
char * var_isafterz;
char * var_word;
var_word = "";
while (1)
{
var_char = peek();
var_isbeforea = lt(var_char, "a");
if ( 0 < strlen(var_isbeforea) )
{
break;
}
var_isafterz = lt("z", var_char);
if ( 0 < strlen(var_isafterz) )
{
break;
}
var_word = addstringchar(var_word, var_char);
skip();
}
return var_word;
}
char * parseconststring()
{
char * var_char;
char * var_iseof;
char * var_isquote;
skipchar(var_quote);
while (1)
{
var_char = peek();
var_iseof = eq(var_char, var_eof);
if ( 0 < strlen(var_iseof) )
{
break;
}
var_isquote = eq(var_char, var_quote);
if ( 0 < strlen(var_isquote) )
{
break;
}
skip();
}
skipchar(var_quote);
emit("i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)");
return 0;
}
char * parseexprvarref()
{
char * var_varname;
var_varname = lexident();
emit("i8* %");
emit(var_varname);
return 0;
}
char * parseexprcall()
{
char * var_char;
char * var_first;
char * var_funcname;
char * var_isspace;
char * var_isnotspace;
char * var_isfirst;
char * var_isnotfirst;
char * var_isquote;
char * var_isnotquote;
var_funcname = lexident();
emit(var_funcname);
emit("(");
var_first = "1";
while (1)
{
var_char = peek();
var_isspace = eq(var_char, " ");
var_isnotspace = not(var_isspace);
if ( 0 < strlen(var_isnotspace) )
{
break;
}
skip();
var_isfirst = eq(var_first, "1");
var_isnotfirst = not(var_isfirst);
if ( 0 < strlen(var_isnotfirst) )
{
emit(", ");
}
var_char = peek();
var_isquote = eq(var_char, var_quote);
var_isnotquote = not(var_isquote);
if ( 0 < strlen(var_isquote) )
{
parseconststring();
}
if ( 0 < strlen(var_isnotquote) )
{
parseexprvarref();
}
var_first = "0";
}
emit(")");
return 0;
}
char * parsestatdeclare(char * var_indent)
{
char * var_var;
skipchar(" ");
var_var = lexident();
emit(var_indent);
emit("char * var_");
emit(var_var);
emit(";");
emit(var_eol);
skipchar(var_eol);
return 0;
}
char * parsestatset(char * var_indent)
{
char * var_var;
skipchar(" ");
var_var = lexident();
skipchar(" ");
emit(var_indent);
emit("var_");
emit(var_var);
emit(" = ");
parseconststring();
emit(";");
emit(var_eol);
skipchar(var_eol);
return 0;
}
char * parsestatcalc(char * var_indent)
{
char * var_var;
char * var_varidx;
skipchar(" ");
var_var = lexident();
skipchar(" ");
emit(var_indent);
emit("%");
emit(var_var);
var_varidx = mapgetkey("funcvarused", var_var);
var_varidx = intinc(var_varidx);
mapsetkey("funcvarused"var_var, var_varidx, );
emit(".");
emit(var_varidx);
emit(" = call i8* @");
parseexprcall();
emit(";");
emit(var_eol);
skipchar(var_eol);
return 0;
}
char * parseblock(char * var_indent);
char * parsestatif(char * var_indent)
{
char * var_indentt;
skipchar(" ");
emit(var_indent);
emit("if ( 0 < strlen(");
parseexprvarref();
emit(") )\n");
emit(var_indent);
emit("{\n");
skipchar(var_eol);
var_indentt = increaseindent(var_indent);
parseblock(var_indentt);
emit(var_indent);
emit("}\n");
return 0;
}
char * parsestatforever(char * var_indent)
{
char * var_indentt;
emit(var_indent);
emit("while (1)\n");
emit(var_indent);
emit("{\n");
skipchar(var_eol);
var_indentt = increaseindent(var_indent);
parseblock(var_indentt);
emit(var_indent);
emit("}\n");
return 0;
}
char * parsestatbreak(char * var_indent)
{
emit(var_indent);
emit("break;\n");
skipchar(var_eol);
return 0;
}
char * parsestatreturn(char * var_indent)
{
char * var_char;
char * var_isspace;
char * var_isnotspace;
emit(var_indent);
emit("ret ");
var_char = peek();
var_isspace = eq(var_char, " ");
var_isnotspace = not(var_isspace);
if ( 0 < strlen(var_isspace) )
{
skip();
parseexprvarref();
}
if ( 0 < strlen(var_isnotspace) )
{
emit("i18* 0");
}
emit(";");
emit(var_eol);
skipchar(var_eol);
return 0;
}
char * parsestattrace(char * var_indent)
{
char * var_varname;
emit(var_indent);
emit("trace(");
emit(var_quote);
skipchar(" ");
var_varname = lexident();
emit(var_varname);
emit(var_quote);
emit(", var_");
emit(var_varname);
emit(");\n");
skipchar(var_eol);
return 0;
}
char * parsestat(char * var_indent)
{
char * var_call;
char * var_char;
char * var_first;
char * var_iscall;
char * var_isfirst;
char * var_isspace;
char * var_isquote;
char * var_isnotfirst;
char * var_isnotspace;
char * var_isnotquote;
var_call = lexident();
trace("call", var_call);
var_iscall = eq(var_call, "declare");
if ( 0 < strlen(var_iscall) )
{
parsestatdeclare(var_indent);
return 0;
}
var_iscall = eq(var_call, "set");
if ( 0 < strlen(var_iscall) )
{
parsestatset(var_indent);
return 0;
}
var_iscall = eq(var_call, "calc");
if ( 0 < strlen(var_iscall) )
{
parsestatcalc(var_indent);
return 0;
}
var_iscall = eq(var_call, "if");
if ( 0 < strlen(var_iscall) )
{
parsestatif(var_indent);
return 0;
}
var_iscall = eq(var_call, "forever");
if ( 0 < strlen(var_iscall) )
{
parsestatforever(var_indent);
return 0;
}
var_iscall = eq(var_call, "break");
if ( 0 < strlen(var_iscall) )
{
parsestatbreak(var_indent);
return 0;
}
var_iscall = eq(var_call, "return");
if ( 0 < strlen(var_iscall) )
{
parsestatreturn(var_indent);
return 0;
}
var_iscall = eq(var_call, "trace");
if ( 0 < strlen(var_iscall) )
{
parsestattrace(var_indent);
return 0;
}
emit(var_indent);
emit(var_call);
emit("(");
var_first = "1";
while (1)
{
var_char = peek();
var_isspace = eq(var_char, " ");
var_isnotspace = not(var_isspace);
if ( 0 < strlen(var_isnotspace) )
{
break;
}
skip();
var_char = peek();
var_isquote = eq(var_char, var_quote);
var_isnotquote = not(var_isquote);
if ( 0 < strlen(var_isquote) )
{
parseconststring();
}
if ( 0 < strlen(var_isnotquote) )
{
parseexprvarref();
}
var_isfirst = eq(var_first, "1");
var_isnotfirst = not(var_isfirst);
if ( 0 < strlen(var_isnotfirst) )
{
emit(", ");
}
var_first = "0";
}
skipchar(var_eol);
emit(");\n");
return 0;
}
char * parseblock(char * var_indent)
{
char * var_char;
char * var_copy;
char * var_iseol;
char * var_isnoteol;
char * var_isdone;
char * var_iseoblock;
while (1)
{
while (1)
{
var_char = peek();
var_iseol = eq(var_char, var_eol);
var_isnoteol = not(var_iseol);
if ( 0 < strlen(var_isnoteol) )
{
break;
}
skip();
}
var_copy = " ";
while (1)
{
var_isdone = eq(var_copy, var_indent);
if ( 0 < strlen(var_isdone) )
{
break;
}
skipchar("\t");
var_copy = increaseindent(var_copy);
}
var_char = peek();
var_iseoblock = eq(var_char, "/");
if ( 0 < strlen(var_iseoblock) )
{
skip();
skipchar(var_eol);
break;
}
skipchar("\t");
parsestat(var_indent);
}
return 0;
}
char * parsefunc()
{
char * var_char;
char * var_first;
char * var_funcname;
char * var_iseoblock;
char * var_isfirst;
char * var_isspace;
char * var_isnotfirst;
char * var_isnotspace;
char * var_var;
mapclear("funcvarused");
var_funcname = lexident();
trace("funcname", var_funcname);
emit("define i8* @");
emit(var_funcname);
emit("(");
var_first = "1";
while (1)
{
var_char = peek();
var_isspace = eq(var_char, " ");
var_isnotspace = not(var_isspace);
if ( 0 < strlen(var_isnotspace) )
{
break;
}
skip();
var_var = lexident();
var_isfirst = eq(var_first, "1");
var_isnotfirst = not(var_isfirst);
if ( 0 < strlen(var_isnotfirst) )
{
emit(", ");
}
emit("i8* %");
emit(var_var);
mapsetkey("funcvarused""var", "0", );
emit("_0");
var_first = "0";
}
var_char = peek();
var_iseoblock = eq(var_char, "/");
if ( 0 < strlen(var_iseoblock) )
{
skipchar("/");
skipchar(var_eol);
emit(");");
emit("\n");
return 0;
}
skipchar(":");
skipchar(var_eol);
emit(")\n{\n");
parseblock(" ");
emit("}\n\n");
return 0;
}
char * emitheader()
{
emit("target datalayout = ");
emit(var_quote);
emit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128");
emit(var_quote);
emit(var_eol);
emit("target triple = ");
emit(var_quote);
emit("x86_64-pc-linux-gnu");
emit(var_quote);
emit(var_eol);
emit(var_eol);
emit("define i8* @addstringchar(i8* %0, i8* %1)");
emit(var_eol);
emit("{");
emit(var_eol);
emit(" ; todo");
emit(var_eol);
emit(" ret i8* %0;");
emit(var_eol);
emit("}");
emit(var_eol);
emit(var_eol);
return 0;
}
char * emitfooter()
{
emit("");
return 0;
}
char * main()
{
char * var_char;
char * var_iseof;
char * var_iseol;
char * var_isnoteol;
emitheader();
while (1)
{
var_char = peek();
var_iseof = eq(var_char, var_eof);
if ( 0 < strlen(var_iseof) )
{
break;
}
while (1)
{
var_char = peek();
var_iseol = eq(var_char, var_eol);
var_isnoteol = not(var_iseol);
if ( 0 < strlen(var_isnoteol) )
{
break;
}
skip();
}
parsefunc();
}
emitfooter();
return 0;
}

19
3-lang0ll/notes.ll Normal file
View 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

View File

@ -1,69 +1,11 @@
.SUFFIXES:
GCC_FLAGS := -g -O0 -Wall
all: it2-out
# it0-out.py => Hand made
it1-out0.py: it0-out.py it1-in.lang0
cat it1-in.lang0 | python3 it0-out.py > it1-out0.py
it1-out1.py: it1-out0.py it1-in.lang0
cat it1-in.lang0 | python3 it1-out0.py > it1-out1.py
# We can diff here since the target hasn't changed
# The target for it0 is the same as for it1
diff it1-out0.py it1-out1.py
it1-out2.py: it1-out1.py it1-in.lang0
cat it1-in.lang0 | python3 it1-out1.py > it1-out2.py
diff it1-out1.py it1-out2.py
it1-out3.py: it1-out2.py it1-in.lang0
cat it1-in.lang0 | python3 it1-out2.py > it1-out3.py
diff it1-out2.py it1-out3.py
it1-out.py: it1-out3.py
cp it1-out3.py it1-out.py
it2-out0.py: it1-out.py it2-in.lang0
cat it2-in.lang0 | python3 it1-out.py > it2-out0.py
# No gcc step since the target is still python here
it2-out1.c: it2-out0.py it2-in.lang0
cat it2-in.lang0 | python3 it2-out0.py > it2-out1.c
# diff it2-out0.py it2-out1.py Do not diff - the target changed so the output will be different
it2-out1: it2-out1.c
gcc it2-out1.c -o it2-out1 $(GCC_FLAGS)
it2-out2.c: it2-out1 it2-in.lang0
cat it2-in.lang0 | ./it2-out1 > it2-out2.c
diff it2-out1.c it2-out2.c
it2-out2: it2-out2.c
gcc it2-out2.c -o it2-out2 $(GCC_FLAGS)
it2-out3.c: it2-out2 it2-in.lang0
cat it2-in.lang0 | ./it2-out2 > it2-out3.c
diff it2-out2.c it2-out3.c
it2-out3: it2-out3.c
gcc it2-out3.c -o it2-out3 $(GCC_FLAGS)
it2-out: it2-out3
cp it2-out3 it2-out
all:
$(MAKE) -C 0-lang0py all
$(MAKE) -C 1-lang0py all
$(MAKE) -C 2-lang0c all
$(MAKE) -C tests all
clean:
-rm it1-out* it2-out*
$(MAKE) -C 0-lang0py clean
$(MAKE) -C 1-lang0py clean
$(MAKE) -C 2-lang0c clean
$(MAKE) -C tests clean

View File

@ -49,6 +49,32 @@ Indentation is done using tabs.
### 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
#### calc var func args*
@ -69,6 +95,10 @@ Sets var to "const".
Exits the deepest `forever` loop.
#### func args*
Calls the function name `func` with the given arguments. The result, if any, is ignored.
#### if arg
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`.
#### func args*
Calls the given function with the given arguments. The result, if any, is ignored.
### Builtins
#### trace
Writes the name and value of the variable passed to stderr if the TRACE environment variable is set.
#### 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.
### Standard library functions
#### addstringchar a b
@ -113,6 +129,48 @@ Creates a new string with `b` appended to `a`.
Writes the given string to standard output.
#### eq a b
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.

View File

@ -9,7 +9,7 @@
"x": 725,
"y": 306,
"width": 197,
"height": 76,
"height": 60,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -25,8 +25,8 @@
"type": 3
},
"seed": 902003894,
"version": 28,
"versionNonce": 1349374006,
"version": 30,
"versionNonce": 882148575,
"isDeleted": false,
"boundElements": [
{
@ -34,16 +34,16 @@
"id": "vC6ze8D2C_8xamOti_FDo"
}
],
"updated": 1736684246699,
"updated": 1738501880052,
"link": null,
"locked": false
},
{
"id": "vC6ze8D2C_8xamOti_FDo",
"type": "text",
"x": 752.9500732421875,
"y": 319,
"width": 141.099853515625,
"x": 734.580078125,
"y": 311,
"width": 177.83984375,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -58,20 +58,20 @@
"index": "a0V",
"roundness": null,
"seed": 1788670826,
"version": 19,
"versionNonce": 1785814954,
"version": 31,
"versionNonce": 1178825919,
"isDeleted": false,
"boundElements": null,
"updated": 1736684250287,
"boundElements": [],
"updated": 1738501880052,
"link": null,
"locked": false,
"text": "it0-out.py\n(hand written)",
"text": "0-lang0py/lang0py\n(hand written)",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "sa5DlHhxpJaKEJJQyQzX0",
"originalText": "it0-out.py\n(hand written)",
"originalText": "0-lang0py/lang0py\n(hand written)",
"autoResize": true,
"lineHeight": 1.25
},
@ -133,7 +133,7 @@
"version": 68,
"versionNonce": 1195221302,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684348736,
"link": null,
"locked": false,
@ -205,7 +205,7 @@
"version": 482,
"versionNonce": 2052650218,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -277,7 +277,7 @@
"version": 115,
"versionNonce": 1274068970,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684445213,
"link": null,
"locked": false,
@ -349,7 +349,7 @@
"version": 179,
"versionNonce": 2088933354,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684949700,
"link": null,
"locked": false,
@ -421,7 +421,7 @@
"version": 219,
"versionNonce": 600803830,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684961559,
"link": null,
"locked": false,
@ -493,7 +493,7 @@
"version": 529,
"versionNonce": 1524384362,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -565,7 +565,7 @@
"version": 580,
"versionNonce": 973746154,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -637,7 +637,7 @@
"version": 628,
"versionNonce": 632995178,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -689,9 +689,9 @@
{
"id": "wbK8T0IJWC6QMWKFsflZU",
"type": "text",
"x": 593.9500732421875,
"x": 593.7700576782227,
"y": 135,
"width": 141.099853515625,
"width": 141.4598846435547,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -706,20 +706,20 @@
"index": "a0l",
"roundness": null,
"seed": 864846774,
"version": 138,
"versionNonce": 1358166378,
"version": 145,
"versionNonce": 1419718257,
"isDeleted": false,
"boundElements": null,
"updated": 1736684351221,
"boundElements": [],
"updated": 1738502492344,
"link": null,
"locked": false,
"text": "it1-in.lang0\n(hand written)",
"text": "1-lang0py/\nlang0py0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "JpWSt6KcCpoXnoEq_GCJp",
"originalText": "it1-in.lang0\n(hand written)",
"originalText": "1-lang0py/\nlang0py0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -761,9 +761,9 @@
{
"id": "Mj0dEWiGr1Z9qT8mn8V3K",
"type": "text",
"x": 1356.4500732421875,
"x": 1361.7000579833984,
"y": 132.5,
"width": 141.099853515625,
"width": 130.59988403320312,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -778,20 +778,20 @@
"index": "a0l2",
"roundness": null,
"seed": 779040554,
"version": 554,
"versionNonce": 365292266,
"version": 565,
"versionNonce": 874960209,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502506673,
"link": null,
"locked": false,
"text": "it2-in.lang0\n(hand written)",
"text": "2-lang0c/\nlang0c0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "xdt3-HzXEKTWxrWigJjiT",
"originalText": "it2-in.lang0\n(hand written)",
"originalText": "2-lang0c/\nlang0c0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -833,9 +833,9 @@
{
"id": "5pAueU5y4qXjdgix_f5pa",
"type": "text",
"x": 768.9500732421875,
"x": 768.7700576782227,
"y": -61,
"width": 141.099853515625,
"width": 141.4598846435547,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -850,20 +850,20 @@
"index": "a0l8",
"roundness": null,
"seed": 471340598,
"version": 242,
"versionNonce": 645687542,
"version": 243,
"versionNonce": 896719295,
"isDeleted": false,
"boundElements": null,
"updated": 1736684455955,
"boundElements": [],
"updated": 1738502495388,
"link": null,
"locked": false,
"text": "it1-in.lang0\n(hand written)",
"text": "1-lang0py/\nlang0py0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "Vi9eTOIjQtbNC7zF_5rwS",
"originalText": "it1-in.lang0\n(hand written)",
"originalText": "1-lang0py/\nlang0py0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -905,9 +905,9 @@
{
"id": "hOjP8z6dti8Z5hpgB3d5b",
"type": "text",
"x": 903.9500732421875,
"x": 903.7700576782227,
"y": -252.25,
"width": 141.099853515625,
"width": 141.4598846435547,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -922,20 +922,20 @@
"index": "a0l8G",
"roundness": null,
"seed": 1843097770,
"version": 308,
"versionNonce": 1508581622,
"version": 309,
"versionNonce": 1367318047,
"isDeleted": false,
"boundElements": null,
"updated": 1736684957255,
"boundElements": [],
"updated": 1738502496300,
"link": null,
"locked": false,
"text": "it1-in.lang0\n(hand written)",
"text": "1-lang0py/\nlang0py0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "nq35O_LXfbGnImWL9Qc06",
"originalText": "it1-in.lang0\n(hand written)",
"originalText": "1-lang0py/\nlang0py0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -977,9 +977,9 @@
{
"id": "P9GsVng_mlohB8reiaQaw",
"type": "text",
"x": 1042.7000732421875,
"x": 1042.5200576782227,
"y": -443.5,
"width": 141.099853515625,
"width": 141.4598846435547,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -994,20 +994,20 @@
"index": "a0l8O",
"roundness": null,
"seed": 1003079478,
"version": 348,
"versionNonce": 1453458550,
"version": 349,
"versionNonce": 63585919,
"isDeleted": false,
"boundElements": null,
"updated": 1736684961559,
"boundElements": [],
"updated": 1738502497243,
"link": null,
"locked": false,
"text": "it1-in.lang0\n(hand written)",
"text": "1-lang0py/\nlang0py0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "sm_C3kQH3NnoN8GY0WsHa",
"originalText": "it1-in.lang0\n(hand written)",
"originalText": "1-lang0py/\nlang0py0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -1049,9 +1049,9 @@
{
"id": "ypQvCIgox5Ez78rMw8nJk",
"type": "text",
"x": 1531.4500732421875,
"x": 1536.7000579833984,
"y": -62.5,
"width": 141.099853515625,
"width": 130.59988403320312,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -1066,20 +1066,20 @@
"index": "a0lC",
"roundness": null,
"seed": 1922220522,
"version": 659,
"versionNonce": 1812183146,
"version": 660,
"versionNonce": 1720655071,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502509525,
"link": null,
"locked": false,
"text": "it2-in.lang0\n(hand written)",
"text": "2-lang0c/\nlang0c0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "FkKqusUxwu0Fdxigv0fZW",
"originalText": "it2-in.lang0\n(hand written)",
"originalText": "2-lang0c/\nlang0c0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -1121,9 +1121,9 @@
{
"id": "5JR6I1qRvymfZUCUFUEiC",
"type": "text",
"x": 1693.4500732421875,
"x": 1698.7000579833984,
"y": -248.5,
"width": 141.099853515625,
"width": 130.59988403320312,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -1138,20 +1138,20 @@
"index": "a0lE",
"roundness": null,
"seed": 887058026,
"version": 720,
"versionNonce": 1951147498,
"version": 721,
"versionNonce": 1934701887,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502510388,
"link": null,
"locked": false,
"text": "it2-in.lang0\n(hand written)",
"text": "2-lang0c/\nlang0c0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "EIr70q6Ecsh_k_mhXX_d1",
"originalText": "it2-in.lang0\n(hand written)",
"originalText": "2-lang0c/\nlang0c0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -1193,9 +1193,9 @@
{
"id": "2mQPed9SFteJcR4z6zGyt",
"type": "text",
"x": 1803.4500732421875,
"x": 1808.7000579833984,
"y": -429.5,
"width": 141.099853515625,
"width": 130.59988403320312,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
@ -1210,20 +1210,20 @@
"index": "a0lF",
"roundness": null,
"seed": 1202851626,
"version": 768,
"versionNonce": 1685533546,
"version": 769,
"versionNonce": 1994500511,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502511204,
"link": null,
"locked": false,
"text": "it2-in.lang0\n(hand written)",
"text": "2-lang0c/\nlang0c0.lang0",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "P5YHIvfxndgZtpw2M194q",
"originalText": "it2-in.lang0\n(hand written)",
"originalText": "2-lang0c/\nlang0c0.lang0",
"autoResize": true,
"lineHeight": 1.25
},
@ -1233,7 +1233,7 @@
"x": 876,
"y": 121,
"width": 195.0000000000001,
"height": 74.99999999999999,
"height": 60,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1249,8 +1249,8 @@
"type": 3
},
"seed": 1738165110,
"version": 320,
"versionNonce": 242867434,
"version": 322,
"versionNonce": 348133425,
"isDeleted": false,
"boundElements": [
{
@ -1258,17 +1258,17 @@
"type": "text"
}
],
"updated": 1736684364282,
"updated": 1738501921397,
"link": null,
"locked": false
},
{
"id": "MFQOMZ3Q8GWnWIOy737f6",
"type": "text",
"x": 920.2900619506836,
"y": 146,
"width": 106.41987609863281,
"height": 25,
"x": 911.3100509643555,
"y": 126,
"width": 124.37989807128906,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1282,27 +1282,27 @@
"index": "a0t",
"roundness": null,
"seed": 781897450,
"version": 334,
"versionNonce": 1304604586,
"version": 341,
"versionNonce": 722253937,
"isDeleted": false,
"boundElements": null,
"updated": 1736684364282,
"boundElements": [],
"updated": 1738502436384,
"link": null,
"locked": false,
"text": "it1-out0.py",
"text": "1-lang0py/\nlang0py0.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "xhGx8DjmbBrbJtwOztMKw",
"originalText": "it1-out0.py",
"originalText": "1-lang0py/\nlang0py0.exe",
"autoResize": true,
"lineHeight": 1.25
},
{
"id": "V4SlwrmLxEj5lu0skBUJ1",
"type": "rectangle",
"x": 1638.5,
"x": 1636.8333333333335,
"y": 118.5,
"width": 195.0000000000001,
"height": 74.99999999999999,
@ -1321,8 +1321,8 @@
"type": 3
},
"seed": 1180838326,
"version": 735,
"versionNonce": 1456551466,
"version": 736,
"versionNonce": 183022687,
"isDeleted": false,
"boundElements": [
{
@ -1330,17 +1330,17 @@
"type": "text"
}
],
"updated": 1736684934138,
"updated": 1738502399176,
"link": null,
"locked": false
},
{
"id": "uq1n89eIzIoEF64MTNtC0",
"type": "text",
"x": 1680.0600662231445,
"y": 143.5,
"width": 111.87986755371094,
"height": 25,
"x": 1677.5733846028647,
"y": 131,
"width": 113.5198974609375,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1354,20 +1354,20 @@
"index": "a0tG",
"roundness": null,
"seed": 1735849130,
"version": 750,
"versionNonce": 1549590762,
"version": 769,
"versionNonce": 368020433,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502474072,
"link": null,
"locked": false,
"text": "it2-out0.py",
"text": "2-lang0c/\nlang0c0.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "V4SlwrmLxEj5lu0skBUJ1",
"originalText": "it2-out0.py",
"originalText": "2-lang0c/\nlang0c0.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1409,10 +1409,10 @@
{
"id": "Y8BLkvSVXeE_VCIsnaqRY",
"type": "text",
"x": 1055.2600555419922,
"y": -52.00000000000001,
"width": 102.47988891601562,
"height": 25,
"x": 1046.280044555664,
"y": -64.5,
"width": 120.43991088867188,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1426,20 +1426,20 @@
"index": "a0u",
"roundness": null,
"seed": 15431402,
"version": 394,
"versionNonce": 1445402998,
"version": 402,
"versionNonce": 624349585,
"isDeleted": false,
"boundElements": null,
"updated": 1736684465162,
"boundElements": [],
"updated": 1738502440183,
"link": null,
"locked": false,
"text": "it1-out1.py",
"text": "1-lang0py/\nlang0py1.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "q7GdmXdIkEVil1E7K3Vtv",
"originalText": "it1-out1.py",
"originalText": "1-lang0py/\nlang0py1.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1481,10 +1481,10 @@
{
"id": "nB2NHk0Nl6BGmmPd2LQlN",
"type": "text",
"x": 1187.5300598144531,
"y": -243.25,
"width": 107.93988037109375,
"height": 25,
"x": 1178.550048828125,
"y": -255.75,
"width": 125.89990234375,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1498,20 +1498,20 @@
"index": "a0u2",
"roundness": null,
"seed": 993774442,
"version": 460,
"versionNonce": 789420906,
"version": 466,
"versionNonce": 407639167,
"isDeleted": false,
"boundElements": null,
"updated": 1736684954094,
"boundElements": [],
"updated": 1738502442119,
"link": null,
"locked": false,
"text": "it1-out2.py",
"text": "1-lang0py/\nlang0py2.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "4tXC4CO1352XEGgn5ZWPo",
"originalText": "it1-out2.py",
"originalText": "1-lang0py/\nlang0py2.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1553,10 +1553,10 @@
{
"id": "K8FKdMdbEtQXcBMy_4JGQ",
"type": "text",
"x": 1327.2000579833984,
"y": -434.5,
"width": 106.09988403320312,
"height": 25,
"x": 1324.3000411987305,
"y": -447,
"width": 111.89991760253906,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1570,20 +1570,20 @@
"index": "a0u3",
"roundness": null,
"seed": 414675062,
"version": 502,
"versionNonce": 1109378358,
"version": 507,
"versionNonce": 47527537,
"isDeleted": false,
"boundElements": null,
"updated": 1736684963415,
"boundElements": [],
"updated": 1738502444576,
"link": null,
"locked": false,
"text": "it1-out3.py",
"text": "1-lang0py/\nlang0py.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "_njzXhKgPzadFQfgDnI_E",
"originalText": "it1-out3.py",
"originalText": "1-lang0py/\nlang0py.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1625,10 +1625,10 @@
{
"id": "-3hZTUkUzcwcd4qQ6tH9Q",
"type": "text",
"x": 1533.4500579833984,
"y": 324.25,
"width": 106.09988403320312,
"height": 25,
"x": 1530.5500411987305,
"y": 311.75,
"width": 111.89991760253906,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1642,20 +1642,20 @@
"index": "a0u8",
"roundness": null,
"seed": 1942100970,
"version": 523,
"versionNonce": 1708469866,
"version": 527,
"versionNonce": 1763250065,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502452896,
"link": null,
"locked": false,
"text": "it1-out3.py",
"text": "1-lang0py/\nlang0py.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "ZjoMA7OeaNnjNpaVjFLsc",
"originalText": "it1-out3.py",
"originalText": "1-lang0py/\nlang0py.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1697,10 +1697,10 @@
{
"id": "gSS5ui-65NHgMOUQh5qaI",
"type": "text",
"x": 1820.8600616455078,
"y": -54.5,
"width": 96.27987670898438,
"height": 25,
"x": 1814.2100448608398,
"y": -67,
"width": 109.57991027832031,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1714,20 +1714,20 @@
"index": "a0uV",
"roundness": null,
"seed": 2126958442,
"version": 761,
"versionNonce": 1958222826,
"version": 771,
"versionNonce": 1871453791,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502478104,
"link": null,
"locked": false,
"text": "it2-out1.c",
"text": "2-lang0c/\nlang0c1.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "_dSfxbsy4dHEcZZ5zwehT",
"originalText": "it2-out1.c",
"originalText": "2-lang0c/\nlang0c1.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1769,10 +1769,10 @@
{
"id": "0RfiY6ME4YQvG93V4ZTf7",
"type": "text",
"x": 1922.1300659179688,
"y": -233.5,
"width": 101.7398681640625,
"height": 25,
"x": 1915.4800491333008,
"y": -246,
"width": 115.03990173339844,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1786,20 +1786,20 @@
"index": "a0uZ",
"roundness": null,
"seed": 1038423094,
"version": 823,
"versionNonce": 1725802858,
"version": 832,
"versionNonce": 606612113,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502480152,
"link": null,
"locked": false,
"text": "it2-out2.c",
"text": "2-lang0c/\nlang0c2.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "7AT_y3BQx_MTOK2YJ5gyT",
"originalText": "it2-out2.c",
"originalText": "2-lang0c/\nlang0c2.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1841,10 +1841,10 @@
{
"id": "yJu3JDSgZH2EElzwcEo8a",
"type": "text",
"x": 2038.050064086914,
"y": -418.5,
"width": 99.89987182617188,
"height": 25,
"x": 2037.4800415039062,
"y": -431,
"width": 101.0399169921875,
"height": 50,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
@ -1858,20 +1858,20 @@
"index": "a0ub",
"roundness": null,
"seed": 1154290486,
"version": 865,
"versionNonce": 69064426,
"version": 868,
"versionNonce": 1145930655,
"isDeleted": false,
"boundElements": null,
"updated": 1736684934138,
"boundElements": [],
"updated": 1738502483040,
"link": null,
"locked": false,
"text": "it2-out3.c",
"text": "2-lang0c/\nlang0c.exe",
"fontSize": 20,
"fontFamily": 5,
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "wtdGNdh8BUiQz-JxcpA_L",
"originalText": "it2-out3.c",
"originalText": "2-lang0c/\nlang0c.exe",
"autoResize": true,
"lineHeight": 1.25
},
@ -1900,7 +1900,7 @@
"version": 59,
"versionNonce": 2125545782,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684495257,
"link": null,
"locked": false,
@ -1946,7 +1946,7 @@
"version": 124,
"versionNonce": 1720455530,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684957255,
"link": null,
"locked": false,
@ -1992,7 +1992,7 @@
"version": 163,
"versionNonce": 1556910134,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684961559,
"link": null,
"locked": false,
@ -2038,7 +2038,7 @@
"version": 472,
"versionNonce": 550988202,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -2084,7 +2084,7 @@
"version": 532,
"versionNonce": 2119214186,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,
@ -2130,7 +2130,7 @@
"version": 579,
"versionNonce": 911509290,
"isDeleted": false,
"boundElements": null,
"boundElements": [],
"updated": 1736684934138,
"link": null,
"locked": false,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 143 KiB

1
tests/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.results

71
tests/Makefile Normal file
View File

@ -0,0 +1,71 @@
.SUFFIXES:
.PHONY: all clean
PYVERSION=3.10
PYPREFIX=/usr
CYTHON=cython3
CC=gcc
TESTLIST=$(shell ls *.lang0 | 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)))
-rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST)))
-rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST)))
-rm -f $@
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; echo "Hello" | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
clean:
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
###
# it0
build/%.it0.py: %.lang0 ../0-lang0py/lang0py.exe
cat $< | ../0-lang0py/lang0py.exe > $@
build/%.it0.c: build/%.it0.py
$(CYTHON) -3 --embed -o $@ $^
build/%.it0.o: build/%.it0.c
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
build/%.it0: build/%.it0.o
$(CC) -o $@ $^ -lpython$(PYVERSION)
###
# it1
build/%.it1.py: %.lang0 ../1-lang0py/lang0py.exe
cat $< | ../1-lang0py/lang0py.exe > $@
build/%.it1.c: build/%.it1.py
$(CYTHON) -3 --embed -o $@ $^
build/%.it1.o: build/%.it1.c
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
build/%.it1: build/%.it1.o
$(CC) -o $@ $^ -lpython$(PYVERSION)
###
# it2
build/%.it2.c: %.lang0 ../2-lang0c/lang0c.exe
cat $< | ../2-lang0c/lang0c.exe > $@
build/%.it2.o: build/%.it2.c
$(CC) -o $@ -c $^ -I$(PYPREFIX)/include/python$(PYVERSION)
build/%.it2: build/%.it2.o
$(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
/

3
tests/stdlibemit.lang0 Normal file
View File

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

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
/