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
48 changed files with 1535 additions and 592 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/it0-out0.diff
/it1-out*
/it2-out*
/it3-out*

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,9 +43,9 @@ def skipchar(char):
assert char == peek(), (LINE, char, peek())
skip()
def fileget(path):
with open(f'./{path}', encoding='ASCII') as fil:
return fil.read()
def emitln(data):
emit(data)
emit(eol)
def lexident():
word = ''
@ -137,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):
@ -174,7 +176,7 @@ def parsestattrace(indent):
emit(var_name)
emit('", ')
emit(var_name)
emit(')\n')
emitln(')')
def parsestat(indent):
call = lexident()
@ -229,7 +231,7 @@ def parsestat(indent):
skipchar(eol)
emit(')\n')
emitln(')')
def parseblock(indent):
while True:
@ -269,27 +271,75 @@ 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():
header = fileget("it0-in-header.py")
emit(header)
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():
footer = fileget("it0-in-footer.py")
emit(footer)
emit("if __name__ == '__main__':\n")
emit(" main()\n")
def main():
emitheader()

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,26 +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:
calc header fileget "it1-in-header.py"
emit header
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:
calc header fileget "it1-in-footer.py"
emit header
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
/
@ -290,11 +295,6 @@ parsestat indent:
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
@ -304,10 +304,15 @@ parsestat indent:
if isnotquote
parseexprvarref
/
calc isfirst eq first "1"
calc isnotfirst not isfirst
if isnotfirst
emit ", "
/
set first "0"
/
skipchar eol
emit ");\n"
emitln ");"
return
/
@ -389,26 +394,119 @@ 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:
declare header
calc header fileget "it2-in-header.c"
emit header
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
emitln ");"
emitln " if( !env_trace ) return 0;"
emitln " fputs(var_name, stderr);"
emit " fputs("
emit quote
emit "="
emit quote
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
emitln ", chr[0], LINE, act[0], 10);"
emitln " exit(1);"
emitln "}"
emitln ""
return
/
emitfooter:
emit ""
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

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"}

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;
}

100
Makefile
View File

@ -1,93 +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 > $@
# 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 $^ -o $@ $(GCC_FLAGS)
it2-out2.c: it2-out1 it2-in.lang0
cat it2-in.lang0 | ./it2-out1 > $@
diff it2-out1.c $@
it2-out2: it2-out2.c
gcc $^ -o $@ $(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 $^ -o $@ $(GCC_FLAGS)
it2-out: it2-out3
cp it2-out3 it2-out
it3-out0.c: it2-out it3-in.lang0
cat it3-in.lang0 | ./it2-out > it3-out0.c
# gcc step since the target is still python here
it3-out0: it3-out0.c
gcc $^ -o $@ $(GCC_FLAGS)
it3-out1.ll: it3-out0 it3-in.lang0
cat it3-in.lang0 | ./it3-out0 > $@
it3-out1.s: it3-out1.ll
llc $^ -o $@
foo.ll: foo.c
clang -S -emit-llvm $^
foo.s: foo.ll
llc $^
foo: foo.s
clang $^ -o $@
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,9 +129,9 @@ Creates a new string with `b` appended to `a`.
Writes the given string to standard output.
#### fileget path
#### eq a b
Reads a file named `path` from the current directory into a string.
Return true if the given strings are the same.
#### intinc a
@ -124,6 +140,12 @@ 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.

View File

@ -1,2 +0,0 @@
if __name__ == '__main__':
main()

View File

@ -1,51 +0,0 @@
import os
import sys
def eq(a, b):
return a == b
def lt(a, b):
return a[0] < b[0]
def addstringchar(a, b):
return a + b[0]
def emit(string):
sys.stdout.write(string)
def trace(header, value):
if os.environ.get('TRACE'):
sys.stderr.write(f'{header}={value!r}\\n')
eof = chr(0)
eol = chr(10)
quote = chr(34)
PEEK = None
LINE = 1
def peek():
global PEEK
if PEEK is None:
char = sys.stdin.read(1)
trace('char', char)
if not char:
PEEK = eof
else:
PEEK = char
return PEEK
def skip():
global LINE
global PEEK
if eol == PEEK:
LINE += 1
PEEK = None
def skipchar(char):
global LINE
assert char == peek(), (LINE, char, peek())
skip()
def fileget(path):
with open(f'./{path}', encoding='ASCII') as fil:
return fil.read()

View File

@ -1,2 +0,0 @@
if __name__ == '__main__':
main()

View File

@ -1,51 +0,0 @@
import os
import sys
def eq(a, b):
return a == b
def lt(a, b):
return a[0] < b[0]
def addstringchar(a, b):
return a + b[0]
def emit(string):
sys.stdout.write(string)
def trace(header, value):
if os.environ.get('TRACE'):
sys.stderr.write(f'{header}={value!r}\\n')
eof = chr(0)
eol = chr(10)
quote = chr(34)
PEEK = None
LINE = 1
def peek():
global PEEK
if PEEK is None:
char = sys.stdin.read(1)
trace('char', char)
if not char:
PEEK = eof
else:
PEEK = char
return PEEK
def skip():
global LINE
global PEEK
if eol == PEEK:
LINE += 1
PEEK = None
def skipchar(char):
global LINE
assert char == peek(), (LINE, char, peek())
skip()
def fileget(path):
with open(f'./{path}', encoding='ASCII') as fil:
return fil.read()

View File

@ -1,136 +0,0 @@
#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\n", chr[0], LINE, act[0]);
exit(1);
}
char * fileget(char * var_path)
{
FILE * file_ptr;
int file_size;
char * res;
file_ptr = fopen(var_path, "r");
if( NULL == file_ptr ) {
fprintf(stderr, "Could not load file %s", var_path);
exit(1);
}
fseek(file_ptr, 0, SEEK_END);
file_size = ftell(file_ptr);
fseek(file_ptr, 0, SEEK_SET);
res = malloc(file_size * sizeof(char));
fread(res, sizeof(char), file_size, file_ptr);
fclose(file_ptr);
return res;
}
void mapclear(char * map_name)
{
}
void mapsetkey(char * map_name, char * key, char * value)
{
}
char * mapgetkey(char * map_name, char * key)
{
return "0";
}
char * intinc(char * a)
{
int len = strlen(a);
int val;
int read = sscanf(a, "%d", &val);
if( len != read ) {
return "1";
}
val += 1;
char * res = malloc((len + 1) * sizeof(char));
sprintf(res, "%d", val);
return res;
}

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
/