Compare commits

..

4 Commits

Author SHA1 Message Date
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
17 changed files with 619 additions and 56 deletions

View File

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

View File

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

View File

@ -574,6 +574,7 @@ emitheader:
emitln "#include <string.h>" emitln "#include <string.h>"
emitln "" emitln ""
emitln "" emitln ""
emitln "char __BACKSLASH[2] = {0x5C, 0};"
emitln "char __EOF[2] = {0xFF, 0};" emitln "char __EOF[2] = {0xFF, 0};"
emitln "char __EOL[2] = {10, 0};" emitln "char __EOL[2] = {10, 0};"
emitln "char __QUOTE[2] = {34, 0};" emitln "char __QUOTE[2] = {34, 0};"
@ -798,6 +799,31 @@ emitheader:
emitln ";" emitln ";"
emitln "}" 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 "// ### END OF RUNTIME ### //"
emitln "" emitln ""
return return
@ -824,6 +850,7 @@ main:
emitheader emitheader
mapsetkey "REGISTERID" "backslash" "__BACKSLASH"
mapsetkey "REGISTERID" "eof" "__EOF" mapsetkey "REGISTERID" "eof" "__EOF"
mapsetkey "REGISTERID" "eol" "__EOL" mapsetkey "REGISTERID" "eol" "__EOL"
mapsetkey "REGISTERID" "quote" "__QUOTE" mapsetkey "REGISTERID" "quote" "__QUOTE"
@ -834,6 +861,8 @@ main:
mapsetkey "REGISTERID" "emit" "__emit" mapsetkey "REGISTERID" "emit" "__emit"
mapsetkey "FUNCREG" "eq" "1" mapsetkey "FUNCREG" "eq" "1"
mapsetkey "REGISTERID" "eq" "__eq" mapsetkey "REGISTERID" "eq" "__eq"
mapsetkey "FUNCREG" "intinc" "1"
mapsetkey "REGISTERID" "intinc" "__intinc"
mapsetkey "FUNCREG" "lt" "1" mapsetkey "FUNCREG" "lt" "1"
mapsetkey "REGISTERID" "lt" "__lt" mapsetkey "REGISTERID" "lt" "__lt"
mapsetkey "FUNCREG" "not" "1" mapsetkey "FUNCREG" "not" "1"
@ -852,6 +881,8 @@ main:
mapsetkey "REGISTERID" "stdincolno" "__stdincolno" mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1" mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno" mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
mapsetkey "FUNCREG" "strlen" "1"
mapsetkey "REGISTERID" "strlen" "__strlen"
forever forever
calc char peek calc char peek

View File

@ -1,4 +1,18 @@
registerid id: registerfunc id:
declare idname
declare newidx
calc idname mapgetkey "REGISTERID" id ""
if idname
return idname
/
declare idnamea
calc idnamea add "@id_" id
return idnamea
/
registervar id:
declare idname declare idname
declare newidx declare newidx
@ -22,8 +36,8 @@ makelocalvar:
declare prevvar declare prevvar
declare newvar declare newvar
declare result declare result
calc prevvar mapgetkey "localvarused" "" "" calc prevvar mapgetkey "localvarused" "" "0"
calc newvar add prevvar "1" calc newvar intinc prevvar
mapsetkey "localvarused" "" newvar mapsetkey "localvarused" "" newvar
calc result add "%tmp" newvar calc result add "%tmp" newvar
return result return result
@ -33,8 +47,8 @@ makelocallabel:
declare prevlabel declare prevlabel
declare newlabel declare newlabel
declare result declare result
calc prevlabel mapgetkey "locallabelused" "" "" calc prevlabel mapgetkey "locallabelused" "" "0"
calc newlabel add prevlabel "1" calc newlabel intinc prevlabel
mapsetkey "locallabelused" "" newlabel mapsetkey "locallabelused" "" newlabel
calc result add "lbl" newlabel calc result add "lbl" newlabel
return result return result
@ -44,15 +58,15 @@ makestringconst str:
declare constid declare constid
declare isempty declare isempty
calc constid mapgetkey "stringconst" str "" calc constid mapgetkey "str_to_const_id" str ""
calc isempty eq constid "" calc isempty eq constid ""
if isempty if isempty
calc constid mapgetkey "stringconst" "___count___" "0" calc constid mapgetkey "const_id_to_str" "___count___" "0"
calc constid add constid "1" calc constid intinc constid
mapsetkey "stringconst" "___count___" constid mapsetkey "const_id_to_str" "___count___" constid
/ /
mapsetkey "stringconst" str constid mapsetkey "str_to_const_id" str constid
mapsetkey "stringconst" constid str mapsetkey "const_id_to_str" constid str
return constid return constid
/ /
@ -130,7 +144,7 @@ parseexprvarref:
declare varid declare varid
declare varname declare varname
calc varname lexident calc varname lexident
calc varid registerid varname calc varid registervar varname
emit "i8* " emit "i8* "
emit varid emit varid
return return
@ -148,9 +162,9 @@ parseexprcall:
declare isquote declare isquote
declare isnotquote declare isnotquote
calc funcname lexident calc funcname lexident
calc funcid registerfunc funcname
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist" check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
emit "@id_" emit funcid
emit funcname
emit "(" emit "("
set first "1" set first "1"
forever forever
@ -188,7 +202,7 @@ parsestatdeclare indent:
calc varname lexident calc varname lexident
skipchar eol skipchar eol
calc varid registerid varname calc varid registervar varname
emit indent emit indent
emit varid emit varid
emitln " = alloca i8*" emitln " = alloca i8*"
@ -204,7 +218,7 @@ parsestatset indent:
skipchar " " skipchar " "
calc varname lexident calc varname lexident
calc varid registerid varname calc varid registervar varname
skipchar " " skipchar " "
emit indent emit indent
emit tmpvar emit tmpvar
@ -233,7 +247,7 @@ parsestatcalc indent:
skipchar " " skipchar " "
calc varname lexident calc varname lexident
calc varid registerid varname calc varid registervar varname
skipchar " " skipchar " "
emit indent emit indent
emit tmpvar emit tmpvar
@ -400,7 +414,7 @@ parsestatcheck indent:
skipchar " " skipchar " "
calc funcname lexident calc funcname lexident
calc funcid registerid funcname calc funcid registerfunc funcname
emit indent emit indent
emit funcresvar emit funcresvar
@ -464,7 +478,7 @@ parsestatcheck indent:
emit indent emit indent
emit " " emit " "
emit stderrvar emit stderrvar
emitln " = load %FILE*, %FILE** @stderrvar" emitln " = load %FILE*, %FILE** @stderr"
emit indent emit indent
emit " call i32 @fputs(i8* @str.ERROR, %FILE* " emit " call i32 @fputs(i8* @str.ERROR, %FILE* "
@ -527,7 +541,7 @@ parsestattrace indent:
skipchar eol skipchar eol
calc callconstid makestringconst varname calc callconstid makestringconst varname
calc varid registerid varname calc varid registervar varname
emit indent emit indent
emit "call void @__trace(i8* @str." emit "call void @__trace(i8* @str."
@ -551,6 +565,7 @@ parsestat indent:
declare isnotspace declare isnotspace
declare isnotquote declare isnotquote
calc call lexident calc call lexident
calc callid registerfunc call
trace call trace call
calc iscall eq call "declare" calc iscall eq call "declare"
if iscall if iscall
@ -599,8 +614,8 @@ parsestat indent:
/ /
check mapgetkey "FUNCREG" call "" : "Function" call "does not exist" check mapgetkey "FUNCREG" call "" : "Function" call "does not exist"
emit indent emit indent
emit "call i8* @id_" emit "call i8* "
emit call emit callid
emit "(" emit "("
set first "1" set first "1"
forever forever
@ -689,10 +704,11 @@ parsefunc:
declare varid declare varid
declare varname declare varname
calc funcname lexident calc funcname lexident
calc funcid registerfunc funcname
mapsetkey "FUNCREG" funcname "1" mapsetkey "FUNCREG" funcname "1"
trace funcname trace funcname
emit "define i8* @id_" emit "define i8* "
emit funcname emit funcid
emit "(" emit "("
set first "1" set first "1"
forever forever
@ -704,7 +720,7 @@ parsefunc:
/ /
skip skip
calc varname lexident calc varname lexident
calc varid registerid varname calc varid registervar varname
calc isfirst eq first "1" calc isfirst eq first "1"
calc isnotfirst not isfirst calc isnotfirst not isfirst
if isnotfirst if isnotfirst
@ -727,6 +743,7 @@ parsefunc:
emitln ")" emitln ")"
emitln "{" emitln "{"
parseblock " " parseblock " "
emitln " ret i8* @__EOF"
emitln "}" emitln "}"
emit eol emit eol
return return
@ -757,14 +774,51 @@ emitheader:
emit eol emit eol
emit "@__BACKSLASH = internal constant [2 x i8] c"
emit quote
emit backslash
emit backslash
emit backslash
emit "00"
emit quote
emitln ""
emit "@__EOF = internal constant [2 x i8] c"
emit quote
emit backslash
emit backslash
emit backslash
emit "FF"
emit quote
emitln ""
emit "@__EOL = internal constant [2 x i8] c" emit "@__EOL = internal constant [2 x i8] c"
emit quote emit quote
emit "\\0A\\00" emit backslash
emit "0A"
emit backslash
emit "00"
emitln quote emitln quote
emit "@__QUOTE = internal constant [2 x i8] c" emit "@__QUOTE = internal constant [2 x i8] c"
emit quote emit quote
emit "\\22\\00" emit backslash
emit "22"
emit backslash
emit "00"
emitln quote
emit "@__FALSE = internal constant [1 x i8] c"
emit quote
emit backslash
emit "00"
emitln quote
emit "@__TRUE = internal constant [2 x i8] c"
emit quote
emit "1"
emit backslash
emit "00"
emitln quote emitln quote
emit eol emit eol
@ -774,6 +828,75 @@ emitheader:
emitln " ret i8* %0" emitln " ret i8* %0"
emitln "}" emitln "}"
emitln "define i8* @__eq(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__lt(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__not(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__add(i8* %0, i8* %1)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__emit(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__trace(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__peek()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__skip()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__stdinlineno()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__stdincolno()"
emitln "{"
emitln " ret i8* @__EOL ; STUB"
emitln "}"
emitln "define i8* @__mapgetkey(i8* %0, i8* %1, i8* %2)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__mapsetkey(i8* %0, i8* %1, i8* %2)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__strlen(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emitln "define i8* @__intinc(i8* %0)"
emitln "{"
emitln " ret i8* %0 ; STUB"
emitln "}"
emit eol emit eol
@ -782,48 +905,58 @@ emitheader:
emitfooter: emitfooter:
declare constid declare constid
declare done
declare len
declare maxconstid
declare str declare str
declare strlenvar declare strlenvar
declare dontusethisstr declare dontusethisstr
emitln "define i64 @main() {"
emitln " call i8* @id_main()"
emitln " ret i64 0"
emitln "}"
emit "@str.ERROR = internal constant [7 x i8] c" emit "@str.ERROR = internal constant [7 x i8] c"
emit quote emit quote
emit "ERROR:\\00" emit "ERROR:"
emit backslash
emit "00"
emit quote emit quote
emitln "" emitln ""
emit "@str.EMPTY = internal constant [1 x i8] c" emit "@str.EMPTY = internal constant [1 x i8] c"
emit quote emit quote
emit "\\00" emit backslash
emit "00"
emit quote emit quote
emitln "" emitln ""
set constid "0"
set dontusethisstr "__dontusethisstr__" calc maxconstid mapgetkey "const_id_to_str" "___count___" "0"
set constid "01"
forever forever
calc str mapgetkey "stringconst" constid dontusethisstr calc str mapgetkey "const_id_to_str" constid "0"
declare unused calc len strlen str
calc unused eq str dontusethisstr calc len intinc len
if unused
break
/
calc strlen strlen str
emit "@str." emit "@str."
emit constid emit constid
emit " = internal constant [" emit " = internal constant ["
emit strlen emit len
emit " x i8] c" emit " x i8] c"
emit quote emit quote
emit str emit str
emit "\\00" emit backslash
emit "00"
emitln quote emitln quote
calc constid add constid "1" calc done eq constid maxconstid
if done
break
/
calc constid intinc constid
/ /
emit "" emit ""
@ -838,6 +971,7 @@ main:
emitheader emitheader
mapsetkey "REGISTERID" "backslash" "@__BACKSLASH"
mapsetkey "REGISTERID" "eof" "@__EOF" mapsetkey "REGISTERID" "eof" "@__EOF"
mapsetkey "REGISTERID" "eol" "@__EOL" mapsetkey "REGISTERID" "eol" "@__EOL"
mapsetkey "REGISTERID" "quote" "@__QUOTE" mapsetkey "REGISTERID" "quote" "@__QUOTE"
@ -866,6 +1000,10 @@ main:
mapsetkey "REGISTERID" "stdincolno" "@__stdincolno" mapsetkey "REGISTERID" "stdincolno" "@__stdincolno"
mapsetkey "FUNCREG" "stdinlineno" "1" mapsetkey "FUNCREG" "stdinlineno" "1"
mapsetkey "REGISTERID" "stdinlineno" "@__stdinlineno" mapsetkey "REGISTERID" "stdinlineno" "@__stdinlineno"
mapsetkey "FUNCREG" "strlen" "1"
mapsetkey "REGISTERID" "strlen" "@__strlen"
mapsetkey "FUNCREG" "intinc" "1"
mapsetkey "REGISTERID" "intinc" "@__intinc"
forever forever
calc char peek calc char peek

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

@ -0,0 +1,272 @@
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 %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* @__strlen(i8* %0)
{
ret i8* %0 ; STUB
}
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 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 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.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.w = internal constant [2 x i8] c"w\00"

View File

@ -2,10 +2,12 @@ all:
$(MAKE) -C 0-lang0py all $(MAKE) -C 0-lang0py all
$(MAKE) -C 1-lang0py all $(MAKE) -C 1-lang0py all
$(MAKE) -C 2-lang0c all $(MAKE) -C 2-lang0c all
$(MAKE) -C 3-lang0ll all
$(MAKE) -C tests all $(MAKE) -C tests all
clean: clean:
$(MAKE) -C 0-lang0py clean $(MAKE) -C 0-lang0py clean
$(MAKE) -C 1-lang0py clean $(MAKE) -C 1-lang0py clean
$(MAKE) -C 2-lang0c clean $(MAKE) -C 2-lang0c clean
$(MAKE) -C 3-lang0ll clean
$(MAKE) -C tests 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 ### Standard library constants
#### backslash
Backslash character.
#### eof #### eof
End of file character, zero byte. 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. 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 #### mapclear mapname
Maps are global and can be used from any function. 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) Returns the line number for stdin (starting at 1)
#### strlen a
Returns a string with the length of a.
### Typing ### Typing
Every variable is of type string. Every function gets a number of strings as output, and returns another string. 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 all: verify-results
Makefile.mk: generate-recipes.py $(wildcard test_*/test_*) 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 include Makefile.mk
@ -29,6 +29,10 @@ clean:
find build -name '*.it2.result' -delete find build -name '*.it2.result' -delete
find build -name '*.it2.stderr' -delete find build -name '*.it2.stderr' -delete
find build -name '*.it2.stdout' -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 '*.py' -delete
find build -name '*.tmp' -delete find build -name '*.tmp' -delete
@ -85,3 +89,19 @@ build/%.it2.o: build/%.it2.c
build/%.it2: build/%.it2.o build/%.it2: build/%.it2.o
$(CC) $(CFLAGS) -o $@ $^ -lpython$(PYVERSION) $(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.result
/*.it2.stderr /*.it2.stderr
/*.it2.stdout /*.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', 'it0': '.py',
'it1': '.py', 'it1': '.py',
'it2': '.c', 'it2': '.c',
'it3': '.ll',
} }
class Rule: 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: main:
declare var 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
/