Compare commits

..

12 Commits

Author SHA1 Message Date
Johan B.W. de Vries
ac516d55a2 Implement and test strlen 2026-02-01 12:49:15 +01:00
Johan B.W. de Vries
68611b4df3 More work 2026-01-25 15:10:26 +01:00
Johan B.W. de Vries
49e1bf204f Adds backslash as a build in constant 2026-01-25 15:10:12 +01:00
Johan B.W. de Vries
5369c15e05 Adds intinc as a buildint function 2026-01-25 13:14:02 +01:00
Johan B.W. de Vries
a282292604 Adds strlen as a builtin function 2026-01-25 12:47:58 +01:00
Johan B.W. de Vries
1be24ef771 close, but no sigare 2026-01-18 16:09:21 +01:00
Johan B.W. de Vries
449a89d6b3 More work 2026-01-18 15:05:21 +01:00
Johan B.W. de Vries
c9029b1216 More work 2026-01-18 14:47:57 +01:00
Johan B.W. de Vries
1671ce2285 More testing 2026-01-18 14:21:48 +01:00
Johan B.W. de Vries
098ab080ca Updated llvm with other changes
Started on outputting string constants

Need to:
- Calc string length
- Implement _add (including allocation)
- Everything else
2026-01-18 13:11:17 +01:00
Johan B.W. de Vries
cfae563aef Start on llvm IR target
# Conflicts:
#	README.md
2025-05-04 18:18:45 +02:00
Johan B.W. de Vries
8502abeff6 Start on llvm IR target 2025-05-04 18:10:53 +02:00
22 changed files with 1742 additions and 12 deletions

View File

@ -409,6 +409,7 @@ def emitheader():
emitln(" if os.environ.get('TRACE'):")
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
emitln("")
emitln("__BACKSLASH = chr(0x5C)")
emitln("__EOF = chr(0xFF)")
emitln("__EOL = chr(10)")
emitln("__QUOTE = chr(34)")
@ -475,6 +476,12 @@ def emitheader():
emitln(" sys.stderr.flush()")
emitln(" exit(1)")
emitln("")
emitln("def __strlen(a: str) -> str:")
emitln(" return str(len(a))")
emitln("")
emitln("def __intinc(a: str) -> str:")
emitln(" return str(int(a) + 1)")
emitln("")
emitln("# ### END OF RUNTIME ### #")
emitln("")
@ -489,6 +496,7 @@ def main():
emitheader()
# Standard library constants
mapsetkey("REGISTERID", "backslash", "__BACKSLASH")
mapsetkey("REGISTERID", "eof", "__EOF")
mapsetkey("REGISTERID", "eol", "__EOL")
mapsetkey("REGISTERID", "quote", "__QUOTE")
@ -500,6 +508,8 @@ def main():
mapsetkey("REGISTERID", "emit", "__emit")
mapsetkey("FUNCREG", "eq", "1")
mapsetkey("REGISTERID", "eq", "__eq")
mapsetkey("FUNCREG", "intinc", "1")
mapsetkey("REGISTERID", "intinc", "__intinc")
mapsetkey("FUNCREG", "lt", "1")
mapsetkey("REGISTERID", "lt", "__lt")
mapsetkey("FUNCREG", "not", "1")
@ -518,6 +528,8 @@ def main():
mapsetkey("REGISTERID", "stdincolno", "__stdincolno")
mapsetkey("FUNCREG", "stdinlineno", "1")
mapsetkey("REGISTERID", "stdinlineno", "__stdinlineno")
mapsetkey("FUNCREG", "strlen", "1")
mapsetkey("REGISTERID", "strlen", "__strlen")
while True:
if eof == peek():

View File

@ -472,6 +472,7 @@ emitheader:
emitln " if os.environ.get('TRACE'):"
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
emitln ""
emitln "__BACKSLASH = chr(0x5C)"
emitln "__EOF = chr(0xFF)"
emitln "__EOL = chr(10)"
emitln "__QUOTE = chr(34)"
@ -534,6 +535,12 @@ emitheader:
emitln " sys.stderr.flush()"
emitln " exit(1)"
emitln ""
emitln "def __strlen(a: str) -> str:"
emitln " return str(len(a))"
emitln ""
emitln "def __intinc(a: str) -> str:"
emitln " return str(int(a) + 1)"
emitln ""
emitln "# ### END OF RUNTIME ### #"
emitln ""
/
@ -551,6 +558,7 @@ emitfooter:
main:
emitheader
mapsetkey "REGISTERID" "backslash" "__BACKSLASH"
mapsetkey "REGISTERID" "eof" "__EOF"
mapsetkey "REGISTERID" "eol" "__EOL"
mapsetkey "REGISTERID" "quote" "__QUOTE"
@ -561,6 +569,8 @@ main:
mapsetkey "REGISTERID" "emit" "__emit"
mapsetkey "FUNCREG" "eq" "1"
mapsetkey "REGISTERID" "eq" "__eq"
mapsetkey "FUNCREG" "intinc" "1"
mapsetkey "REGISTERID" "intinc" "__intinc"
mapsetkey "FUNCREG" "lt" "1"
mapsetkey "REGISTERID" "lt" "__lt"
mapsetkey "FUNCREG" "not" "1"
@ -579,6 +589,8 @@ main:
mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
mapsetkey "FUNCREG" "strlen" "1"
mapsetkey "REGISTERID" "strlen" "__strlen"
forever

View File

@ -574,6 +574,7 @@ emitheader:
emitln "#include <string.h>"
emitln ""
emitln ""
emitln "char __BACKSLASH[2] = {0x5C, 0};"
emitln "char __EOF[2] = {0xFF, 0};"
emitln "char __EOL[2] = {10, 0};"
emitln "char __QUOTE[2] = {34, 0};"
@ -798,6 +799,31 @@ emitheader:
emitln ";"
emitln "}"
emitln ""
emitln "char * __strlen(char * inp)"
emitln "{"
emitln " char * buffer = malloc(20);"
emitln " size_t len = strlen(inp);"
emit " snprintf(buffer, 20, "
emit quote
emit "%zu"
emit quote
emitln ", len);"
emitln " return buffer;"
emitln "}"
emitln ""
emitln "char * __intinc(char * inp)"
emitln "{"
emitln " char * buffer = malloc(20);"
emitln " char * endptr;"
emitln " unsigned long long number = strtoull(inp, &endptr, 10);"
emit " snprintf(buffer, 20, "
emit quote
emit "%llu"
emit quote
emitln ", number + 1);"
emitln " return buffer;"
emitln "}"
emitln ""
emitln "// ### END OF RUNTIME ### //"
emitln ""
return
@ -824,6 +850,7 @@ main:
emitheader
mapsetkey "REGISTERID" "backslash" "__BACKSLASH"
mapsetkey "REGISTERID" "eof" "__EOF"
mapsetkey "REGISTERID" "eol" "__EOL"
mapsetkey "REGISTERID" "quote" "__QUOTE"
@ -834,6 +861,8 @@ main:
mapsetkey "REGISTERID" "emit" "__emit"
mapsetkey "FUNCREG" "eq" "1"
mapsetkey "REGISTERID" "eq" "__eq"
mapsetkey "FUNCREG" "intinc" "1"
mapsetkey "REGISTERID" "intinc" "__intinc"
mapsetkey "FUNCREG" "lt" "1"
mapsetkey "REGISTERID" "lt" "__lt"
mapsetkey "FUNCREG" "not" "1"
@ -852,6 +881,8 @@ main:
mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
mapsetkey "FUNCREG" "strlen" "1"
mapsetkey "REGISTERID" "strlen" "__strlen"
forever
calc char peek

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

@ -0,0 +1,12 @@
/lang0ll*.bc
/lang0ll*.c
/lang0ll*.exe
/lang0ll*.ll
/lang0ll*.o
/lang0ll*.s
/runtimetest.bc
/runtimetest.c
/runtimetest.exe
/runtimetest.ll
/runtimetest.o
/runtimetest.s

48
3-lang0ll/Makefile Normal file
View File

@ -0,0 +1,48 @@
.SUFFIXES:
LANG0C=$(CURDIR)/../2-lang0c/lang0c.exe
all: lang0ll.exe
%.exe: %.s
clang -g $^ -o $@
%.s: %.bc
llc --relocation-model=pic $^ -o $@
%.bc: %.ll
llvm-as $^ -o $@
lang0ll0.c: lang0ll.lang0 $(LANG0C)
cat $< | $(LANG0C) > $@
lang0ll0.o: lang0ll0.c
gcc -g -c $<
lang0ll0.exe: lang0ll0.o
gcc -g -o $@ $<
lang0ll1.ll: lang0ll.lang0 lang0ll0.exe
cat $< | ./lang0ll0.exe > $@
sed -i '/^.*; pre-declaration$$/d' $@
# Cannot diff on the first iteration - platform change
lang0ll2.ll: lang0ll.lang0 lang0ll1.exe
cat $< | ./lang0ll1.exe > $@
sed -i '/^.*; pre-declaration$$/d' $@
-diff lang0ll1.ll lang0ll2.ll
lang0ll.ll: lang0ll.lang0 lang0ll2.exe
cat $< | ./lang0ll2.exe > $@
sed -i '/^.*; pre-declaration$$/d' $@
-diff lang0ll2.ll lang0ll.ll
foo.ll: foo.c
clang -S -emit-llvm $^
clean:
rm -f lang0ll*.c lang0ll*.ll lang0ll*.o lang0ll*.exe foo.ll foo.o foo.exe

71
3-lang0ll/backup.ll Normal file
View File

@ -0,0 +1,71 @@
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"
declare noalias i8* @malloc(i64)
define i8* @__add(i8* %lft, i8* %rgt)
{
%lft_len = call i64 @__strlen(i8* %lft)
%rgt_len = call i64 @__strlen(i8* %rgt)
%new_len = add i64 %lft_len, %rgt_len
%res = call i8* @malloc(i64 %new_len)
; todo: copy lft
; todo: copy rgt
; todo: set 0 byte
ret i8* %res
}
define i64 @__strlen(i8* %str)
{
start:
br label %loop_start
loop_start:
%i.0 = phi i64 [0, %start], [%i.new, %loop]
%c_adr = getelementptr i8, i8* %str, i64 %i.0
%c = load i8, i8* %c_adr
%done = icmp eq i8 %c, 0
br i1 %done, label %exit, label %loop
loop:
%i.new = add i64 %i.0, 1
br label %loop_start
exit:
ret i64 %i.0
}
define i8* @__mapgetkey(i8* %mapname, i8* %key, i8* %def)
{
; todo
ret i8* %def
}
define i8* @addstringchar(i8* %0, i8* %1)
{
; todo
ret i8* %0
}
define i8* @registerid(i8* %id_id)
{
%id_idname = call i8* @__mapgetkey(i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.01, i64 0, i64 0), i8* %id_id, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.011, i64 0, i64 0))
%1 = call i64 @__strlen(i8* %id_idname)
%11 = icmp ne i64 %1, 0
br i1 %11, label %lbl1, label %lbl11
lbl1:
ret i8* %id_idname
lbl11:
%id_idnamea = call i8* @__add(i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str.0111, i64 0, i64 0), i8* %id_id)
ret i8* %id_idnamea
}
define i64 @main() {
%res = call i64 @__strlen(i8* @str.01)
ret i64 %res
}
@str.01 = internal constant [11 x i8] c"REGISTERID\00"
@str.011 = internal constant [0 x i8] c""
@str.0111 = internal constant [3 x i8] c"id_"

1027
3-lang0ll/lang0ll.lang0 Normal file

File diff suppressed because it is too large Load Diff

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

400
3-lang0ll/runtimetest.ll Normal file
View File

@ -0,0 +1,400 @@
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"
%FILE = type opaque
@stdout = global %FILE* null
declare void @exit(i32)
declare i32 @fputs(i8*, %FILE*)
declare i8* @malloc(i32)
declare %FILE* @fdopen(i32, i8*)
declare void @fclose(%FILE*)
@__BACKSLASH = internal constant [2 x i8] c"\\\00"
@__EOF = internal constant [2 x i8] c"\\\FF"
@__EOL = internal constant [2 x i8] c"\0A\00"
@__QUOTE = internal constant [2 x i8] c"\22\00"
@__FALSE = internal constant [1 x i8] c"\00"
@__TRUE = internal constant [2 x i8] c"1\00"
define i8* @__drop_i8_type(i8* %0) alwaysinline readnone
{
ret i8* %0
}
define i8* @__eq(i8* %0, i8* %1)
{
%i = alloca i64, align 8
store i64 0, i64* %i
br label %loop
loop:
%index = load i64, i64* %i
%char0_adr = getelementptr i8, i8* %0, i64 %index
%char1_adr = getelementptr i8, i8* %1, i64 %index
%char0 = load i8, i8* %char0_adr
%char1 = load i8, i8* %char1_adr
%chars_differ = icmp ne i8 %char0, %char1
br i1 %chars_differ, label %lbl_not_equal, label %lbl_equal
lbl_equal:
%string_end = icmp eq i8 %char0, 0
br i1 %string_end, label %string_equal, label %next_char
string_equal:
ret i8* @__TRUE
next_char:
%next_index = add i64 %index, 1
store i64 %next_index, i64* %i
br label %loop
lbl_not_equal:
ret i8* @__FALSE
}
define i8* @__lt(i8* %0, i8* %1)
{
%i = alloca i64, align 8
store i64 0, i64* %i
br label %loop
loop:
%index = load i64, i64* %i
%char0_adr = getelementptr i8, i8* %0, i64 %index
%char1_adr = getelementptr i8, i8* %1, i64 %index
%char0 = load i8, i8* %char0_adr
%char1 = load i8, i8* %char1_adr
%char0_eol = icmp eq i8 %char0, 0
%char1_eol = icmp eq i8 %char1, 0
; if char0 == 0
; if char1 == 0
; return FALSE ; "" < "" === False
; else
; return TRUE ; "" < "." === True
; endif
; else
; if char1 == 0
; return FALSE ; "." < "" === False
; else
; if char0 < char1
; return TRUE ; "a" < "b" === True
; else
; if char0 > char1
; return FALSE ; "b" < "a" === False
; else
; jump next_char
; endif
; endif
; endif
; endif
br i1 %char0_eol, label %lbl_char0_eol, label %lbl_char0_not_eol
lbl_char0_eol:
br i1 %char1_eol, label %lbl_not_smaller, label %lbl_smaller
lbl_char0_not_eol:
br i1 %char1_eol, label %lbl_not_smaller, label %lbl_char0_not_eol_char1_not_eol
lbl_char0_not_eol_char1_not_eol:
%char0_lt_char1 = icmp ult i8 %char0, %char1
br i1 %char0_lt_char1, label %lbl_smaller, label %lbl_char0_ge_char1
lbl_char0_ge_char1:
%char0_gt_char1 = icmp ugt i8 %char0, %char1
br i1 %char0_gt_char1, label %lbl_not_smaller, label %next_char
next_char:
%next_index = add i64 %index, 1
store i64 %next_index, i64* %i
br label %loop
lbl_smaller:
ret i8* @__TRUE
lbl_not_smaller:
ret i8* @__FALSE
}
define i8* @__not(i8* %0)
{
%char0_adr = getelementptr i8, i8* %0, i64 0
%char0 = load i8, i8* %char0_adr
%char0_eol = icmp eq i8 %char0, 0
br i1 %char0_eol, label %lbl_empty, label %lbl_not_empty
lbl_empty:
ret i8* @__TRUE;
lbl_not_empty:
ret i8* @__FALSE;
}
define i8* @__add(i8* %0, i8* %1)
{
ret i8* %0 ; STUB
}
define i8* @__emit(i8* %0)
{
%stdout_ptr = load %FILE*, %FILE** @stdout
call i32 @fputs(i8* %0, %FILE* %stdout_ptr)
ret i8* @__FALSE
}
define i8* @__trace(i8* %0, i8* %1)
{
ret i8* %0 ; STUB
}
define i8* @__peek()
{
ret i8* @__EOL ; STUB
}
define i8* @__skip()
{
ret i8* @__EOL ; STUB
}
define i8* @__stdinlineno()
{
ret i8* @__EOL ; STUB
}
define i8* @__stdincolno()
{
ret i8* @__EOL ; STUB
}
define i8* @__mapgetkey(i8* %0, i8* %1, i8* %2)
{
ret i8* %0 ; STUB
}
define i8* @__mapsetkey(i8* %0, i8* %1, i8* %2)
{
ret i8* %0 ; STUB
}
define i8* @__str_reverse(i8* %0, i64 %1)
{
%input_empty = icmp ule i64 %1, 1
br i1 %input_empty, label %lbl_done, label %lbl_work_to_do
lbl_work_to_do:
%arg1_sub1 = sub i64 %1, 1
%rgidx_reg = alloca i64, align 8
store i64 %arg1_sub1, i64* %rgidx_reg
%lfidx_reg = alloca i64, align 8
store i64 0, i64* %lfidx_reg
br label %loop
loop:
%rgidx = load i64, i64* %rgidx_reg
%lfidx = load i64, i64* %lfidx_reg
%rgidx_le_lfidx = icmp ule i64 %rgidx, %lfidx
br i1 %rgidx_le_lfidx, label %lbl_done, label %lbl_flip_one
lbl_flip_one:
%rgadr = getelementptr i8, i8* %0, i64 %rgidx
%rgchr = load i8, i8* %rgadr
%lfadr = getelementptr i8, i8* %0, i64 %lfidx
%lfchr = load i8, i8* %lfadr
store i8 %lfchr, i8* %rgadr
store i8 %rgchr, i8* %lfadr
%new_rgidx = sub i64 %rgidx, 1
%new_lfidx = add i64 %lfidx, 1
store i64 %new_rgidx, i64* %rgidx_reg
store i64 %new_lfidx, i64* %lfidx_reg
br label %loop
lbl_done:
ret i8* %0;
}
define i8* @__i64_to_str(i64 %i)
{
%res = call i8* @malloc(i64 32)
store i8 48, i8* %res ; Base case
%idx_reg = alloca i64, align 8
store i64 0, i64* %idx_reg
%rem_idx = alloca i64, align 8
store i64 %i, i64* %rem_idx
br label %loop
loop:
%rem = load i64, i64* %rem_idx
%rem.eq0 = icmp eq i64 %rem, 0
br i1 %rem.eq0, label %lbl_done, label %lbl_addchar
lbl_addchar:
%digit = urem i64 %rem, 10
%char.0 = trunc i64 %digit to i8
%char.1 = add i8 48, %char.0
%idx = load i64, i64* %idx_reg
%char.adr = getelementptr i8, i8* %res, i64 %idx
store i8 %char.1, i8* %char.adr
%newrem.0 = sub i64 %rem, %digit
%newrem.1 = udiv i64 %newrem.0, 10
store i64 %newrem.1, i64* %rem_idx
%newidx = add i64 %idx, 1
store i64 %newidx, i64* %idx_reg
br label %loop
lbl_done:
; null terminator
%nt_idx = load i64, i64* %idx_reg
%nt_adr = getelementptr i8, i8* %res, i64 %nt_idx
store i8 0, i8* %nt_adr
; By not increasing the index, the index is the length
%len = load i64, i64* %idx_reg
%rev = call i8* @__str_reverse(i8* %res, i64 %len)
ret i8 *%rev
}
define i8* @__strlen(i8* %0)
{
%i = alloca i64, align 8
store i64 0, i64* %i
br label %loop
loop:
%index = load i64, i64* %i
%char0_adr = getelementptr i8, i8* %0, i64 %index
%char0 = load i8, i8* %char0_adr
%char0_eol = icmp eq i8 %char0, 0
br i1 %char0_eol, label %lbl_char0_eol, label %lbl_char0_not_eol
lbl_char0_not_eol:
%next_index = add i64 %index, 1
store i64 %next_index, i64* %i
br label %loop
lbl_char0_eol:
%len = load i64, i64* %i
%res = call i8* @__i64_to_str(i64 %len)
ret i8* %res;
}
define i8* @__intinc(i8* %0)
{
ret i8* %0 ; STUB
}
define void @test_result_1(i8* %func, i8* %arg0, i8* %result)
{
call i32 @__emit(i8* %func)
call i32 @__emit(i8* @str.bracket)
call i32 @__emit(i8* %arg0)
call i32 @__emit(i8* @str.bracket_colon_space)
call i32 @__emit(i8* %result)
call i32 @__emit(i8* @__EOL)
ret void
}
define void @test_result_2(i8* %func, i8* %arg0, i8* %arg1, i8* %result)
{
call i32 @__emit(i8* %func)
call i32 @__emit(i8* @str.bracket)
call i32 @__emit(i8* %arg0)
call i32 @__emit(i8* @str.comma_space)
call i32 @__emit(i8* %arg1)
call i32 @__emit(i8* @str.bracket_colon_space)
call i32 @__emit(i8* %result)
call i32 @__emit(i8* @__EOL)
ret void
}
define void @test_eq(i8* %0, i8* %1)
{
%result = call i8* @__eq(i8* %0, i8* %1)
call void @test_result_2(i8* @str.eq, i8* %0, i8* %1, i8* %result)
ret void
}
define void @test_lt(i8* %0, i8* %1)
{
%result = call i8* @__lt(i8* %0, i8* %1)
call void @test_result_2(i8* @str.lt, i8* %0, i8* %1, i8* %result)
ret void
}
define void @test_not(i8* %0)
{
%result = call i8* @__not(i8* %0)
call void @test_result_1(i8* @str.not, i8* %0, i8* %result)
ret void
}
define void @test_strlen(i8* %0)
{
%result = call i8* @__strlen(i8* %0)
call void @test_result_1(i8* @str.strlen, i8* %0, i8* %result)
ret void
}
define i64 @main()
{
%stdout_ptr = call %FILE* @fdopen(i32 1, i8* @str.w)
store %FILE* %stdout_ptr, %FILE** @stdout
call void @test_eq(i8* @str., i8* @str.0)
call void @test_eq(i8* @str.0, i8* @str.)
call void @test_eq(i8* @str.0, i8* @str.0)
call void @test_eq(i8* @str.a, i8* @str.a)
call void @test_eq(i8* @str.a, i8* @str.b)
call void @test_eq(i8* @str.a, i8* @str.c)
call void @test_eq(i8* @str.b, i8* @str.a)
call void @test_eq(i8* @str.b, i8* @str.b)
call void @test_eq(i8* @str.b, i8* @str.c)
call void @test_eq(i8* @str.c, i8* @str.a)
call void @test_eq(i8* @str.c, i8* @str.b)
call void @test_eq(i8* @str.c, i8* @str.c)
call void @test_eq(i8* @str.left, i8* @str.right)
call void @test_eq(i8* @str.left, i8* @str.left)
call void @test_eq(i8* @str.right, i8* @str.left)
call void @test_eq(i8* @str.right, i8* @str.right)
call void @test_lt(i8* @str.0, i8* @str.0)
call void @test_lt(i8* @str.a, i8* @str.a)
call void @test_lt(i8* @str.a, i8* @str.b)
call void @test_lt(i8* @str.a, i8* @str.c)
call void @test_lt(i8* @str.b, i8* @str.a)
call void @test_lt(i8* @str.b, i8* @str.b)
call void @test_lt(i8* @str.b, i8* @str.c)
call void @test_lt(i8* @str.c, i8* @str.a)
call void @test_lt(i8* @str.c, i8* @str.b)
call void @test_lt(i8* @str.c, i8* @str.c)
; `a` and `b` are expected to have length 1.
call void @test_not(i8* @str.)
call void @test_not(i8* @str.0)
call void @test_not(i8* @str.1)
call void @test_strlen(i8* @str.)
call void @test_strlen(i8* @str.a)
call void @test_strlen(i8* @str.eq)
call void @test_strlen(i8* @str.not)
call void @test_strlen(i8* @str.left)
call void @test_strlen(i8* @str.right)
call void @test_strlen(i8* @str.strlen)
call void @test_strlen(i8* @str.explanation)
call void @test_strlen(i8* @str.cats_paragraph)
call i32 @fclose(%FILE* %stdout_ptr)
ret i64 0
}
@str. = internal constant [1 x i8] c"\00"
@str.0 = internal constant [2 x i8] c"0\00"
@str.1 = internal constant [2 x i8] c"1\00"
@str.2 = internal constant [2 x i8] c"2\00"
@str.3 = internal constant [2 x i8] c"3\00"
@str.4 = internal constant [2 x i8] c"4\00"
@str.5 = internal constant [2 x i8] c"5\00"
@str.6 = internal constant [2 x i8] c"6\00"
@str.a = internal constant [2 x i8] c"a\00"
@str.b = internal constant [2 x i8] c"b\00"
@str.c = internal constant [2 x i8] c"c\00"
@str.bracket = internal constant [2 x i8] c"(\00"
@str.bracket_colon_space = internal constant [4 x i8] c"): \00"
@str.comma_space = internal constant [3 x i8] c", \00"
@str.eq = internal constant [3 x i8] c"eq\00"
@str.left = internal constant [5 x i8] c"left\00"
@str.lt = internal constant [3 x i8] c"lt\00"
@str.not = internal constant [4 x i8] c"not\00"
@str.right = internal constant [6 x i8] c"right\00"
@str.strlen = internal constant [7 x i8] c"strlen\00"
@str.w = internal constant [2 x i8] c"w\00"
@str.explanation = internal constant [135 x i8] c"Bitwise AND Operation: The and instruction performs a bitwise AND between the input value and the mask to isolate the smallest 8 bits.\00"
@str.cats_paragraph = internal constant [1193 x i8] c"Cats are fascinating creatures that have captivated humans for thousands of years. Belonging to the family Felidae, they are known for their agility, sharp senses, and playful behavior. Cats communicate through a variety of vocalizations, body language, and purring. One remarkable feature is their keen hunting skills; they possess sharp retractable claws and excellent night vision, enabling them to stalk and capture prey effectively. Domesticated cats, often kept as pets, bring joy to many households. They exhibit a range of personalities, from solitary and aloof to affectionate and social. Cats also enjoy playing, often engaging in activities that mimic hunting, such as chasing toys or pouncing on moving objects. Additionally, their grooming habits help keep their fur clean and contain calming pheromones that promote bonding with their human companions. Studies suggest that having a cat can reduce stress and anxiety levels. This unique relationship invites appreciation for their independence and charm, as they provide companionship while often maintaining a mysterious aura. Overall, cats are beloved pets that enrich our lives with their unique attributes and companionship.\00"

View File

@ -2,10 +2,12 @@ all:
$(MAKE) -C 0-lang0py all
$(MAKE) -C 1-lang0py all
$(MAKE) -C 2-lang0c all
$(MAKE) -C 3-lang0ll all
$(MAKE) -C tests all
clean:
$(MAKE) -C 0-lang0py clean
$(MAKE) -C 1-lang0py clean
$(MAKE) -C 2-lang0c clean
$(MAKE) -C 3-lang0ll clean
$(MAKE) -C tests clean

View File

@ -123,6 +123,10 @@ Writes the name and value of the variable passed to stderr if the TRACE environm
### Standard library constants
#### backslash
Backslash character.
#### eof
End of file character, zero byte.
@ -155,6 +159,12 @@ Return true if the given strings are the same.
Return true if a would sort before b.
#### intinc
Assumes `a` is a string containing solely a decimal integer.
Returns a increased by one.
#### mapclear mapname
Maps are global and can be used from any function.
@ -194,6 +204,10 @@ Returns the column number for stdin (starting at 1)
Returns the line number for stdin (starting at 1)
#### strlen a
Returns a string with the length of a.
### Typing
Every variable is of type string. Every function gets a number of strings as output, and returns another string.

View File

@ -11,7 +11,7 @@ CFLAGS=-ggdb
all: verify-results
Makefile.mk: generate-recipes.py $(wildcard test_*/test_*)
python3 generate-recipes.py Makefile.mk it0 it1 it2
python3 generate-recipes.py Makefile.mk it0 it1 it2 it3
include Makefile.mk
@ -29,6 +29,10 @@ clean:
find build -name '*.it2.result' -delete
find build -name '*.it2.stderr' -delete
find build -name '*.it2.stdout' -delete
find build -name '*.it3' -delete
find build -name '*.it3.result' -delete
find build -name '*.it3.stderr' -delete
find build -name '*.it3.stdout' -delete
find build -name '*.py' -delete
find build -name '*.tmp' -delete
@ -85,3 +89,19 @@ build/%.it2.o: build/%.it2.c
build/%.it2: build/%.it2.o
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION)
###
# it3
../3-lang0ll/lang0ll.exe: ../0-lang0py/lang0py.exe ../1-lang0py/lang0py.exe ../2-lang0c/lang0c.exe ../3-lang0ll/lang0ll.lang0
$(MAKE) -C ../3-lang0ll
build/%.it3.ll: %.lang0 ../3-lang0ll/lang0ll.exe
-cat $< | ../3-lang0ll/lang0ll.exe > $@.tmp 2> build/$*.it3.cmperr
mv $@.tmp $@
build/%.it3.s: build/%.it3.ll
llc --relocation-model=pic $^
build/%.it3: build/%.it3.s
clang $^ -o $@

View File

@ -24,3 +24,11 @@
/*.it2.result
/*.it2.stderr
/*.it2.stdout
/*.it3
/*.it3.ll
/*.it3.cmperr
/*.it3.ll.tmp
/*.it3.o
/*.it3.result
/*.it3.stderr
/*.it3.stdout

View File

@ -6,6 +6,7 @@ STAGE0_MAP = {
'it0': '.py',
'it1': '.py',
'it2': '.c',
'it3': '.ll',
}
class Rule:

View File

@ -0,0 +1 @@
\

View File

@ -0,0 +1,3 @@
main:
emit backslash
/

View File

@ -1,14 +1,3 @@
func tst a b:
declare var
calc var add a b
emit a
emit " + "
emit b
emit " = "
emit var
emit eol
/
main:
declare var

View File

@ -0,0 +1,5 @@
0 + 1: 1
5 + 1: 6
9 + 1: 10
15 + 1: 16
99 + 1: 100

View File

@ -0,0 +1,28 @@
main:
declare result
emit "0 + 1: "
calc result intinc "0"
emit result
emit eol
emit "5 + 1: "
calc result intinc "5"
emit result
emit eol
emit "9 + 1: "
calc result intinc "9"
emit result
emit eol
emit "15 + 1: "
calc result intinc "15"
emit result
emit eol
emit "99 + 1: "
calc result intinc "99"
emit result
emit eol
/

View File

@ -0,0 +1,4 @@
strlen()=0
strlen()=1
strlen()=1
strlen()=8

View File

@ -0,0 +1,23 @@
main:
declare var
calc var strlen ""
emit "strlen()="
emit var
emit eol
calc var strlen "0"
emit "strlen()="
emit var
emit eol
calc var strlen "1"
emit "strlen()="
emit var
emit eol
calc var strlen "abcdefgh"
emit "strlen()="
emit var
emit eol
/