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 return "" / makelocalvar: declare prevvar declare newvar declare result calc prevvar mapgetkey "localvarused" "" "" calc newvar add prevvar "1" mapsetkey "localvarused" "" newvar calc result add "%tmp" newvar return result / makelocallabel: declare prevlabel declare newlabel declare result calc prevlabel mapgetkey "locallabelused" "" "" calc newlabel add prevlabel "1" mapsetkey "locallabelused" "" newlabel calc result add "lbl" newlabel return result / makestringconst str: declare constid declare isempty calc constid mapgetkey "stringconst" str "" 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 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 registerid 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 check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist" emit "@id_" emit funcname 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 registerid 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 registerid 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 registerid 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 registerid 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** @stderrvar" 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 registerid 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 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* @id_" emit call 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 mapsetkey "FUNCREG" funcname "1" trace funcname emit "define i8* @id_" emit funcname 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 registerid 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 "}" 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 "@__EOL = internal constant [2 x i8] c" emit quote emit "\\0A\\00" emitln quote emit "@__QUOTE = internal constant [2 x i8] c" emit quote emit "\\22\\00" emitln quote emit eol emitln "define i8* @__drop_i8_type(i8* %0) alwaysinline readnone" emitln "{" emitln " ret i8* %0" emitln "}" emit eol return / emitfooter: declare constid declare str declare strlenvar declare dontusethisstr emit "@str.ERROR = internal constant [7 x i8] c" emit quote emit "ERROR:\\00" emit quote emitln "" emit "@str.EMPTY = internal constant [1 x i8] c" emit quote emit "\\00" emit quote emitln "" set dontusethisstr "__dontusethisstr__" set constid "01" forever calc str mapgetkey "stringconst" constid dontusethisstr declare unused calc unused eq str dontusethisstr if unused break / calc strlen strlen str emit "@str." emit constid emit " = internal constant [" emit strlen emit " x i8] c" emit quote emit str emit "\\00" emitln quote calc constid add constid "1" / emit "" return / main: declare char 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 if iseof break / forever calc char peek calc iseol eq char eol calc isnoteol not iseol if isnoteol break / skip / parsefunc / emitfooter return /