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 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 return "" / makelocalvar: declare prevvar declare newvar declare result calc prevvar mapgetkey "localvarused" "" "0" calc newvar intinc prevvar mapsetkey "localvarused" "" newvar calc result add "%tmp" newvar return result / makelocallabel: declare prevlabel declare newlabel declare result calc prevlabel mapgetkey "locallabelused" "" "0" calc newlabel intinc prevlabel mapsetkey "locallabelused" "" newlabel calc result add "lbl" newlabel return result / makestringconst str: declare constid declare isempty calc constid mapgetkey "str_to_const_id" str "" calc isempty eq constid "" if isempty calc constid mapgetkey "const_id_to_str" "___count___" "0" calc constid intinc constid mapsetkey "const_id_to_str" "___count___" constid / mapsetkey "str_to_const_id" str constid mapsetkey "const_id_to_str" constid str return constid / lexident: declare char declare isbeforea declare isafterz declare word set word "" forever calc char peek calc isbeforea lt char "a" if isbeforea break / calc isafterz lt "z" char if isafterz break / calc word 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 return "" / 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 calc iseof eq char eof if iseof break / calc isquote eq char quote if isquote break / calc str add str char skip / skipchar quote declare constid calc constid makestringconst str emit "i8* @str." emit constid return / parseexprvarref: declare varid declare varname calc varname lexident calc varid registervar varname emit "i8* " emit varid return / parseexprcall: declare char declare first declare funcid declare funcname declare isspace declare isnotspace declare isfirst declare isnotfirst declare isquote declare isnotquote calc funcname lexident calc funcid registerfunc funcname check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist" emit funcid emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / set first "0" / emit ")" return / parsestatdeclare indent: declare varid declare varname skipchar " " calc varname lexident skipchar eol calc varid registervar varname emit indent emit varid emitln " = alloca i8*" return / parsestatset indent: declare tmpvar declare varid declare varname calc tmpvar makelocalvar skipchar " " calc varname lexident calc varid registervar varname skipchar " " emit indent emit tmpvar emit " = call i8* @__drop_i8_type(" parseconststring emit ")" emit eol skipchar eol emit indent emit "store i8* " emit tmpvar emit ", i8**" emit varid emitln "" return / parsestatcalc indent: declare varid declare varname declare tmpvar calc tmpvar makelocalvar skipchar " " calc varname lexident calc varid registervar varname skipchar " " emit indent emit tmpvar emit " = call i8* " parseexprcall emit eol skipchar eol emit indent emit "store i8* " emit tmpvar emit ", i8**" emit varid emitln "" return / parseblock indent/ parsestatif indent: declare labelempty declare labelnotempty declare strlenvar declare strnotemptyvar calc strlenvar makelocalvar calc strnotemptyvar makelocalvar calc labelempty makelocallabel calc labelnotempty makelocallabel skipchar " " emit indent emit strlenvar emit " = call i64 @__strlen(" parseexprvarref skipchar eol emitln ")" emit indent emit strnotemptyvar emit " = icmp ne i64 " emit strlenvar emitln ", 0" emit indent emit "br i1 " emit strnotemptyvar emit ", label %" emit labelnotempty emit ", label %" emitln labelempty emit labelnotempty emitln ":" declare indentt calc indentt increaseindent indent parseblock indentt emit indentt emit "br label %" emitln labelempty emit labelempty emitln ":" return / parsestatforever indent: declare endlabel declare indentt declare startlabel calc endlabel makelocallabel calc startlabel makelocallabel calc indentt increaseindent indent mapsetkey "foreverstatendlabel" "" endlabel emit indent emit "br label %" emitln startlabel emit startlabel emitln ":" skipchar eol parseblock indentt emit indent emit "br label %" emitln startlabel emit endlabel emitln ":" return / parsestatbreak indent: declare endlabel calc endlabel mapgetkey "foreverstatendlabel" "" "?" emit indent emit "br label %" emitln endlabel skipchar eol return / parsestatreturn indent: declare char declare isspace declare isnotquote declare isquote declare isnotspace emit indent emit "ret " calc char peek calc isspace eq char " " calc isnotspace not isspace if isspace skip calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / / if isnotspace emit "i8* @str.EMPTY" / emit eol skipchar eol return / parsestatcheck indent: declare char declare funcid declare funcname declare iscolon declare iseol declare isnotquote declare isquote declare notfirst declare funcresvar declare labelfail declare labelnotfail declare strlenvar declare strnotemptyvar declare stderrvar calc funcresvar makelocalvar calc strlenvar makelocalvar calc strnotemptyvar makelocalvar calc stderrvar makelocalvar calc labelfail makelocallabel calc labelnotfail makelocallabel skipchar " " calc funcname lexident calc funcid registerfunc funcname emit indent emit funcresvar emit " = call i8* " 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 emit strlenvar emit " = call i64 @__strlen(i8* " emit funcresvar emitln ")" emit indent emit strnotemptyvar emit " = icmp ne i64 " emit strlenvar emitln ", 0" emit indent emit "br i1 " emit strnotemptyvar emit ", label %" emit labelnotfail emit ", label %" emitln labelfail emit labelfail emitln ":" emit indent emit " " emit stderrvar emitln " = load %FILE*, %FILE** @stderr" emit indent emit " call i32 @fputs(i8* @str.ERROR, %FILE* " emit stderrvar 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 " call void @exit(i32 1)" emit indent emitln " unreachable" emit labelnotfail emitln ":" return / parsestattrace indent: declare varid declare varname declare callconstid skipchar " " calc varname lexident skipchar eol calc callconstid makestringconst varname calc varid registervar varname emit indent emit "call void @__trace(i8* @str." emit callconstid emit ", i8* " emit varid emitln ")" return / parsestat indent: declare call declare callid declare char declare first declare iscall declare isfirst declare isspace declare isquote declare isnotfirst declare isnotspace declare isnotquote calc call lexident calc callid registerfunc call trace call calc iscall eq call "declare" if iscall parsestatdeclare indent return / calc iscall eq call "set" if iscall parsestatset indent return / calc iscall eq call "calc" if iscall parsestatcalc indent return / calc iscall eq call "if" if iscall parsestatif indent return / calc iscall eq call "forever" if iscall parsestatforever indent return / calc iscall eq call "break" if iscall parsestatbreak indent return / calc iscall eq call "return" if iscall parsestatreturn indent return / calc iscall eq call "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" emit indent emit "call i8* " emit callid emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc char peek calc isquote eq char quote calc isnotquote not isquote calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / if isquote parseconststring / if isnotquote parseexprvarref / set first "0" / skipchar eol emitln ")" return / parseblock indent: declare char declare copy declare iseol declare isnoteol declare isdone declare iseoblock forever forever calc char peek calc iseol eq char eol calc isnoteol not iseol if isnoteol break / skip / set copy " " forever calc isdone eq copy indent if isdone break / skipchar "\t" calc copy increaseindent copy / calc char peek calc iseoblock eq char "/" if iseoblock skip skipchar eol break / skipchar "\t" parsestat indent / return / parsefunc: mapsetkey "localvarused" "" "0" mapsetkey "locallabelused" "" "0" declare char declare first declare funcid declare funcname declare iseoblock declare isfirst declare ismain declare isnotmain declare isspace declare isnotfirst declare isnotspace declare varid declare varname calc funcname lexident calc funcid registerfunc funcname mapsetkey "FUNCREG" funcname "1" trace funcname emit "define i8* " emit funcid emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc varname lexident calc varid registervar varname calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / emit "i8* " emit varid set first "0" / calc char peek calc iseoblock eq char "/" if iseoblock skipchar "/" skipchar eol emitln " ; pre-declaration" return / skipchar ":" skipchar eol emitln ")" emitln "{" parseblock " " emitln " ret i8* @__EOF" emitln "}" emit eol return / emitheader: emit "target datalayout = " emit quote emit "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" emit quote emit eol emit "target triple = " emit quote emit "x86_64-pc-linux-gnu" emit quote emit eol emit eol emitln "%FILE = type opaque" emitln "@stderr = external global %FILE*" emit eol emitln "declare void @exit(i32)" emitln "declare i32 @fputs(i8*, %FILE*)" 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 quote emit backslash emit "0A" emit backslash emit "00" emitln quote emit "@__QUOTE = internal constant [2 x i8] c" emit quote 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 emit eol emitln "define i8* @__drop_i8_type(i8* %0) alwaysinline readnone" emitln "{" emitln " ret i8* %0" 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 return / emitfooter: declare constid declare done declare len declare maxconstid declare str declare strlenvar 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 quote emit "ERROR:" emit backslash emit "00" emit quote emitln "" emit "@str.EMPTY = internal constant [1 x i8] c" emit quote emit backslash emit "00" emit quote emitln "" set constid "0" calc maxconstid mapgetkey "const_id_to_str" "___count___" "0" forever calc str mapgetkey "const_id_to_str" constid "0" calc len strlen str calc len intinc len emit "@str." emit constid emit " = internal constant [" emit len emit " x i8] c" emit quote emit str emit backslash emit "00" emitln quote calc done eq constid maxconstid if done break / calc constid intinc constid / emit "" return / main: declare char declare iseof declare iseol declare isnoteol emitheader mapsetkey "REGISTERID" "backslash" "@__BACKSLASH" 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" mapsetkey "FUNCREG" "strlen" "1" mapsetkey "REGISTERID" "strlen" "@__strlen" mapsetkey "FUNCREG" "intinc" "1" mapsetkey "REGISTERID" "intinc" "@__intinc" forever calc char peek calc iseof eq char eof if iseof break / forever calc char peek calc iseol eq char eol calc isnoteol not iseol if isnoteol break / skip / parsefunc / emitfooter return /