diff --git a/3-lang0ll/Makefile b/3-lang0ll/Makefile index c5d6266..40b03c4 100644 --- a/3-lang0ll/Makefile +++ b/3-lang0ll/Makefile @@ -18,10 +18,10 @@ lang0ll0.c: lang0ll.lang0 $(LANG0C) cat $< | $(LANG0C) > $@ lang0ll0.o: lang0ll0.c - gcc -c $< + gcc -g -c $< lang0ll0.exe: lang0ll0.o - gcc -o $@ $< + gcc -g -o $@ $< lang0ll1.ll: lang0ll.lang0 lang0ll0.exe cat $< | ./lang0ll0.exe > $@ @@ -39,4 +39,4 @@ 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 + rm -f lang0ll*.c lang0ll*.ll lang0ll*.o lang0ll*.exe foo.ll foo.o foo.exe diff --git a/3-lang0ll/lang0ll.lang0 b/3-lang0ll/lang0ll.lang0 index 3be2e41..ca57217 100644 --- a/3-lang0ll/lang0ll.lang0 +++ b/3-lang0ll/lang0ll.lang0 @@ -1,9 +1,20 @@ -increaseindent indent: - calc indent addstringchar indent " " - calc indent addstringchar indent " " - calc indent addstringchar indent " " - calc indent addstringchar indent " " - return indent +registerid id: + declare idname + declare newidx + + calc idname mapgetkey "REGISTERID" id "" + if idname + return idname + / + + declare idnamea + calc idnamea add "id_" id + return idnamea +/ + +emitln data: + emit data + emit eol / lexident: @@ -22,16 +33,34 @@ lexident: if isafterz break / - calc word addstringchar word char + calc word add word char skip / return word / +skipchar exp: + declare act + declare lineno + declare colno + calc act peek + calc lineno stdinlineno + calc colno stdincolno + check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno + skip +/ + +increaseindent indent: + calc indent add indent " " + return indent +/ + parseconststring: declare char declare iseof declare isquote + declare str + set str "" skipchar quote forever calc char peek @@ -43,24 +72,43 @@ parseconststring: if isquote break / + calc str add str char skip / skipchar quote - emit "i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)" + + declare constid + calc constid mapgetkey "stringconst" str "" + declare isempty + calc isempty eq constid "" + if isempty + calc constid mapgetkey "stringconst" "___count___" "0" + calc constid add constid "1" + mapsetkey "stringconst" "___count___" constid + / + mapsetkey "stringconst" str constid + mapsetkey "stringconst" constid str + + emit "i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @str." + emit constid + emit ", i64 0, i64 0)" return / parseexprvarref: + declare varid declare varname calc varname lexident + calc varid registerid varname emit "i8* %" - emit varname + emit varid return / parseexprcall: declare char declare first + declare funcid declare funcname declare isspace declare isnotspace @@ -69,7 +117,9 @@ parseexprcall: declare isquote declare isnotquote calc funcname lexident - emit funcname + check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist" + calc funcid registerid funcname + emit funcid emit "(" set first "1" forever @@ -101,26 +151,23 @@ parseexprcall: / parsestatdeclare indent: - declare var + declare varid + declare varname skipchar " " - calc var lexident - emit indent - emit "char * var_" - emit var - emit ";" - emit eol + calc varname lexident skipchar eol return / parsestatset indent: - declare var + declare varid + declare varname skipchar " " - calc var lexident + calc varname lexident + calc varid registerid varname skipchar " " emit indent - emit "var_" - emit var + emit varid emit " = " parseconststring emit ";" @@ -130,19 +177,19 @@ parsestatset indent: / parsestatcalc indent: - declare var + declare varid + declare varname declare varidx skipchar " " - calc var lexident + calc varname lexident + calc varid registerid varname skipchar " " emit indent emit "%" - emit var - calc varidx mapgetkey "funcvarused" var - calc varidx intinc varidx - mapsetkey "funcvarused" var varidx - emit "." - emit varidx + emit varid + calc varidx mapgetkey "funcvarused" varid "" + calc varidx add varidx "1" + mapsetkey "funcvarused" varid varidx emit " = call i8* @" parseexprcall emit ";" @@ -154,39 +201,85 @@ parsestatcalc indent: parseblock indent/ parsestatif indent: - declare indentt skipchar " " + + declare strlenvar + calc strlenvar mapgetkey "localvarused" "" "" + calc strlenvar add strlenvar "1" + mapsetkey "localvarused" "" strlenvar + trace strlenvar emit indent - emit "if ( 0 < strlen(" + emit "%" + emit strlenvar + emit " = call i64 @__strlen(" parseexprvarref - emit ") )\n" - emit indent - emit "{\n" skipchar eol + emitln ")" + + declare strnotemptyvar + calc strnotemptyvar mapgetkey "localvarused" "" "" + calc strnotemptyvar add strnotemptyvar "1" + mapsetkey "localvarused" "" strnotemptyvar + trace strnotemptyvar + + emit indent + emit "%" + emit strnotemptyvar + emit " = icmp ne i64 %" + emit strlenvar + emitln ", 0" + + declare labelnotempty + calc labelnotempty mapgetkey "locallabelused" "" "" + calc labelnotempty add labelnotempty "1" + mapsetkey "locallabelused" "" labelnotempty + trace labelnotempty + + declare labelempty + calc labelempty mapgetkey "locallabelused" "" "" + calc labelempty add labelempty "1" + mapsetkey "locallabelused" "" labelempty + trace labelempty + + emit indent + emit "br i1 %" + emit strnotemptyvar + emit ", label %lbl" + emit labelnotempty + emit ", label %lbl" + emitln labelempty + + emit "lbl" + emit labelnotempty + emitln ":" + declare indentt calc indentt increaseindent indent parseblock indentt - emit indent - emit "}\n" + + emit "lbl" + emit labelempty + 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 / @@ -194,6 +287,8 @@ parsestatbreak indent: parsestatreturn indent: declare char declare isspace + declare isnotquote + declare isquote declare isnotspace emit indent emit "ret " @@ -202,7 +297,15 @@ parsestatreturn indent: calc isnotspace not isspace if isspace skip - parseexprvarref + calc char peek + calc isquote eq char quote + calc isnotquote not isquote + if isquote + parseconststring + / + if isnotquote + parseexprvarref + / / if isnotspace emit "i18* 0" @@ -213,24 +316,130 @@ parsestatreturn indent: return / +parsestatcheck indent: + declare char + declare funcid + declare funcname + declare iscolon + declare iseol + declare isnotquote + declare isquote + declare notfirst + + skipchar " " + emit indent + emit "if( 0 == strlen(" + + calc funcname lexident + calc funcid registerid funcname + emit funcid + emit "(" + + set notfirst "" + forever + skipchar " " + calc char peek + calc iscolon eq char ":" + if iscolon + break + / + + if notfirst + emit ", " + / + + calc char peek + calc isquote eq char quote + calc isnotquote not isquote + if isquote + parseconststring + / + if isnotquote + parseexprvarref + / + + set notfirst "1" + / + + skipchar ":" + + emitln ")) )" + emit indent + emitln "{" + + emit indent + emit " fprintf(stderr, " + emit quote + emit "%s" + emit quote + emit ", " + emit quote + emit "ERROR:" + emit quote + emitln ");" + + forever + skipchar " " + + emit indent + emit " fprintf(stderr, " + emit quote + emit " %s" + emit quote + emit ", " + calc char peek + calc isquote eq char quote + calc isnotquote not isquote + if isquote + parseconststring + / + if isnotquote + parseexprvarref + / + emitln ");" + + calc char peek + calc iseol eq char eol + if iseol + break + / + / + + emit indent + emit " fprintf(stderr, " + emit quote + emit "%s" + emit quote + emit ", __EOL" + emitln ");" + + emit indent + emitln " exit(1);" + emit indent + emitln "}" +/ + parsestattrace indent: + declare varid declare varname emit indent - emit "trace(" + emit "__trace(" emit quote skipchar " " calc varname lexident + calc varid registerid varname emit varname emit quote - emit ", var_" - emit varname - emit ");\n" + emit ", " + emit varid + emitln ");" skipchar eol return / parsestat indent: declare call + declare callid declare char declare first declare iscall @@ -277,13 +486,20 @@ parsestat indent: parsestatreturn indent return / + calc iscall eq call "check" + if iscall + parsestatcheck indent + return + / calc iscall eq call "trace" if iscall parsestattrace indent return / + check mapgetkey "FUNCREG" call "" : "Function" call "does not exist" + calc callid registerid call emit indent - emit call + emit callid emit "(" set first "1" forever @@ -297,21 +513,21 @@ parsestat indent: calc char peek calc isquote eq char quote calc isnotquote not isquote + calc isfirst eq first "1" + calc isnotfirst not isfirst + if isnotfirst + emit ", " + / if isquote parseconststring / if isnotquote parseexprvarref / - calc isfirst eq first "1" - calc isnotfirst not isfirst - if isnotfirst - emit ", " - / set first "0" / skipchar eol - emit ");\n" + emitln ");" return / @@ -357,15 +573,20 @@ parseblock indent: parsefunc: declare char declare first + declare funcid declare funcname declare iseoblock declare isfirst + declare ismain + declare isnotmain declare isspace declare isnotfirst declare isnotspace - declare var - mapclear "funcvarused" + declare varid + declare varname calc funcname lexident + mapsetkey "FUNCREG" funcname "1" + calc funcid registerid funcname trace funcname emit "define i8* @" emit funcname @@ -379,16 +600,16 @@ parsefunc: break / skip - calc var lexident + calc varname lexident + calc varid registerid varname calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / emit "i8* %" - emit var - mapsetkey "funcvarused" "var" "0" - emit "_0" + emit varid + mapsetkey "funcvarused" varid "0" set first "0" / calc char peek @@ -396,15 +617,16 @@ 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 / @@ -440,6 +662,32 @@ emitheader: / emitfooter: + declare constid + declare str + declare dontusethisstr + + set dontusethisstr "__dontusethisstr__" + + set constid "01" + forever + calc str mapgetkey "stringconst" constid dontusethisstr + + declare unused + calc unused eq str dontusethisstr + if unused + break + / + + emit "@str." + emit constid + emit " = internal constant [33 x i8] c" + emit quote + emit str + emitln quote + + calc constid add constid "1" + / + emit "" return / @@ -449,7 +697,38 @@ main: declare iseof declare iseol declare isnoteol + emitheader + + mapsetkey "REGISTERID" "eof" "__EOF" + mapsetkey "REGISTERID" "eol" "__EOL" + mapsetkey "REGISTERID" "quote" "__QUOTE" + + mapsetkey "FUNCREG" "add" "1" + mapsetkey "REGISTERID" "add" "__add" + mapsetkey "FUNCREG" "emit" "1" + mapsetkey "REGISTERID" "emit" "__emit" + mapsetkey "FUNCREG" "eq" "1" + mapsetkey "REGISTERID" "eq" "__eq" + mapsetkey "FUNCREG" "lt" "1" + mapsetkey "REGISTERID" "lt" "__lt" + mapsetkey "FUNCREG" "not" "1" + mapsetkey "REGISTERID" "not" "__not" + mapsetkey "FUNCREG" "mapclear" "1" + mapsetkey "REGISTERID" "mapclear" "__mapclear" + mapsetkey "FUNCREG" "mapgetkey" "1" + mapsetkey "REGISTERID" "mapgetkey" "__mapgetkey" + mapsetkey "FUNCREG" "mapsetkey" "1" + mapsetkey "REGISTERID" "mapsetkey" "__mapsetkey" + mapsetkey "FUNCREG" "peek" "1" + mapsetkey "REGISTERID" "peek" "__peek" + mapsetkey "FUNCREG" "skip" "1" + mapsetkey "REGISTERID" "skip" "__skip" + mapsetkey "FUNCREG" "stdincolno" "1" + mapsetkey "REGISTERID" "stdincolno" "__stdincolno" + mapsetkey "FUNCREG" "stdinlineno" "1" + mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno" + forever calc char peek calc iseof eq char eof