cc_knight-native.s 140 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446
  1. ; Copyright (C) 2016 Jeremiah Orians
  2. ; This file is part of stage0.
  3. ;
  4. ; stage0 is free software: you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation, either version 3 of the License, or
  7. ; (at your option) any later version.
  8. ;
  9. ; stage0 is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with stage0. If not, see <http://www.gnu.org/licenses/>.
  16. ;; A Minimal C Compiler
  17. ;; type Cells are in the following form:
  18. ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
  19. ;; token_list Cells are in the following form:
  20. ;; NEXT (0), LOCALS/PREV (4), S (8), TYPE/FILENAME (12), ARGUMENTS/DEPTH/LINENUMBER (16)
  21. ;; Each being the length of a register [32bits]
  22. ;;
  23. ;; STACK space: End of program -> 512KB (0x80000) [Could be reduced]
  24. ;; HEAP space: 512KB -> End of Memory
  25. ;; R15 is the STACK pointer
  26. ;; R14 is the HEAP pointer
  27. :start
  28. ;; Prep TAPE_02
  29. LOADUI R0 0x1101
  30. FOPEN_WRITE
  31. ;; Prep TAPE_01
  32. LOADUI R0 0x1100
  33. FOPEN_READ
  34. :main
  35. LOADUI R0 0x1100 ; Pass Tape_01 for reading
  36. LOADR32 R14 @HEAP ; Setup Initial HEAP
  37. LOADUI R15 $STACK ; Setup Initial STACK
  38. CALLI R15 @read_all_tokens ; Read all Tokens in Tape_01
  39. CALLI R15 @reverse_list ; Fix Token Order
  40. ; CALLI R15 @debug_list ; Lets try to debug token errors
  41. MOVE R13 R0 ; Set global_token for future reading
  42. FALSE R12 ; Set struct token_list* out to NULL
  43. FALSE R11 ; Set struct token_list* list_strings to NULL
  44. FALSE R10 ; Set struct token_list* globals_list to NULL
  45. CALLI R15 @program ; Build our output
  46. LOADUI R0 $header_string1 ; Using our first header string
  47. LOADUI R1 0x1101 ; Using Tape_02
  48. CALLI R15 @file_print ; Write string
  49. MOVE R0 R12 ; using Contents of output_list
  50. CALLI R15 @recursive_output ; Recursively write
  51. LOADUI R0 $header_string2 ; Using our second header string
  52. CALLI R15 @file_print ; Write string
  53. MOVE R0 R10 ; using Contents of globals_list
  54. CALLI R15 @recursive_output ; Recursively write
  55. LOADUI R0 $header_string3 ; Using our third header string
  56. CALLI R15 @file_print ; Write string
  57. MOVE R0 R11 ; using Contents of strings_list
  58. CALLI R15 @recursive_output ; Recursively write
  59. LOADUI R0 $header_string4 ; Using our final header string
  60. CALLI R15 @file_print ; Write string
  61. HALT ; We have completed compiling our input
  62. ;; Symbol lists
  63. :global_constant_list
  64. NOP
  65. :global_symbol_list
  66. NOP
  67. :global_function_list
  68. NOP
  69. ;; Pointer to initial HEAP ADDRESS
  70. :HEAP
  71. '00080000'
  72. ;; Output strings
  73. :header_string1
  74. "
  75. # Core program
  76. "
  77. :header_string2
  78. "
  79. # Program global variables
  80. "
  81. :header_string3
  82. "
  83. # Program strings
  84. "
  85. :header_string4
  86. "
  87. :STACK
  88. "
  89. ;; clearWhiteSpace function
  90. ;; Receives a character in R0 and FILE* in R1 and line_num in R11
  91. ;; Returns first non-whitespace character in R0
  92. :clearWhiteSpace
  93. CMPSKIPI.NE R0 32 ; Check for a Space
  94. JUMP @clearWhiteSpace_reset ; Looks like we need to remove a space
  95. CMPSKIPI.NE R0 9 ; Check for a tab
  96. JUMP @clearWhiteSpace_reset ; Looks like we need to remove a tab
  97. CMPSKIPI.E R0 10 ; Check for a newline
  98. RET R15 ; Looks we found a non-whitespace
  99. ADDUI R11 R11 1 ; Increment line number
  100. ;; Fall through to iterate to next char
  101. :clearWhiteSpace_reset
  102. FGETC ; Get next char
  103. JUMP @clearWhiteSpace ; Iterate
  104. ;; consume_byte function
  105. ;; Receives a char in R0, FILE* in R1 and index in R13
  106. ;; Returns next char in R0
  107. :consume_byte
  108. STOREX8 R0 R14 R13 ; Put char onto HEAP
  109. ADDUI R13 R13 1 ; Increment index
  110. FGETC ; Get next char
  111. RET R15
  112. ;; consume_word function
  113. ;; Receives a char in R0, FILE* in R1, FREQUENT in R2 and index in R13
  114. ;; Returns next char in R0
  115. :consume_word
  116. PUSHR R3 R15 ; Protect R3
  117. FALSE R3 ; ESCAPE is FALSE
  118. :consume_word_reset
  119. JUMP.NZ R3 @consume_word_iter1
  120. CMPSKIPI.NE R0 92 ; If \
  121. TRUE R3 ; Looks like we are in an escape
  122. JUMP @consume_word_iter2
  123. :consume_word_iter1
  124. FALSE R3 ; Looks like we are no longer in an escape
  125. :consume_word_iter2
  126. CALLI R15 @consume_byte ; Store the char
  127. JUMP.NZ R3 @consume_word_reset ; If escape loop
  128. CMPJUMPI.NE R0 R2 @consume_word_reset ; if not matching frequent loop
  129. FGETC ; Get a new char to return
  130. POPR R3 R15 ; Restore R3
  131. RET R15
  132. ;; fixup_label function
  133. ;; Receives nothing (But uses R14 as HEAP pointer)
  134. ;; Returns 32 in R0 and no other registers altered
  135. :fixup_label
  136. PUSHR R1 R15 ; Protect R1 from change
  137. PUSHR R2 R15 ; Protect R2 from change
  138. LOADUI R0 58 ; Set HOLD to :
  139. FALSE R2 ; Set I to 0
  140. :fixup_label_reset
  141. MOVE R1 R0 ; Set PREV = HOLD
  142. LOADXU8 R0 R14 R2 ; Read hold_string[I] into HOLD
  143. STOREX8 R1 R14 R2 ; Set hold_string[I] = PREV
  144. ADDUI R2 R2 1 ; increment I
  145. JUMP.NZ R0 @fixup_label_reset ; Loop until we hit a NULL
  146. ;; clean up
  147. ADDUI R2 R2 1 ; increment I
  148. LOADUI R0 32 ; Put 32 in R0
  149. POPR R2 R15 ; Restore R2
  150. POPR R1 R15 ; Restore R1
  151. RET R15
  152. ;; in_set2 function
  153. ;; Receives a Char in R0, FILE* in R1, char* in R2 and index in R13
  154. ;; Return result in R2
  155. :in_set2
  156. PUSHR R3 R15 ; Protect R3 from changes
  157. :in_set2_reset
  158. LOADU8 R3 R2 0 ; Get char from list
  159. JUMP.Z R3 @in_set2_fail ; Stop when 0 == s[0]
  160. CMPJUMPI.E R0 R3 @in_set2_done ; We found a match
  161. ADDUI R2 R2 1 ; Increment to next char
  162. JUMP.NZ R3 @in_set2_reset ; Iterate if not NULL
  163. :in_set2_fail
  164. ;; Looks like not found
  165. FALSE R2 ; Return FALSE
  166. :in_set2_done
  167. CMPSKIPI.E R2 0 ; Provided not FALSE
  168. TRUE R2 ; The result is true
  169. POPR R3 R15 ; Restore R3
  170. RET R15
  171. ;; in_set function
  172. ;; Receives a Char in R0, char* in R1
  173. ;; Return result in R0
  174. :in_set
  175. PUSHR R2 R15 ; Protect R3 from changes
  176. :in_set_reset
  177. LOADU8 R2 R1 0 ; Get char from list
  178. JUMP.Z R2 @in_set_fail ; Stop when 0 == s[0]
  179. CMPJUMPI.E R0 R2 @in_set_done ; We found a match
  180. ADDUI R1 R1 1 ; Increment to next char
  181. JUMP.NZ R2 @in_set_reset ; Iterate if not NULL
  182. :in_set_fail
  183. ;; Looks like not found
  184. FALSE R1 ; Return FALSE
  185. :in_set_done
  186. CMPSKIPI.E R1 0 ; Provided not FALSE
  187. TRUE R2 ; The result is true
  188. MOVE R0 R2 ; Put result in correct place
  189. POPR R2 R15 ; Restore R3
  190. RET R15
  191. ;; Common in_set strings of interest
  192. ;; As Raw strings (") is forbidden and ' has some restrictions
  193. :nice_chars
  194. "
  195. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
  196. :keyword_chars
  197. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
  198. :variable_chars
  199. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
  200. :symbol_chars
  201. "<=>|&!-"
  202. :hex_chars
  203. "0123456789ABCDEF"
  204. :digit_chars
  205. "0123456789"
  206. :whitespace_chars
  207. "
  208. "
  209. ;; preserve_keyword function
  210. ;; Receives a Char in R0, FILE* in R1 and index in R13
  211. ;; Overwrites R2
  212. ;; Returns next CHAR
  213. :preserve_keyword
  214. LOADUI R2 $keyword_chars ; Using keyword list of chars
  215. CALLI R15 @in_set2 ; Check if in list
  216. JUMP.Z R2 @preserve_keyword_label ; if not in set, stop iterating
  217. :preserve_keyword_reset
  218. CALLI R15 @consume_byte ; Consume another byte
  219. JUMP @preserve_keyword ; Iterate
  220. :preserve_keyword_label
  221. CMPSKIPI.NE R0 58 ; Check for label (:)
  222. CALLI R15 @fixup_label ; Looks like we found one
  223. RET R15
  224. ;; preserve_symbol function
  225. ;; Receives a Char in R0, FILE* in R1 and index in R13
  226. ;; Overwrites R2
  227. ;; Returns next CHAR
  228. :preserve_symbol
  229. LOADUI R2 $symbol_chars ; Using symbol list of chars
  230. CALLI R15 @in_set2 ; Check if in list
  231. JUMP.NZ R2 @preserve_symbol_reset
  232. ;; Looks we didn't find anything we wanted to preserve
  233. RET R15
  234. :preserve_symbol_reset
  235. CALLI R15 @consume_byte ; Consume another byte
  236. JUMP @preserve_symbol ; Iterate
  237. ;; purge_macro function
  238. ;; Receives a Char in R0, FILE* in R1 and index in R13
  239. ;; Returns next CHAR via jumping to get_token_reset
  240. :purge_macro
  241. CMPSKIPI.NE R0 10 ; Check for Line Feed
  242. JUMP @get_token_reset ; Looks like we found it, call it done
  243. FGETC ; Looks like we need another CHAR
  244. JUMP @purge_macro ; Keep looping
  245. ;; get_token function
  246. ;; Receives a Char in R0, FILE* in R1, line_num in R11 and TOKEN in R10
  247. ;; sets index in R13 and current in R12
  248. ;; Overwrites R2
  249. ;; Returns next CHAR
  250. :get_token
  251. PUSHR R12 R15 ; Preserve R12
  252. PUSHR R13 R15 ; Preserve R13
  253. COPY R12 R14 ; Save CURRENT's Address
  254. ADDUI R14 R14 20 ; Update Malloc to free space for string
  255. :get_token_reset
  256. FALSE R13 ; Reset string_index to 0
  257. CALLI R15 @clearWhiteSpace ; Clear any leading whitespace
  258. CMPSKIPI.NE R0 35 ; Deal with # line macros
  259. JUMP @purge_macro ; Returns at get_token_reset
  260. ;; Check for keywords
  261. LOADUI R2 $keyword_chars ; Using keyword list
  262. CALLI R15 @in_set2 ; Check if keyword
  263. JUMP.Z R2 @get_token_symbol ; if not a keyword
  264. CALLI R15 @preserve_keyword ; Yep its a keyword
  265. JUMP @get_token_done ; Be done with token
  266. ;; Check for symbols
  267. :get_token_symbol
  268. LOADUI R2 $symbol_chars ; Using symbol list
  269. CALLI R15 @in_set2 ; Check if symbol
  270. JUMP.Z R2 @get_token_char ; If not a symbol
  271. CALLI R15 @preserve_symbol ; Yep its a symbol
  272. JUMP @get_token_done ; Be done with token
  273. ;; Check for char
  274. :get_token_char
  275. CMPSKIPI.E R0 39 ; Check if '
  276. JUMP @get_token_string ; Not a '
  277. COPY R2 R0 ; Prepare for consume_word
  278. CALLI R15 @consume_word ; Call it
  279. JUMP @get_token_done ; Be done with token
  280. ;; Check for string
  281. :get_token_string
  282. CMPSKIPI.E R0 34 ; Check if "
  283. JUMP @get_token_EOF ; Not a "
  284. COPY R2 R0 ; Prepare for consume_word
  285. CALLI R15 @consume_word ; Call it
  286. JUMP @get_token_done ; Be done with token
  287. ;; Check for EOF
  288. :get_token_EOF
  289. CMPSKIPI.L R0 0 ; If c < 0
  290. JUMP @get_token_comment ; If not EOF
  291. POPR R13 R15 ; Restore R13
  292. POPR R12 R15 ; Restore R12
  293. RET R15 ; Otherwise just return the EOF
  294. ;; Check for C comments
  295. :get_token_comment
  296. CMPSKIPI.E R0 47 ; Deal with non-comments
  297. JUMP @get_token_else ; immediately
  298. CALLI R15 @consume_byte ; Deal with another byte
  299. CMPSKIPI.NE R0 42 ; if * make it a block comment
  300. JUMP @get_token_comment_block ; and purge it all
  301. CMPSKIPI.E R0 47 ; Check if not //
  302. JUMP @get_token_done ; Finish off the token
  303. ;; Looks like it was //
  304. FGETC ; Get next char
  305. JUMP @get_token_reset ; Try again
  306. ;; Deal with the mess that is C block comments
  307. :get_token_comment_block
  308. FGETC ; Get next char
  309. :get_token_comment_block_outer
  310. CMPSKIPI.NE R0 47 ; Check for closing /
  311. JUMP @get_token_comment_block_outer_done ; Yep has closing /
  312. :get_token_comment_block_inner
  313. CMPSKIPI.NE R0 42 ; Check for preclosing *
  314. JUMP @get_token_comment_block_inner_done ; Yep has *
  315. ;; Otherwise we are just consuming
  316. FGETC ; Remove another CHAR
  317. CMPSKIPI.NE R0 10 ; Check for Line Feed
  318. ADDUI R11 R11 1 ; Found one, updating line number
  319. JUMP @get_token_comment_block_inner
  320. :get_token_comment_block_inner_done
  321. FGETC ; Remove another CHAR
  322. CMPSKIPI.NE R0 10 ; Check for Line Feed
  323. ADDUI R11 R11 1 ; Found one, updating line number
  324. JUMP @get_token_comment_block_outer
  325. :get_token_comment_block_outer_done
  326. FGETC ; Remove another CHAR
  327. JUMP @get_token_reset ; And Try again
  328. ;; Deal with default case
  329. :get_token_else
  330. CALLI R15 @consume_byte ; Consume the byte and be done
  331. :get_token_done
  332. ADDUI R13 R13 2 ; Pad with NULL the string
  333. STORE32 R14 R12 8 ; Set CURRENT->S to String
  334. ADD R14 R14 R13 ; Add string length to HEAP
  335. STORE32 R10 R12 0 ; CURRENT->NEXT = TOKEN
  336. STORE32 R10 R12 4 ; CURRENT->PREV = TOKE
  337. STORE32 R11 R12 16 ; CURRENT->LINENUM = LINE_NUM
  338. MOVE R10 R12 ; SET TOKEN to CURRENT
  339. POPR R13 R15 ; Restore R13
  340. POPR R12 R15 ; Restore R12
  341. RET R15
  342. ;; reverse_list function
  343. ;; Receives a Token_list in R0
  344. ;; Returns List in Reverse order in R0
  345. :reverse_list
  346. PUSHR R1 R15 ; Protect R1
  347. PUSHR R2 R15 ; Protect R2
  348. FALSE R1 ; Set ROOT to NULL
  349. CMPJUMPI.E R0 R1 @reverse_list_done ; ABORT if given a NULL
  350. :reverse_list_reset
  351. LOAD32 R2 R0 0 ; SET next to HEAD->NEXT
  352. STORE32 R1 R0 0 ; SET HEAD->NEXT to ROOT
  353. MOVE R1 R0 ; SET ROOT to HEAD
  354. MOVE R0 R2 ; SET HEAD to NEXT
  355. JUMP.NZ R0 @reverse_list_reset ; Iterate if HEAD not NULL
  356. :reverse_list_done
  357. MOVE R0 R1 ; SET Result to ROOT
  358. POPR R2 R15 ; Restore R2
  359. POPR R1 R15 ; Restore R1
  360. RET R15
  361. ;; read_all_tokens function
  362. ;; Receives a FILE* in R0
  363. ;; sets line_num in R11 and TOKEN in R10
  364. ;; Overwrites R2
  365. ;; Returns struct token_list* in R0
  366. :read_all_tokens
  367. PUSHR R1 R15 ; Protect R1
  368. PUSHR R2 R15 ; Protect R2
  369. PUSHR R10 R15 ; Protect R10
  370. PUSHR R11 R15 ; Protect R11
  371. MOVE R1 R0 ; Set R1 as FILE*
  372. FGETC ; Read our first CHAR
  373. LOADUI R11 1 ; Start line_num at 1
  374. FALSE R10 ; First token is NULL
  375. :read_all_tokens_reset
  376. JUMP.NP R0 @read_all_tokens_done
  377. CALLI R15 @get_token
  378. JUMP @read_all_tokens_reset
  379. :read_all_tokens_done
  380. MOVE R0 R10 ; Return the Token
  381. POPR R11 R15 ; Restore R11
  382. POPR R10 R15 ; Restore R10
  383. POPR R2 R15 ; Restore R2
  384. POPR R1 R15 ; Restore R1
  385. RET R15
  386. ;; parse_string function
  387. ;; Receives char* string in R0
  388. ;; R14 is HEAP Pointer
  389. ;; Returns char* in R0
  390. :parse_string
  391. PUSHR R1 R15 ; Protect R1
  392. COPY R1 R0 ; Make a copy of STRING
  393. CALLI R15 @weird ; Check if string is weird
  394. SWAP R0 R1
  395. JUMP.Z R1 @parse_string_regular ; Deal with regular strings
  396. ;; Looks like we have a weirdo
  397. CALLI R15 @collect_weird_string ; Create our weird string
  398. JUMP @parse_string_done ; Simply return what was created
  399. :parse_string_regular
  400. CALLI R15 @collect_regular_string
  401. :parse_string_done
  402. POPR R1 R15 ; Restore R1
  403. RET R15
  404. ;; weird function
  405. ;; Analyze string to determine if it's output would be weird for mescc-tools
  406. ;; Receives char* in R0
  407. ;; Returns BOOL in R0
  408. :weird
  409. PUSHR R1 R15 ; Protect R1
  410. PUSHR R2 R15 ; Protect R2
  411. PUSHR R3 R15 ; Protect R3
  412. PUSHR R4 R15 ; Protect R4
  413. FALSE R2 ; Assume FALSE
  414. ADDUI R3 R0 1 ; STRING = STRING + 1
  415. :weird_iter
  416. JUMP.NZ R2 @weird_done ; Stop if TRUE
  417. LOADU8 R4 R3 0 ; C = STRING[0]
  418. JUMP.Z R4 @weird_done ; Be done at NULL Termination
  419. CMPSKIPI.E R4 92 ; If not '\\'
  420. JUMP @weird_post_escape ; Looks like no escape analysis
  421. ;; Deal with the mess
  422. COPY R0 R3 ; Using STRING
  423. CALLI R15 @escape_lookup ; Get our CHAR
  424. MOVE R4 R0 ; C = ESCAPE_LOOKUP(STRING)
  425. LOADU8 R0 R3 1 ; STRING[1]
  426. CMPSKIPI.NE R0 120 ; if 'x' == STRING[1]
  427. ADDUI R3 R3 2 ; STRING = STRING + 2
  428. ADDUI R3 R3 1 ; STRING = STRING + 1
  429. :weird_post_escape
  430. LOADUI R1 $nice_chars ; using list of nice CHARS
  431. COPY R0 R4 ; using copy of C
  432. CALLI R15 @in_set ; Use in_set
  433. CMPSKIPI.NE R0 0 ; IF TRUE
  434. TRUE R2 ; Return TRUE
  435. ADDUI R3 R3 1 ; STRING = STRING + 1
  436. LOADUI R1 $whitespace_chars ; Check Whitespace Chars
  437. COPY R0 R4 ; Using copy of C
  438. CALLI R15 @in_set ; Use in_set
  439. JUMP.Z R0 @weird_iter ; If False simply loop
  440. LOADU8 R0 R3 0 ; STRING[1]
  441. CMPSKIPI.NE R0 58 ; If ':' == STRING[1]
  442. TRUE R2 ; Flip flag
  443. JUMP @weird_iter ; Keep trying to find an answer
  444. :weird_done
  445. MOVE R0 R2 ; Whatever is in R2 is the answer
  446. POPR R4 R15 ; Restore R4
  447. POPR R3 R15 ; Restore R3
  448. POPR R2 R15 ; Restore R2
  449. POPR R1 R15 ; Restore R1
  450. RET R15
  451. ;; collect_weird_string function
  452. ;; Converts weird string into a form mescc-tools can handle cleanly
  453. ;; Receives char* in R0
  454. ;; R14 is HEAP Pointer and $hex_chars as the table
  455. ;; Returns char* in R0
  456. :collect_weird_string
  457. PUSHR R1 R15 ; Protect R1
  458. PUSHR R2 R15 ; Protect R2
  459. PUSHR R3 R15 ; Protect R3
  460. PUSHR R4 R15 ; Protect R4
  461. LOADUI R4 $hex_chars ; Pointer to TABLE
  462. COPY R3 R14 ; Get HOLD
  463. MOVE R2 R0 ; Put STRING in Place
  464. LOADUI R0 39 ; Prefix with '
  465. PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
  466. :collect_weird_string_iter
  467. ADDUI R2 R2 1 ; STRING = STRING + 1
  468. LOADUI R0 32 ; Insert ' '
  469. PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
  470. COPY R0 R2 ; copy STRING
  471. CALLI R15 @escape_lookup ; Get char value
  472. ANDI R1 R0 0x0F ; Save Bottom out of the way
  473. SR0I R0 4 ; Isolate Top
  474. LOADXU8 R0 R4 R0 ; Using Table
  475. LOADXU8 R1 R4 R1 ; Using Table
  476. PUSH8 R0 R3 ; HOLD[0] = TABLE[(TEMP >> 4)] && HOLD = HOLD + 1
  477. PUSH8 R1 R3 ; HOLD[0] = TABLE[(TEMP & 15)] && HOLD = HOLD + 1
  478. LOADU8 R0 R2 0 ; STRING[0]
  479. JUMP.Z R0 @collect_weird_string_done ; Stop if NULL
  480. CMPSKIPI.E R0 92 ; IF STRING[0] != '\\'
  481. JUMP @collect_weird_string_check ; Deal with iteration
  482. LOADU8 R0 R2 1 ; STRING[1]
  483. CMPSKIPI.NE R0 120 ; If STRING[1] == 'x'
  484. ADDUI R2 R2 2 ; STRING = STRING + 2
  485. ADDUI R2 R2 1 ; STRING = STRING + 1
  486. :collect_weird_string_check
  487. LOADU8 R0 R2 1 ; STRING[1]
  488. JUMP.NZ R0 @collect_weird_string_iter
  489. :collect_weird_string_done
  490. LOADUI R0 32 ; Insert ' '
  491. PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
  492. LOADUI R0 48 ; Insert '0'
  493. PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
  494. PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
  495. LOADUI R0 39 ; Insert '\''
  496. PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
  497. LOADUI R0 10 ; Insert '\n'
  498. PUSH8 R0 R3 ; HOLD[0] = '\n' && HOLD = HOLD + 1
  499. ADDUI R3 R3 1 ; NULL Terminate
  500. SWAP R3 R14 ; CALLOC HOLD
  501. MOVE R0 R3 ; Return HOLD
  502. POPR R4 R15 ; Restore R4
  503. POPR R3 R15 ; Restore R3
  504. POPR R2 R15 ; Restore R2
  505. POPR R1 R15 ; Restore R1
  506. RET R15
  507. ;; hex function
  508. ;; Receives Char in R0
  509. ;; Return Int in R0
  510. :hex
  511. SUBUI R0 R0 48 ; First shift
  512. CMPSKIPI.GE R0 10 ; If 0-9
  513. RET R15 ; Be done
  514. ;; Deal with A-F
  515. ANDI R0 R0 0xDF ; Unset high bit
  516. SUBUI R0 R0 7 ; Shift them down
  517. CMPSKIPI.GE R0 10 ; if between 9 and A
  518. JUMP @hex_error ; Throw an error
  519. CMPSKIPI.L R0 16 ; if > F
  520. JUMP @hex_error ; Throw an error
  521. RET R15
  522. :hex_error
  523. LOADUI R0 $hex_error_message ; Our message
  524. FALSE R1 ; For human
  525. CALLI R15 @file_print ; write it
  526. CALLI R15 @line_error ; More info
  527. HALT
  528. :hex_error_message
  529. "Tried to print non-hex number
  530. "
  531. ;; escape_lookup function
  532. ;; Receives char* in R0
  533. ;; Returns char in R0
  534. :escape_lookup
  535. PUSHR R1 R15 ; Protect R1
  536. PUSHR R2 R15 ; Protect R2
  537. MOVE R1 R0 ; Put C in the right spot
  538. FALSE R2 ; Our flag for done
  539. LOADU8 R0 R1 0 ; c[0]
  540. CMPSKIPI.E R0 92 ; If C[0] != '\\'
  541. JUMP @escape_lookup_none ; Deal with none case
  542. LOADU8 R0 R1 1 ; c[1]
  543. CMPSKIPI.NE R0 120 ; if \x??
  544. JUMP @escape_lookup_hex
  545. ;; Deal with \? escapes
  546. CMPSKIPI.NE R0 110 ; If \n
  547. LOADUI R2 10 ; return \n
  548. CMPSKIPI.NE R0 116 ; If \t
  549. LOADUI R2 9 ; return \t
  550. CMPSKIPI.NE R0 92 ; If \\
  551. LOADUI R2 92 ; return \\
  552. CMPSKIPI.NE R0 39 ; If \'
  553. LOADUI R2 39 ; return \'
  554. CMPSKIPI.NE R0 34 ; If \"
  555. LOADUI R2 34 ; return \"
  556. CMPSKIPI.NE R0 114 ; If \r
  557. LOADUI R2 13 ; return \r
  558. JUMP.Z R2 @escape_lookup_error ; Looks like we got something weird
  559. JUMP @escape_lookup_done ; Otherwise just use our R2
  560. :escape_lookup_none
  561. MOVE R2 R0 ; We just return the char at C[0]
  562. JUMP @escape_lookup_done ; Be done
  563. :escape_lookup_hex
  564. LOADU8 R0 R1 2 ; c[2]
  565. CALLI R15 @hex ; Get first char
  566. SL0I R0 4 ; Shift our first nybble
  567. MOVE R2 R0 ; Protect our top nybble
  568. LOADU8 R0 R1 3 ; c[3]
  569. CALLI R15 @hex ; Get second char
  570. ADD R2 R2 R0 ; \x?? => ? << 4 + ?
  571. :escape_lookup_done
  572. MOVE R0 R2 ; R2 has our answer
  573. POPR R2 R15 ; Restore R2
  574. POPR R1 R15 ; Restore R1
  575. RET R15
  576. :escape_lookup_error
  577. MOVE R2 R0 ; Protect Char that failed
  578. LOADUI R0 $escape_lookup_string0 ; Load message
  579. FALSE R1 ; We want the User to see
  580. CALLI R15 @file_print ; Write it
  581. MOVE R0 R2 ; Our CHAR
  582. FPUTC ; Write it
  583. LOADUI R0 10 ; '\n'
  584. FPUTC ; Write it
  585. CALLI R15 @line_error ; Provide some debug information
  586. HALT
  587. :escape_lookup_string0
  588. "Received invalid escape \\"
  589. ;; collect_regular_string function
  590. ;; Converts C string into a RAW string for mescc-tools
  591. ;; Receives char* in R0
  592. ;; R14 is HEAP Pointer
  593. ;; Returns char* in R0
  594. :collect_regular_string
  595. PUSHR R1 R15 ; Protect R1
  596. PUSHR R2 R15 ; Protect R2
  597. COPY R2 R14 ; MESSAGE
  598. MOVE R1 R0 ; Put STRING in the right place
  599. :collect_regular_string_iter
  600. LOADU8 R0 R1 0 ; STRING[0]
  601. JUMP.Z R0 @collect_regular_string_done ; End at NULL
  602. CMPSKIPI.NE R0 92 ; if STRING[0] == '\\'
  603. JUMP @collect_regular_string_escape ; deal with escapes
  604. ;; Deal with vannilla chars
  605. STORE8 R0 R2 0 ; MESSAGE[0] = STRING[0]
  606. ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
  607. ADDUI R1 R1 1 ; STRING = STRING + 1
  608. JUMP @collect_regular_string_iter ; Loop
  609. :collect_regular_string_escape
  610. COPY R0 R1 ; Prepare for call
  611. CALLI R15 @escape_lookup ; Get what weird char we need
  612. STORE8 R0 R2 0 ; MESSAGE[0] = escape_lookup(string)
  613. ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
  614. LOADU8 R0 R1 1 ; STRING[1]
  615. CMPSKIPI.NE R0 120 ; if \x??
  616. ADDUI R1 R1 2 ; STRING = STRING + 2
  617. ADDUI R1 R1 2 ; STRING = STRING + 2
  618. JUMP @collect_regular_string_iter ; Loop
  619. :collect_regular_string_done
  620. LOADUI R0 34 ; Using "
  621. STORE8 R0 R2 0 ; MESSAGE[0] = '"'
  622. LOADUI R0 10 ; Using '\n'
  623. STORE8 R0 R2 1 ; MESSAGE[1] = "\n"
  624. ADDUI R2 R2 3 ; Add extra NULL padding
  625. SWAP R2 R14 ; Update HEAP
  626. MOVE R0 R2 ; Put MESSAGE in the right Spot
  627. POPR R2 R15 ; Restore R2
  628. POPR R1 R15 ; Restore R1
  629. RET R15
  630. ;; unary_expr_sizeof function
  631. ;; Receives nothing
  632. ;; Returns nothing
  633. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  634. :unary_expr_sizeof
  635. PUSHR R0 R15 ; Protect R0
  636. PUSHR R1 R15 ; Protect R1
  637. PUSHR R2 R15 ; Protect R2
  638. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  639. LOADUI R0 $unary_expr_sizeof_string0 ; Our first error message
  640. LOADUI R1 $open_paren ; Using "("
  641. CALLI R15 @require_match ; Ensure a match
  642. CALLI R15 @type_name ; Get type_name
  643. MOVE R2 R0 ; Protect A
  644. LOADUI R0 $unary_expr_sizeof_string1 ; Our final error message
  645. LOADUI R1 $close_paren ; Using ")"
  646. CALLI R15 @require_match ; Ensure a match
  647. LOADUI R0 $unary_expr_sizeof_string2 ; Our header
  648. CALLI R15 @emit_out ; emit it
  649. LOAD32 R0 R2 4 ; A->SIZE
  650. CALLI R15 @numerate_number ; Convert to string
  651. CALLI R15 @emit_out ; emit it
  652. LOADUI R0 $newline ; Using "\n"
  653. CALLI R15 @emit_out ; emit it
  654. POPR R2 R15 ; Restore R2
  655. POPR R1 R15 ; Restore R1
  656. POPR R0 R15 ; Restore R0
  657. RET R15
  658. :unary_expr_sizeof_string0
  659. "ERROR in unary_expr
  660. Missing (
  661. "
  662. :unary_expr_sizeof_string1
  663. "ERROR in unary_expr
  664. Missing )
  665. "
  666. :unary_expr_sizeof_string2
  667. "LOADUI R0 "
  668. ;; constant_load function
  669. ;; Receives struct token_list* a in R0
  670. ;; Returns nothing
  671. :constant_load
  672. PUSHR R0 R15 ; Protect R0
  673. LOADUI R0 $constant_load_string0 ; Our header
  674. CALLI R15 @emit_out ; emit it
  675. POPR R0 R15 ; Restore R0
  676. LOAD32 R0 R0 16 ; A->ARGUMENTS
  677. LOAD32 R0 R0 8 ; A->ARGUMENTS->S
  678. CALLI R15 @emit_out ; emit it
  679. LOADUI R0 $newline ; Using "\n"
  680. CALLI R15 @emit_out ; emit it
  681. RET R15
  682. :constant_load_string0
  683. "LOADI R0 "
  684. ;; variable_load function
  685. ;; Receives struct token_list* a in R0
  686. ;; and struct token_list* current_target in R8
  687. ;; Returns Nothing
  688. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  689. :variable_load
  690. PUSHR R1 R15 ; Protect R1
  691. PUSHR R2 R15 ; Protect R2
  692. MOVE R2 R0 ; Protect A
  693. ;; Check if function call
  694. LOADUI R0 $type_function_name ; Using "FUNCTION"
  695. LOAD32 R1 R2 12 ; A->TYPE
  696. LOAD32 R1 R1 24 ; A->TYPE->NAME
  697. CALLI R15 @match ; IF "FUNCTION" == A->TYPE->NAME
  698. JUMP.Z R0 @variable_load_regular ; Nope
  699. LOADUI R0 $open_paren ; Using "("
  700. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  701. CALLI R15 @match ; IF "(" == GLOBAL_TOKEN->S
  702. JUMP.Z R0 @variable_load_regular ; Nope
  703. ;; Deal with function call
  704. LOAD32 R0 R2 16 ; A->DEPTH
  705. CALLI R15 @numerate_number ; Convert to string
  706. TRUE R1 ; Passing TRUE
  707. CALLI R15 @function_call ; DO IT
  708. JUMP @variable_load_done ; Be done
  709. :variable_load_regular
  710. LOAD32 R8 R2 12 ; CURRENT_TARGET = A->TYPE
  711. LOADUI R0 $variable_load_string0 ; Our prefix
  712. CALLI R15 @emit_out ; emit it
  713. LOAD32 R0 R2 16 ; A->DEPTH
  714. CALLI R15 @numerate_number ; Convert to string
  715. CALLI R15 @emit_out ; emit it
  716. LOADUI R0 $newline ; Using "\n"
  717. CALLI R15 @emit_out ; emit it
  718. ;; check for special case 1
  719. LOADUI R0 $equal ; Using "="
  720. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  721. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  722. JUMP.NZ R0 @variable_load_done ; Be done
  723. ;; deal with the general case
  724. LOADUI R0 $variable_load_string1 ; Our postfix
  725. CALLI R15 @emit_out ; emit it
  726. :variable_load_done
  727. POPR R2 R15 ; Restore R2
  728. POPR R1 R15 ; Restore R1
  729. RET R15
  730. :variable_load_string0
  731. "ADDI R0 R14 "
  732. :variable_load_string1
  733. "LOAD R0 R0 0
  734. "
  735. ;; function_load function
  736. ;; Receives struct token_list* a in R0
  737. ;; Returns nothing
  738. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  739. :function_load
  740. PUSHR R1 R15 ; Protect R1
  741. LOAD32 R0 R0 8 ; A->S
  742. PUSHR R0 R15 ; Protect A->S
  743. LOADUI R0 $open_paren ; Using "("
  744. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  745. CALLI R15 @match ; If GLOBAL_TOKEN->S == "("
  746. JUMP.Z R0 @function_load_regular ; If not do the simple thing
  747. ;; Deal iwth function call
  748. POPR R0 R15 ; Restore A->S
  749. FALSE R1 ; FALSE
  750. CALLI R15 @function_call ; Do the function call
  751. JUMP @function_load_done ; Clean up
  752. :function_load_regular
  753. LOADUI R0 $function_load_string0 ; Using our header string
  754. CALLI R15 @emit_out ; emit it
  755. POPR R0 R15 ; Restore A->S
  756. CALLI R15 @emit_out ; emit it
  757. LOADUI R0 $newline ; Using "\n"
  758. CALLI R15 @emit_out ; emit it
  759. :function_load_done
  760. POPR R1 R15 ; Restore R1
  761. RET R15
  762. :function_load_string0
  763. "LOADR R0 4
  764. JUMP 4
  765. &FUNCTION_"
  766. ;; global_load function
  767. ;; Receives struct token_list* a in R0
  768. ;; and struct token_list* current_target in R8
  769. ;; Returns nothing
  770. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  771. :global_load
  772. PUSHR R0 R15 ; Protect A
  773. LOAD32 R8 R0 12 ; CURRENT_TARGET = A->TYPE
  774. LOADUI R0 $global_load_string0 ; Our header string
  775. CALLI R15 @emit_out ; emit it
  776. POPR R0 R15 ; Restore A
  777. LOAD32 R0 R0 8 ; A->S
  778. CALLI R15 @emit_out ; emit it
  779. LOADUI R0 $newline ; Using "\n"
  780. CALLI R15 @emit_out ; emit it
  781. PUSHR R1 R15 ; Protect R1
  782. LOADUI R0 $equal ; Using "="
  783. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  784. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  785. JUMP.NZ R0 @global_load_done ; Skip the following
  786. ;; Deal with non-assignment
  787. LOADUI R0 $global_load_string1 ; Our footer string
  788. CALLI R15 @emit_out ; emit it
  789. :global_load_done
  790. POPR R1 R15 ; Restore R1
  791. RET R15
  792. :global_load_string0
  793. "LOADR R0 4
  794. JUMP 4
  795. &GLOBAL_"
  796. :global_load_string1
  797. "LOAD R0 R0 0
  798. "
  799. ;; primary_expr_failure function
  800. ;; Fails hard and fast
  801. ;; Receives nothing
  802. ;; HALTs and will trash registers
  803. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  804. :primary_expr_failure
  805. LOADUI R0 $primary_expr_failure_string0 ; Our first string
  806. FALSE R1 ; Display to User
  807. CALLI R15 @file_print ; Print it
  808. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  809. CALLI R15 @file_print ; Print it
  810. LOADUI R0 $primary_expr_failure_string1 ; Our last string
  811. CALLI R15 @file_print ; Print it
  812. CALLI R15 @line_error ; Make it a line error message too
  813. HALT
  814. :primary_expr_failure_string0
  815. "Received "
  816. :primary_expr_failure_string1
  817. " in primary_expr
  818. "
  819. ;; primary_expr_string function
  820. ;; Receives struct token_list* global_token in R13,
  821. ;; struct token_list* out in R12,
  822. ;; struct token_list* string_list in R11
  823. ;; struct token_list* global_list in R10
  824. ;; and struct token_list* FUNC in R9
  825. ;; and struct token_list* current_target in R8
  826. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  827. ;; Returns the token_lists modified
  828. :primary_expr_string
  829. PUSHR R0 R15 ; Protect R0
  830. PUSHR R1 R15 ; Protect R1
  831. PUSHR R2 R15 ; Protect R2
  832. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  833. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  834. STORER32 R1 @current_count ; Update CURRENT_COUNT
  835. CALLI R15 @numerate_number ; Convert to string
  836. MOVE R2 R0 ; Put string in safe place
  837. LOADUI R0 $primary_expr_string_string0 ; Our string prefix
  838. CALLI R15 @emit_out ; emit it
  839. LOAD32 R0 R9 8 ; FUNCTION->S
  840. COPY R1 R2 ; NUMBER_STRING
  841. CALLI R15 @uniqueID_out ; Make it unique
  842. ;; The target
  843. LOADUI R0 $primary_expr_string_string1
  844. COPY R1 R11 ; Using STRINGS_LIST
  845. CALLI R15 @emit ; emit it
  846. MOVE R1 R0 ; Put STRINGS_LIST in correct place
  847. LOAD32 R0 R9 8 ; Using FUNCTION->S
  848. CALLI R15 @uniqueID ; Make it unique
  849. MOVE R11 R0 ; Update STRINGS_LIST
  850. ;; Parse the string
  851. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  852. CALLI R15 @parse_string ; Parse it
  853. COPY R1 R11 ; Using STRINGS_LIST
  854. CALLI R15 @emit ; emit it
  855. MOVE R11 R0 ; Update STRINGS_LIST
  856. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  857. POPR R2 R15 ; Restore R2
  858. POPR R1 R15 ; Restore R1
  859. POPR R0 R15 ; Restore R0
  860. RET R15
  861. :primary_expr_string_string0
  862. "LOADR R0 4
  863. JUMP 4
  864. &STRING_"
  865. :primary_expr_string_string1
  866. ":STRING_"
  867. ;; primary_expr_char function
  868. ;; Receives struct token_list* global_token in R13,
  869. ;; struct token_list* out in R12,
  870. ;; struct token_list* string_list in R11
  871. ;; struct token_list* global_list in R10
  872. ;; and struct token_list* FUNC in R9
  873. ;; and struct token_list* current_target in R8
  874. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  875. ;; Returns the token_lists modified
  876. :primary_expr_char
  877. PUSHR R0 R15 ; Protect R0
  878. LOADUI R0 $primary_expr_char_string0 ; Using our header string
  879. CALLI R15 @emit_out ; emit it
  880. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  881. ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
  882. CALLI R15 @escape_lookup ; escape_lookup value
  883. CALLI R15 @numerate_number ; Make it a string
  884. CALLI R15 @emit_out ; emit it
  885. LOADUI R0 $newline ; Using "\n"
  886. CALLI R15 @emit_out ; emit it
  887. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  888. POPR R0 R15 ; Restore R0
  889. RET R15
  890. :primary_expr_char_string0
  891. "LOADI R0 "
  892. ;; primary_expr_number function
  893. ;; struct token_list* out in R12,
  894. ;; struct token_list* string_list in R11
  895. ;; struct token_list* global_list in R10
  896. ;; and struct token_list* FUNC in R9
  897. ;; and struct token_list* current_target in R8
  898. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  899. ;; Returns the token_lists modified
  900. :primary_expr_number
  901. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  902. CALLI R15 @numerate_string ; Convert it to an int
  903. CMPSKIPI.L R0 32767 ; If 32767 > size
  904. JUMP @primary_expr_number_ugly ; Do it the ugly way
  905. CMPSKIPI.G R0 -32767 ; If -32767 < size
  906. JUMP @primary_expr_number_ugly ; Do it the ugly way
  907. LOADUI R0 $primary_expr_number_string0 ; Our header
  908. CALLI R15 @emit_out ; emit it
  909. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  910. CALLI R15 @emit_out ; emit it
  911. JUMP @primary_expr_number_done ; Be done
  912. :primary_expr_number_ugly
  913. PUSHR R1 R15 ; Protect R1
  914. PUSHR R0 R15 ; Protect the size
  915. LOADUI R0 $primary_expr_number_string1 ; Our ugly header
  916. CALLI R15 @emit_out ; emit it
  917. POPR R0 R15 ; Get the size back
  918. COPY R1 R14 ; Get pointer
  919. CALLI R15 @hex32 ; Convert size to string
  920. ADDUI R14 R14 1 ; Extra pad for paranoia
  921. MOVE R0 R1 ; Put string in right place
  922. CALLI R15 @emit_out ; emit it
  923. LOADUI R0 $primary_expr_number_string2 ; Our ugly trailer
  924. CALLI R15 @emit_out ; emit it
  925. POPR R1 R15 ; Restore R1
  926. :primary_expr_number_done
  927. LOADUI R0 $newline ; Using "\n"
  928. CALLI R15 @emit_out ; emit it
  929. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  930. RET R15
  931. :primary_expr_number_string0
  932. "LOADI R0 "
  933. :primary_expr_number_string1
  934. "LOADR R0 4
  935. JUMP 4
  936. '"
  937. :primary_expr_number_string2
  938. "'"
  939. ;; hex32 functionality
  940. ;; Accepts 32bit value in R0
  941. ;; Require R14 to be the heap pointer
  942. ;; WILL ALTER R14 !
  943. ;; Returns to whatever called it
  944. :hex32
  945. PUSHR R0 R15
  946. SR0I R0 16 ; Do high word first
  947. CALLI R15 @hex16
  948. POPR R0 R15
  949. :hex16
  950. PUSHR R0 R15
  951. SR0I R0 8 ; Do high byte first
  952. CALLI R15 @hex8
  953. POPR R0 R15
  954. :hex8
  955. PUSHR R0 R15
  956. SR0I R0 4 ; Do high nybble first
  957. CALLI R15 @hex4
  958. POPR R0 R15
  959. :hex4
  960. ANDI R0 R0 0xF ; isolate nybble
  961. ADDUI R0 R0 48 ; convert to ascii
  962. CMPSKIPI.LE R0 57 ; If nybble was greater than '9'
  963. ADDUI R0 R0 7 ; Shift it into 'A' range of ascii
  964. STORE8 R0 R14 0 ; Store Hex Char
  965. ADDUI R14 R14 1 ; Increment address pointer
  966. RET R15 ; Get next nybble or return if done
  967. ;; primary_expr_variable function
  968. ;; struct token_list* out in R12,
  969. ;; struct token_list* string_list in R11
  970. ;; struct token_list* global_list in R10
  971. ;; and struct token_list* FUNC in R9
  972. ;; and struct token_list* current_target in R8
  973. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  974. ;; Returns the token_lists modified
  975. :primary_expr_variable
  976. PUSHR R0 R15 ; Protect R0
  977. PUSHR R1 R15 ; Protect R1
  978. PUSHR R2 R15 ; Protect R2
  979. LOAD32 R2 R13 8 ; S = GLOBAL_TOKEN->S
  980. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  981. COPY R0 R2 ; Using S
  982. LOADR32 R1 @global_constant_list
  983. CALLI R15 @sym_lookup ; Lookup S in CONSTANTS
  984. JUMP.Z R0 @primary_expr_variable_locals ; try Locals
  985. ;; Deal with Constants
  986. CALLI R15 @constant_load ; A is in R0 already
  987. JUMP @primary_expr_variable_done ; Moving on
  988. :primary_expr_variable_locals
  989. COPY R0 R2 ; Using S
  990. LOAD32 R1 R9 4 ; Using FUNCTION->LOCALS
  991. CALLI R15 @sym_lookup ; Lookup S in Locals
  992. JUMP.Z R0 @primary_expr_variable_arguments ; try arguments
  993. ;; Deal with Locals
  994. CALLI R15 @variable_load ; A is in R0 already
  995. JUMP @primary_expr_variable_done ; Moving on
  996. :primary_expr_variable_arguments
  997. COPY R0 R2 ; Using S
  998. LOAD32 R1 R9 16 ; Using FUNCTION->ARGUMENTS
  999. CALLI R15 @sym_lookup ; Lookup S in arguments
  1000. JUMP.Z R0 @primary_expr_variable_function ; try Functions
  1001. ;; Deal with argument
  1002. CALLI R15 @variable_load ; A is in R0 already
  1003. JUMP @primary_expr_variable_done ; Moving on
  1004. :primary_expr_variable_function
  1005. COPY R0 R2 ; Using S
  1006. LOADR32 R1 @global_function_list ; Get current GLOBAL_FUNCTION_LIST
  1007. CALLI R15 @sym_lookup ; Lookup S in GLOBAL_FUNCTION_LIST
  1008. JUMP.Z R0 @primary_expr_variable_global ; try Globals
  1009. ;; Deal with function
  1010. CALLI R15 @function_load ; Dothe work
  1011. JUMP @primary_expr_variable_done ; Moving on
  1012. :primary_expr_variable_global
  1013. COPY R0 R2 ; Using S
  1014. LOADR32 R1 @global_symbol_list ; Get current GLOBAL_SYMBOL_LIST
  1015. CALLI R15 @sym_lookup ; Lookup S in GLOBAL_SYMBOL_LIST
  1016. JUMP.Z R0 @primary_expr_variable_failure ; Looks like it isn't anything we know
  1017. ;; Deal with a global
  1018. CALLI R15 @global_load
  1019. :primary_expr_variable_done
  1020. POPR R2 R15 ; Restore R2
  1021. POPR R1 R15 ; Restore R1
  1022. POPR R0 R15 ; Restore R0
  1023. RET R15
  1024. :primary_expr_variable_failure
  1025. MOVE R0 R2 ; Using S
  1026. FALSE R1 ; We want the user to see
  1027. CALLI R15 @file_print ; Print it
  1028. LOADUI R0 $primary_expr_variable_string0 ; Body
  1029. CALLI R15 @file_print ; Print it
  1030. CALLI R15 @line_error ; Provide useful error info
  1031. HALT
  1032. :primary_expr_variable_string0
  1033. " is not a defined symbol
  1034. "
  1035. ;; promote_type function
  1036. ;; Receives struct type* in R0 and struct type* in R1
  1037. ;; Returns first match struct type* in R0
  1038. :promote_type
  1039. JUMP.Z R1 @promote_type_abort0 ; If B is NULL just abort
  1040. PUSHR R1 R15 ; Protect R1
  1041. SWAP R0 R1 ; Give A a try
  1042. JUMP.Z R1 @promote_type_abort1 ; A is NULL just short abort
  1043. ;; Looks like we have a bunch of work to do
  1044. PUSHR R2 R15 ; Protect R2
  1045. PUSHR R3 R15 ; Protect R3
  1046. PUSHR R4 R15 ; Protect R4
  1047. PUSHR R5 R15 ; Protect R5
  1048. MOVE R5 R1 ; Put A in the right spot
  1049. MOVE R4 R0 ; Put B in the right spot
  1050. LOADR32 R3 @global_types ; I = GLOBAL_TYPES
  1051. :promote_type_iter
  1052. LOAD32 R1 R3 24 ; I->NAME
  1053. LOAD32 R0 R5 24 ; A->NAME
  1054. CMPJUMPI.E R0 R1 @promote_type_done ; break
  1055. LOAD32 R0 R4 24 ; B->NAME
  1056. CMPJUMPI.E R0 R1 @promote_type_done ; break
  1057. LOAD32 R1 R3 12 ; I->INDIRECT
  1058. LOAD32 R1 R1 24 ; I->INDIRECT->NAME
  1059. LOAD32 R0 R5 24 ; A->NAME
  1060. CMPJUMPI.E R0 R1 @promote_type_done ; break
  1061. LOAD32 R0 R4 24 ; B->NAME
  1062. CMPJUMPI.E R0 R1 @promote_type_done ; break
  1063. LOAD32 R3 R3 0 ; I = I->NEXT
  1064. JUMP.NZ R3 @promote_type_iter ; Loop if not NULL
  1065. :promote_type_done
  1066. MOVE R0 R3 ; Return I
  1067. POPR R5 R15 ; Restore R5
  1068. POPR R4 R15 ; Restore R4
  1069. POPR R3 R15 ; Restore R3
  1070. POPR R2 R15 ; Restore R2
  1071. :promote_type_abort1
  1072. POPR R1 R15 ; Restore R1
  1073. :promote_type_abort0
  1074. RET R15
  1075. ;; common_recursion function
  1076. ;; Receives FUNCTION* in R0
  1077. ;; struct token_list* out in R12,
  1078. ;; struct token_list* string_list in R11
  1079. ;; struct token_list* global_list in R10
  1080. ;; and struct token_list* FUNC in R9
  1081. ;; and struct token_list* current_target in R8
  1082. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1083. ;; Returns the token_lists modified
  1084. :common_recursion
  1085. PUSHR R0 R15 ; Protect R0
  1086. PUSHR R1 R15 ; Protect R1
  1087. PUSHR R2 R15 ; Protect R2
  1088. MOVE R2 R0 ; Protect F
  1089. COPY R1 R8 ; LAST_TYPE = CURRENT_TARGET
  1090. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1091. LOADUI R0 $common_recursion_string0 ; Header string
  1092. CALLI R15 @emit_out ; Our header
  1093. CALL R2 R15 ; CALL F()
  1094. COPY R0 R8 ; Using CURRENT_TARGET
  1095. CALLI R15 @promote_type ; Promote type
  1096. MOVE R8 R0 ; update CURRENT_TARGET
  1097. LOADUI R0 $common_recursion_string1 ; Footer string
  1098. CALLI R15 @emit_out ; Our footer
  1099. POPR R2 R15 ; Restore R2
  1100. POPR R1 R15 ; Restore R1
  1101. POPR R0 R15 ; Restore R0
  1102. RET R15
  1103. :common_recursion_string0
  1104. "PUSHR R0 R15 #_common_recursion
  1105. "
  1106. :common_recursion_string1
  1107. "POPR R1 R15 # _common_recursion
  1108. "
  1109. ;; general_recursion function
  1110. ;; Receives FUNCTION F in R0, char* s in R1, char* name in R2
  1111. ;; and FUNCTION ITERATE in R3
  1112. ;; struct token_list* out in R12,
  1113. ;; struct token_list* string_list in R11
  1114. ;; struct token_list* global_list in R10
  1115. ;; and struct token_list* FUNC in R9
  1116. ;; and struct token_list* current_target in R8
  1117. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1118. ;; Returns nothing
  1119. :general_recursion
  1120. PUSHR R0 R15 ; Protect R0
  1121. PUSHR R1 R15 ; Protect S
  1122. PUSHR R0 R15 ; Protect F
  1123. COPY R0 R2 ; Using NAME
  1124. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1125. CALLI R15 @match ; IF GLOBAL_TOKEN->S == NAME
  1126. JUMP.Z R0 @general_recursion_done
  1127. ;; deal with case of match
  1128. POPR R0 R15 ; Restore F
  1129. CALLI R15 @common_recursion ; Recurse
  1130. POPR R1 R15 ; Restore S
  1131. COPY R0 R1 ; Put S in correct place
  1132. CALLI R15 @emit_out ; emit it
  1133. CALL R3 R15 ; CALL ITERATE()
  1134. POPR R0 R15 ; Restore R0
  1135. RET R15 ; Don't double pop
  1136. :general_recursion_done
  1137. POPR R0 R15 ; Restore F
  1138. POPR R1 R15 ; Restore S
  1139. POPR R0 R15 ; Restore R0
  1140. RET R15
  1141. ;; ceil_log2 function
  1142. ;; Receives INT A in R0
  1143. ;; Returns LOG2(A) in R0
  1144. :ceil_log2
  1145. PUSHR R1 R15 ; Protect R1
  1146. PUSHR R2 R15 ; Protect R2
  1147. FALSE R2 ; RESULT = 0
  1148. SUBI R1 R0 1 ; A - 1
  1149. AND R1 R1 R0 ; A & (A - 1)
  1150. CMPSKIPI.NE R1 0 ; IF (A & (A - 1)) == 0
  1151. LOADI R2 -1 ; RESULT = -1
  1152. :ceil_log2_iter
  1153. JUMP.Z R0 @ceil_log2_done ; IF A > 0
  1154. ADDI R2 R2 1 ; RESULT = RESULT + 1
  1155. SARI R0 1 ; A = A >> 1
  1156. JUMP @ceil_log2_iter ; Loop
  1157. :ceil_log2_done
  1158. MOVE R0 R2 ; Use RESULT
  1159. POPR R2 R15 ; Restore R2
  1160. POPR R1 R15 ; Restore R1
  1161. RET R15
  1162. ;; postfix_expr_arrow function
  1163. ;; Receives nothing
  1164. ;; struct token_list* out in R12,
  1165. ;; struct token_list* string_list in R11
  1166. ;; struct token_list* global_list in R10
  1167. ;; and struct token_list* FUNC in R9
  1168. ;; and struct token_list* current_target in R8
  1169. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1170. ;; Returns the token_lists modified
  1171. :postfix_expr_arrow
  1172. PUSHR R0 R15 ; Protect R0
  1173. PUSHR R1 R15 ; Protect R1
  1174. PUSHR R2 R15 ; Protect R2
  1175. LOADUI R0 $postfix_expr_arrow_string0 ; Our header string
  1176. CALLI R15 @emit_out ; Emit it
  1177. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1178. COPY R0 R8 ; Passing CURRENT_TARGET
  1179. LOAD32 R1 R13 8 ; Using GLOBAL_TOKEN->S
  1180. CALLI R15 @lookup_member ; Look it up
  1181. LOAD32 R2 R0 4 ; Protect I->SIZE
  1182. LOAD32 R8 R0 20 ; CURRENT_TARGET = I->TYPE
  1183. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1184. LOAD32 R1 R0 8 ; I->OFFSET
  1185. JUMP.Z R1 @postfix_expr_arrow_offset ; If no offset needed skip the work
  1186. ;; Deal with non-zero offsets
  1187. LOADUI R0 $postfix_expr_arrow_string1 ; Our first prefix
  1188. CALLI R15 @emit_out ; Emit it
  1189. LOADUI R0 $postfix_expr_arrow_string2 ; Our second prefix
  1190. CALLI R15 @emit_out ; Emit it
  1191. MOVE R0 R1 ; Put I->OFFSET in the right place
  1192. CALLI R15 @numerate_number ; Convert to string
  1193. CALLI R15 @emit_out ; Emit it
  1194. LOADUI R0 $postfix_expr_arrow_string3 ; Our postfix
  1195. CALLI R15 @emit_out ; Emit it
  1196. :postfix_expr_arrow_offset
  1197. LOADUI R0 $equal ; Using "="
  1198. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1199. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1200. JUMP.NZ R0 @postfix_expr_arrow_done
  1201. LOADUI R0 4 ; Compare against 4
  1202. CMPJUMPI.L R0 R2 @postfix_expr_arrow_done
  1203. ;; Deal with special case
  1204. LOADUI R0 $postfix_expr_arrow_string4 ; Our final string
  1205. CALLI R15 @emit_out ; Emit it
  1206. :postfix_expr_arrow_done
  1207. POPR R2 R15 ; Restore R2
  1208. POPR R1 R15 ; Restore R1
  1209. POPR R0 R15 ; Restore R0
  1210. RET R15
  1211. :postfix_expr_arrow_string0
  1212. "# looking up offset
  1213. "
  1214. :postfix_expr_arrow_string1
  1215. "# -> offset calculation
  1216. "
  1217. :postfix_expr_arrow_string2
  1218. "ADDUI R0 R0 "
  1219. :postfix_expr_arrow_string3
  1220. "
  1221. "
  1222. :postfix_expr_arrow_string4
  1223. "LOAD R0 R0 0
  1224. "
  1225. ;; postfix_expr_array function
  1226. ;; Receives nothing
  1227. ;; struct token_list* out in R12,
  1228. ;; struct token_list* string_list in R11
  1229. ;; struct token_list* global_list in R10
  1230. ;; and struct token_list* FUNC in R9
  1231. ;; and struct token_list* current_target in R8
  1232. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1233. ;; Returns the token_lists modified
  1234. :postfix_expr_array
  1235. PUSHR R0 R15 ; Protect R0
  1236. PUSHR R1 R15 ; Protect R1
  1237. PUSHR R2 R15 ; Protect R2
  1238. COPY R2 R8 ; ARRAY = CURRENT_TARGET
  1239. LOADUI R0 $expression ; Using EXPRESSION
  1240. CALLI R15 @common_recursion ; Recurse
  1241. MOVE R8 R2 ; CURRENT_TARGET = ARRAY
  1242. LOADUI R2 $postfix_expr_array_string0 ; ASSIGN = load integer
  1243. LOADUI R0 $type_char_indirect_name ; Using "char*"
  1244. LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
  1245. CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
  1246. CMPSKIPI.E R0 0 ; deal with Byte
  1247. LOADUI R2 $postfix_expr_array_string1 ; ASSIGN = load byte
  1248. JUMP.NZ R0 @postfix_expr_array_byte ; Skip if Byte
  1249. ;; Deal with larger than byte
  1250. LOADUI R0 $postfix_expr_array_string2 ; Our shift
  1251. CALLI R15 @emit_out ; emit it
  1252. LOAD32 R0 R8 12 ; CURRENT_TARGET->INDIRECT
  1253. LOAD32 R0 R0 4 ; CURRENT_TARGET->INDIRECT->SIZE
  1254. CALLI R15 @ceil_log2 ; LOG2(CURRENT_TARGET->INDIRECT->SIZE)
  1255. CALLI R15 @numerate_number ; Convert to string
  1256. CALLI R15 @emit_out ; emit it
  1257. LOADUI R0 $newline ; Using "\n"
  1258. CALLI R15 @emit_out ; emit it
  1259. :postfix_expr_array_byte
  1260. LOADUI R0 $postfix_expr_array_string3 ; Add the offset
  1261. CALLI R15 @emit_out ; emit it
  1262. LOADUI R0 $postfix_expr_array_string4 ; Our final error message
  1263. LOADUI R1 $close_bracket ; Using "]"
  1264. CALLI R15 @require_match ; Ensure match
  1265. LOADUI R0 $equal ; Using "="
  1266. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1267. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1268. CMPSKIPI.E R0 0 ; If match
  1269. LOADUI R2 $postfix_expr_array_string5 ; empty string
  1270. MOVE R0 R2 ; What ever string survived
  1271. CALLI R15 @emit_out ; emit it
  1272. POPR R2 R15 ; Restore R2
  1273. POPR R1 R15 ; Restore R1
  1274. POPR R0 R15 ; Restore R0
  1275. RET R15
  1276. :postfix_expr_array_string0
  1277. "LOAD R0 R0 0
  1278. "
  1279. :postfix_expr_array_string1
  1280. "LOAD8 R0 R0 0
  1281. "
  1282. :postfix_expr_array_string2
  1283. "SALI R0 "
  1284. :postfix_expr_array_string3
  1285. "ADD R0 R0 R1
  1286. "
  1287. :postfix_expr_array_string4
  1288. "ERROR in postfix_expr
  1289. Missing ]
  1290. "
  1291. :postfix_expr_array_string5
  1292. ""
  1293. ;; postfix_expr_stub function
  1294. ;; Receives nothing
  1295. ;; struct token_list* out in R12,
  1296. ;; struct token_list* string_list in R11
  1297. ;; struct token_list* global_list in R10
  1298. ;; and struct token_list* FUNC in R9
  1299. ;; and struct token_list* current_target in R8
  1300. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1301. ;; Returns the token_lists modified
  1302. :postfix_expr_stub
  1303. PUSHR R0 R15 ; Protect R0
  1304. PUSHR R1 R15 ; Protect R1
  1305. LOADUI R0 $open_bracket ; Using "["
  1306. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1307. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
  1308. JUMP.Z R0 @postfix_expr_stub_next
  1309. ;; Deal with "[" case
  1310. CALLI R15 @postfix_expr_array ; process
  1311. CALLI R15 @postfix_expr_stub ; recurse
  1312. :postfix_expr_stub_next
  1313. LOADUI R0 $arrow_string ; Using "->"
  1314. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1315. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "->"
  1316. JUMP.Z R0 @postfix_expr_stub_done ; clean up
  1317. ;; Deal with "->" case
  1318. CALLI R15 @postfix_expr_arrow ; Process
  1319. CALLI R15 @postfix_expr_stub ; recurse
  1320. :postfix_expr_stub_done
  1321. POPR R1 R15 ; Restore R1
  1322. POPR R0 R15 ; Restore R0
  1323. RET R15
  1324. ;; postfix_expr function
  1325. ;; struct token_list* out in R12,
  1326. ;; struct token_list* string_list in R11
  1327. ;; struct token_list* global_list in R10
  1328. ;; and struct token_list* FUNC in R9
  1329. ;; and struct token_list* current_target in R8
  1330. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1331. ;; Returns the token_lists modified
  1332. :postfix_expr
  1333. CALLI R15 @primary_expr ; Walk up the tree
  1334. CALLI R15 @postfix_expr_stub ; Deal with nodes on this level
  1335. RET R15
  1336. ;; additive_expr_stub function
  1337. ;; receives nothing
  1338. ;; returns nothing
  1339. ;; Updates struct token_list*
  1340. :additive_expr_stub
  1341. PUSHR R0 R15 ; Protect R0
  1342. PUSHR R1 R15 ; Protect R1
  1343. PUSHR R2 R15 ; Protect R2
  1344. PUSHR R3 R15 ; Protect R3
  1345. ;; Fixed pieces
  1346. LOADUI R0 $postfix_expr ; Set First argument
  1347. LOADUI R3 $additive_expr_stub
  1348. ;; The + bit
  1349. LOADUI R1 $additive_expr_stub_string0 ; Our first operation
  1350. LOADUI R2 $plus_string ; Using "+"
  1351. CALLI R15 @general_recursion
  1352. ;; The - bit
  1353. LOADUI R1 $additive_expr_stub_string1 ; Our second operation
  1354. LOADUI R2 $minus_string ; Using "-"
  1355. CALLI R15 @general_recursion
  1356. ;; The * bit
  1357. LOADUI R1 $additive_expr_stub_string2 ; Our third operation
  1358. LOADUI R2 $multiply_string ; Using "*"
  1359. CALLI R15 @general_recursion
  1360. ;; The / bit
  1361. LOADUI R1 $additive_expr_stub_string3 ; Our fourth operation
  1362. LOADUI R2 $divide_string ; Using "/"
  1363. CALLI R15 @general_recursion
  1364. ;; The % bit
  1365. LOADUI R1 $additive_expr_stub_string4 ; Our fifth operation
  1366. LOADUI R2 $modulus_string ; Using "%"
  1367. CALLI R15 @general_recursion
  1368. ;; The << bit
  1369. LOADUI R1 $additive_expr_stub_string5 ; Our sixth operation
  1370. LOADUI R2 $left_shift_string ; Using "<<"
  1371. CALLI R15 @general_recursion
  1372. ;; The >> bit
  1373. LOADUI R1 $additive_expr_stub_string6 ; Our final operation
  1374. LOADUI R2 $right_shift_string ; Using ">>"
  1375. CALLI R15 @general_recursion
  1376. POPR R3 R15 ; Restore R3
  1377. POPR R2 R15 ; Restore R2
  1378. POPR R1 R15 ; Restore R1
  1379. POPR R0 R15 ; Restore R0
  1380. RET R15
  1381. :additive_expr_stub_string0
  1382. "ADD R0 R1 R0
  1383. "
  1384. :additive_expr_stub_string1
  1385. "SUB R0 R1 R0
  1386. "
  1387. :additive_expr_stub_string2
  1388. "MUL R0 R1 R0
  1389. "
  1390. :additive_expr_stub_string3
  1391. "DIVU R0 R1 R0
  1392. "
  1393. :additive_expr_stub_string4
  1394. "MODU R0 R1 R0
  1395. "
  1396. :additive_expr_stub_string5
  1397. "SAL R0 R1 R0
  1398. "
  1399. :additive_expr_stub_string6
  1400. "SAR R0 R1 R0
  1401. "
  1402. ;; additive_expr function
  1403. ;; Receives struct token_list* global_token in R13,
  1404. ;; struct token_list* out in R12,
  1405. ;; struct token_list* string_list in R11
  1406. ;; struct token_list* global_list in R10
  1407. ;; and struct token_list* FUNC in R9
  1408. ;; and struct token_list* current_target in R8
  1409. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1410. ;; Returns the token_lists modified
  1411. :additive_expr
  1412. CALLI R15 @postfix_expr ; Walk up the tree
  1413. CALLI R15 @additive_expr_stub ; Deal with nodes at this level
  1414. RET R15
  1415. ;; relational_expr_stub function
  1416. ;; receives nothing
  1417. ;; returns nothing
  1418. ;; Updates struct token_list*
  1419. :relational_expr_stub
  1420. PUSHR R0 R15 ; Protect R0
  1421. PUSHR R1 R15 ; Protect R1
  1422. PUSHR R2 R15 ; Protect R2
  1423. PUSHR R3 R15 ; Protect R3
  1424. ;; Fixed pieces
  1425. LOADUI R0 $additive_expr ; Set First argument
  1426. LOADUI R3 $relational_expr_stub
  1427. ;; The < bit
  1428. LOADUI R1 $relational_expr_stub_string0 ; Our first operation
  1429. LOADUI R2 $less_than_string ; Using "<"
  1430. CALLI R15 @general_recursion
  1431. ;; The <= bit
  1432. LOADUI R1 $relational_expr_stub_string1 ; Our second operation
  1433. LOADUI R2 $less_than_equal_string ; Using "<="
  1434. CALLI R15 @general_recursion
  1435. ;; The >= bit
  1436. LOADUI R1 $relational_expr_stub_string2 ; Our third operation
  1437. LOADUI R2 $greater_than_equal_string ; Using ">="
  1438. CALLI R15 @general_recursion
  1439. ;; The > bit
  1440. LOADUI R1 $relational_expr_stub_string3 ; Our fourth operation
  1441. LOADUI R2 $greater_than_string ; Using ">"
  1442. CALLI R15 @general_recursion
  1443. ;; The == bit
  1444. LOADUI R1 $relational_expr_stub_string4 ; Our fifth operation
  1445. LOADUI R2 $equal_to_string ; Using "=="
  1446. CALLI R15 @general_recursion
  1447. ;; The != bit
  1448. LOADUI R1 $relational_expr_stub_string5 ; Our final operation
  1449. LOADUI R2 $not_equal_string ; Using "!="
  1450. CALLI R15 @general_recursion
  1451. POPR R3 R15 ; Restore R3
  1452. POPR R2 R15 ; Restore R2
  1453. POPR R1 R15 ; Restore R1
  1454. POPR R0 R15 ; Restore R0
  1455. RET R15
  1456. :relational_expr_stub_string0
  1457. "CMPSKIP.GE R1 R0
  1458. LOADUI R2 1
  1459. MOVE R0 R2
  1460. "
  1461. :relational_expr_stub_string1
  1462. "CMPSKIP.G R1 R0
  1463. LOADUI R2 1
  1464. MOVE R0 R2
  1465. "
  1466. :relational_expr_stub_string2
  1467. "CMPSKIP.L R1 R0
  1468. LOADUI R2 1
  1469. MOVE R0 R2
  1470. "
  1471. :relational_expr_stub_string3
  1472. "CMPSKIP.LE R1 R0
  1473. LOADUI R2 1
  1474. MOVE R0 R2
  1475. "
  1476. :relational_expr_stub_string4
  1477. "CMPSKIP.NE R1 R0
  1478. LOADUI R2 1
  1479. MOVE R0 R2
  1480. "
  1481. :relational_expr_stub_string5
  1482. "CMPSKIP.E R1 R0
  1483. LOADUI R2 1
  1484. MOVE R0 R2
  1485. "
  1486. ;; relational_expr function
  1487. ;; Receives struct token_list* global_token in R13,
  1488. ;; struct token_list* out in R12,
  1489. ;; struct token_list* string_list in R11
  1490. ;; struct token_list* global_list in R10
  1491. ;; and struct token_list* FUNC in R9
  1492. ;; and struct token_list* current_target in R8
  1493. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1494. ;; Returns the token_lists modified
  1495. :relational_expr
  1496. CALLI R15 @additive_expr ; Walk up the tree
  1497. CALLI R15 @relational_expr_stub ; Deal with nodes at this level
  1498. RET R15
  1499. ;; relational_expr_stub function
  1500. ;; receives nothing
  1501. ;; returns nothing
  1502. ;; Updates struct token_list*
  1503. :bitwise_expr_stub
  1504. PUSHR R0 R15 ; Protect R0
  1505. PUSHR R1 R15 ; Protect R1
  1506. PUSHR R2 R15 ; Protect R2
  1507. PUSHR R3 R15 ; Protect R3
  1508. ;; Fixed pieces
  1509. LOADUI R0 $relational_expr ; Set First argument
  1510. LOADUI R3 $bitwise_expr_stub
  1511. ;; The & bit
  1512. LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
  1513. LOADUI R2 $bitwise_and ; Using "&"
  1514. CALLI R15 @general_recursion
  1515. ;; The && bit
  1516. LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
  1517. LOADUI R2 $logical_and ; Using "&&"
  1518. CALLI R15 @general_recursion
  1519. ;; The | bit
  1520. LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
  1521. LOADUI R2 $bitwise_or ; Using "|"
  1522. CALLI R15 @general_recursion
  1523. ;; The || bit
  1524. LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
  1525. LOADUI R2 $logical_or ; Using "||"
  1526. CALLI R15 @general_recursion
  1527. ;; The ^ bit
  1528. LOADUI R1 $bitwise_expr_stub_string2 ; Our second operation
  1529. LOADUI R2 $bitwise_xor ; Using "^"
  1530. CALLI R15 @general_recursion
  1531. POPR R3 R15 ; Restore R3
  1532. POPR R2 R15 ; Restore R2
  1533. POPR R1 R15 ; Restore R1
  1534. POPR R0 R15 ; Restore R0
  1535. RET R15
  1536. :bitwise_expr_stub_string0
  1537. "AND R0 R0 R1
  1538. "
  1539. :bitwise_expr_stub_string1
  1540. "OR R0 R0 R1
  1541. "
  1542. :bitwise_expr_stub_string2
  1543. "XOR R0 R0 R1
  1544. "
  1545. ;; bitwise_expr function
  1546. ;; Receives struct token_list* global_token in R13,
  1547. ;; struct token_list* out in R12,
  1548. ;; struct token_list* string_list in R11
  1549. ;; struct token_list* global_list in R10
  1550. ;; and struct token_list* FUNC in R9
  1551. ;; and struct token_list* current_target in R8
  1552. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1553. ;; Returns the token_lists modified
  1554. :bitwise_expr
  1555. CALLI R15 @relational_expr ; Walk up the tree
  1556. CALLI R15 @bitwise_expr_stub ; Deal with nodes at this level
  1557. RET R15
  1558. ;; primary_expr function
  1559. ;; Receives struct token_list* global_token in R13,
  1560. ;; struct token_list* out in R12,
  1561. ;; struct token_list* string_list in R11
  1562. ;; struct token_list* global_list in R10
  1563. ;; and struct token_list* FUNC in R9
  1564. ;; and struct token_list* current_target in R8
  1565. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1566. ;; Returns the token_lists modified
  1567. :primary_expr
  1568. PUSHR R0 R15 ; Protect R0
  1569. PUSHR R1 R15 ; Protect R1
  1570. LOADUI R0 $sizeof_string ; Load "sizeof"
  1571. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1572. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "sizeof"
  1573. JUMP.Z R0 @primary_expr_negate ; Guess not
  1574. ;; Deal with sizeof expression
  1575. CALLI R15 @unary_expr_sizeof ; Do real work
  1576. JUMP @primary_expr_done ; Wrap up
  1577. :primary_expr_negate
  1578. LOADU8 R0 R1 0 ; GLOBAL_TOKEN->S[0]
  1579. CMPSKIPI.E R0 45 ; IF GLOBAL_TOKEN->S[0] == '-'
  1580. JUMP @primary_expr_bang ; If not try '!'
  1581. ;; Deal with -a and -4 expressions
  1582. LOADUI R0 $primary_expr ; Using PRIMARY_EXPR
  1583. CALLI R15 @common_recursion ; Recurse
  1584. LOADUI R0 $primary_expr_str0 ; add footer
  1585. CALLI R15 @emit_out ; emit it
  1586. JUMP @primary_expr_done ; Wrap up
  1587. :primary_expr_bang
  1588. CMPSKIPI.E R0 33 ; IF GLOBAL_TOKEN->S[0] == "!"
  1589. JUMP @primary_expr_nested ; If not try '('
  1590. ;; deal with !a expressions
  1591. LOADUI R0 $postfix_expr ; Using POSTFIX_EXPR
  1592. CALLI R15 @common_recursion ; Recurse
  1593. LOADUI R0 $primary_expr_str1 ; add footer
  1594. CALLI R15 @emit_out ; emit it
  1595. JUMP @primary_expr_done ; Wrap up
  1596. :primary_expr_nested
  1597. CMPSKIPI.E R0 40 ; IF GLOBAL_TOKEN->S[0] == '('
  1598. JUMP @primary_expr_ch ; If not try 'char'
  1599. ;; Deal with ( expr )
  1600. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1601. CALLI R15 @expression ; Recurse
  1602. LOADUI R0 $primary_expr_str2 ; Using error message
  1603. LOADUI R1 $close_paren ; Using ")"
  1604. CALLI R15 @require_match ; Make sure we have closing match
  1605. JUMP @primary_expr_done ; Wrap up
  1606. :primary_expr_ch
  1607. CMPSKIPI.E R0 39 ; IF GLOBAL_TOKEN->S[0] == '\''
  1608. JUMP @primary_expr_st ; If not try "string"
  1609. ;; Deal with 'char'
  1610. CALLI R15 @primary_expr_char ; Collect char
  1611. JUMP @primary_expr_done ; Wrap up
  1612. :primary_expr_st
  1613. CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
  1614. JUMP @primary_expr_var ; If not try variables
  1615. ;; deal with "string"
  1616. CALLI R15 @primary_expr_string ; Collect string
  1617. JUMP @primary_expr_done ; Wrap up
  1618. :primary_expr_var
  1619. LOADUI R1 $variable_chars ; Using a-z+A-Z+_
  1620. CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in a-z+A-Z+_
  1621. JUMP.Z R0 @primary_expr_num
  1622. ;; Deal with foo TODO
  1623. CALLI R15 @primary_expr_variable ; deal with names
  1624. JUMP @primary_expr_done ; Wrap up
  1625. :primary_expr_num
  1626. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  1627. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  1628. LOADUI R1 $digit_chars ; Using 0-9
  1629. CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in 0-9
  1630. JUMP.Z R0 @primary_expr_failure ; Fail HARD
  1631. ;; Deal with 5
  1632. CALLI R15 @primary_expr_number ; deal with number
  1633. :primary_expr_done
  1634. POPR R1 R15 ; Restore R1
  1635. POPR R0 R15 ; Restore R0
  1636. RET R15
  1637. :primary_expr_str0
  1638. "NEG R0 R0
  1639. "
  1640. :primary_expr_str1
  1641. "XORI R0 R0 1
  1642. "
  1643. :primary_expr_str2
  1644. "Error in Primary expression
  1645. Didn't get )
  1646. "
  1647. ;; expression function
  1648. ;; Receives struct token_list* global_token in R13,
  1649. ;; struct token_list* out in R12,
  1650. ;; struct token_list* string_list in R11
  1651. ;; struct token_list* global_list in R10
  1652. ;; and struct token_list* FUNC in R9
  1653. ;; and struct token_list* current_target in R8
  1654. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1655. ;; Returns the token_lists modified
  1656. :expression
  1657. PUSHR R0 R15 ; Protect R0
  1658. PUSHR R1 R15 ; Protect R1
  1659. PUSHR R2 R15 ; Protect R2
  1660. PUSHR R3 R15 ; Protect R3
  1661. CALLI R15 @bitwise_expr ; Check for more primitives first
  1662. LOADUI R0 $equal ; Using "="
  1663. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1664. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  1665. JUMP.Z R0 @expression_done ; Be done
  1666. ;; Determine store type
  1667. LOADUI R3 $expression_string1 ; Assuming the default of STORE CHAR
  1668. ;; First possible reason for INT
  1669. LOADUI R0 $close_bracket ; Using "]"
  1670. LOAD32 R1 R13 4 ; GLOBAL_TOKEN->PREV
  1671. LOAD32 R1 R1 8 ; GLOBAL_TOKEN->PREV->S
  1672. CALLI R15 @match ; IF GLOBAL_TOKEN->PREV-> == "]"
  1673. CMPSKIPI.NE R0 0 ; IF FALSE
  1674. LOADUI R3 $expression_string0 ; STORE INTEGER
  1675. ;; Second possible reason for INTeger
  1676. LOADUI R0 $type_char_indirect_name ; Using "char*"
  1677. LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
  1678. CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
  1679. CMPSKIPI.NE R0 0 ; IF FALSE
  1680. LOADUI R3 $expression_string0 ; STORE INTEGER
  1681. ;; Recurse to evaluate expression being stored
  1682. LOADUI R0 $expression ; Using expression
  1683. CALLI R15 @common_recursion ; Perform common recursion
  1684. ;; Put our string and clean up
  1685. MOVE R0 R3 ; Using our STORED string
  1686. CALLI R15 @emit_out ; emit it
  1687. FALSE R8 ; CURRENT_TARGET = NULL
  1688. :expression_done
  1689. POPR R3 R15 ; Restore R3
  1690. POPR R2 R15 ; Restore R2
  1691. POPR R1 R15 ; Restore R1
  1692. POPR R0 R15 ; Restore R0
  1693. RET R15
  1694. :expression_string0
  1695. "STORE R0 R1 0
  1696. "
  1697. :expression_string1
  1698. "STORE8 R0 R1 0
  1699. "
  1700. ;; process_if function
  1701. ;; struct token_list* out in R12,
  1702. ;; struct token_list* string_list in R11
  1703. ;; struct token_list* global_list in R10
  1704. ;; and struct token_list* FUNC in R9
  1705. ;; and struct token_list* current_target in R8
  1706. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1707. ;; Returns the token_lists modified
  1708. :process_if
  1709. PUSHR R0 R15 ; Protect R0
  1710. PUSHR R1 R15 ; Protect R1
  1711. PUSHR R2 R15 ; Protect R2
  1712. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1713. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1714. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1715. CALLI R15 @numerate_number ; Convert CURRENT_COUNT to string
  1716. MOVE R2 R0 ; Protect our string
  1717. LOADUI R0 $process_if_string0 ; using first string
  1718. CALLI R15 @emit_out ; emit it
  1719. LOAD32 R0 R9 8 ; FUNCTION->S
  1720. COPY R1 R2 ; Using our current count string
  1721. CALLI R15 @uniqueID_out ; Add unique identifier
  1722. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1723. LOADUI R0 $process_if_string1 ; Our first error message
  1724. LOADUI R1 $open_paren ; Using "("
  1725. CALLI R15 @require_match ; Make sure we have what we need
  1726. CALLI R15 @expression ; Recurse to get our boolean expression
  1727. LOADUI R0 $process_if_string2 ; Our test and jump
  1728. CALLI R15 @emit_out ; emit it
  1729. LOAD32 R0 R9 8 ; FUNCTION->S
  1730. COPY R1 R2 ; Using our current count string
  1731. CALLI R15 @uniqueID_out ; Add unique identifier
  1732. LOADUI R0 $process_if_string3 ; Our second error message
  1733. LOADUI R1 $close_paren ; Using ")"
  1734. CALLI R15 @require_match ; Make sure we have what we need
  1735. CALLI R15 @statement ; Collect our if statement
  1736. LOADUI R0 $process_if_string4 ; Our jump over else
  1737. CALLI R15 @emit_out ; emit it
  1738. LOAD32 R0 R9 8 ; FUNCTION->S
  1739. COPY R1 R2 ; Using our current count string
  1740. CALLI R15 @uniqueID_out ; Add unique identifier
  1741. LOADUI R0 $process_if_string5 ; Our else label
  1742. CALLI R15 @emit_out ; emit it
  1743. LOAD32 R0 R9 8 ; FUNCTION->S
  1744. CALLI R15 @uniqueID_out ; Add unique identifier
  1745. LOADUI R0 $else_string ; Using "else"
  1746. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1747. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "else"
  1748. JUMP.Z R0 @process_if_else ; Looks like no else
  1749. ;; Deal with else
  1750. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1751. CALLI R15 @statement ; Grab else statement
  1752. :process_if_else
  1753. LOADUI R0 $process_if_string6 ; Our jump over else
  1754. CALLI R15 @emit_out ; emit it
  1755. LOAD32 R0 R9 8 ; FUNCTION->S
  1756. COPY R1 R2 ; Using our current count string
  1757. CALLI R15 @uniqueID_out ; Add unique identifier
  1758. POPR R2 R15 ; Restore R2
  1759. POPR R1 R15 ; Restore R1
  1760. POPR R0 R15 ; Restore R0
  1761. RET R15
  1762. :process_if_string0
  1763. "# IF_"
  1764. :process_if_string1
  1765. "ERROR in process_if
  1766. MISSING (
  1767. "
  1768. :process_if_string2
  1769. "JUMP.Z R0 @ELSE_"
  1770. :process_if_string3
  1771. "ERROR in process_if
  1772. MISSING )
  1773. "
  1774. :process_if_string4
  1775. "JUMP @_END_IF_"
  1776. :process_if_string5
  1777. ":ELSE_"
  1778. :process_if_string6
  1779. ":_END_IF_"
  1780. ;; save_break_frame microfunction
  1781. ;; Overwrites R0 and R1
  1782. ;; Saves break frame on stack
  1783. ;; Returns to caller
  1784. :save_break_frame
  1785. POPR R1 R15 ; Save return address
  1786. LOADR32 R0 @break_frame ; Obtain BREAK_FRAME
  1787. PUSHR R0 R15 ; Protect BREAK_FRAME
  1788. LOADR32 R0 @break_target_head ; obtain HEAD
  1789. PUSHR R0 R15 ; Protect HEAD
  1790. LOADR32 R0 @break_target_func ; obtain FUNC
  1791. PUSHR R0 R15 ; Protect FUNC
  1792. LOADR32 R0 @break_target_num ; obtain NUM
  1793. PUSHR R0 R15 ; Protect NUM
  1794. PUSHR R1 R15 ; Set where we are returning to
  1795. RET R15
  1796. ;; restore_break_frame microfunction
  1797. ;; Overwrites R0 and R1
  1798. ;; Restores break frame from stack
  1799. ;; Returns to caller
  1800. :restore_break_frame
  1801. POPR R1 R15 ; Save return address
  1802. POPR R0 R15 ; obtain NUM
  1803. STORER32 R0 @break_target_num ; Restore NUM
  1804. POPR R0 R15 ; obtain FUNC
  1805. STORER32 R0 @break_target_func ; Restore FUNC
  1806. POPR R0 R15 ; obtain HEAD
  1807. STORER32 R0 @break_target_head ; Restore HEAD
  1808. POPR R0 R15 ; obtain BREAK_FRAME
  1809. STORER32 R0 @break_frame ; Restore BREAK_FRAME
  1810. PUSHR R1 R15 ; Set where we are returning to
  1811. RET R15
  1812. ;; set_break_frame microfunction
  1813. ;; Receives char* num in R0, char* head in R1
  1814. ;; Overwrites R0
  1815. ;; Sets break frame using
  1816. ;; R9 holding FUNC
  1817. ;; Returns to calling function
  1818. :set_break_frame
  1819. STORER32 R1 @break_target_head ; update BREAK_TARGET_HEAD
  1820. STORER32 R0 @break_target_num ; Update BREAK_TARGET_NUM
  1821. LOAD32 R0 R9 4 ; Using FUNCTION->LOCALS
  1822. STORER32 R0 @break_frame ; update BREAK_FRAME
  1823. LOAD32 R0 R9 8 ; Using FUNCTION->S
  1824. STORER32 R0 @break_target_func ; update BREAK_TARGET_FUNC
  1825. RET R15
  1826. ;; process_for function
  1827. ;; struct token_list* out in R12,
  1828. ;; struct token_list* string_list in R11
  1829. ;; struct token_list* global_list in R10
  1830. ;; and struct token_list* FUNC in R9
  1831. ;; and struct token_list* current_target in R8
  1832. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1833. ;; Returns the token_lists modified
  1834. :process_for
  1835. PUSHR R2 R15 ; Protect R2
  1836. PUSHR R1 R15 ; Protect R1
  1837. PUSHR R0 R15 ; Protect R0
  1838. CALLI R15 @save_break_frame ; Save break frame
  1839. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1840. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1841. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1842. CALLI R15 @numerate_number ; Convert to string
  1843. COPY R2 R0 ; Protect NUMBER_STRING
  1844. LOADUI R1 $process_for_string0 ; Get new HEAD
  1845. CALLI R15 @set_break_frame ; Set the break frame values
  1846. LOADUI R0 $process_for_string1 ; Our comment header
  1847. CALLI R15 @emit_out ; emit it
  1848. COPY R1 R2 ; Using NUMBER_STRING
  1849. LOAD32 R0 R9 8 ; FUNCTION->S
  1850. CALLI R15 @uniqueID_out ; emit it
  1851. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1852. LOADUI R0 $process_for_string2 ; Our first error message
  1853. LOADUI R1 $open_paren ; Using "("
  1854. CALLI R15 @require_match ; Verify match
  1855. LOADUI R0 $semicolon ; Using ";"
  1856. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  1857. CALLI R15 @match ; IF GLOBAL_TOKEN->S -- ";"
  1858. CMPSKIPI.NE R0 0 ; If GLOBAL_TOKEN->S != ";"
  1859. CALLI R15 @expression ; Skip that step
  1860. LOADUI R0 $process_for_string3 ; Our comment header
  1861. CALLI R15 @emit_out ; emit it
  1862. COPY R1 R2 ; Using NUMBER_STRING
  1863. LOAD32 R0 R9 8 ; FUNCTION->S
  1864. CALLI R15 @uniqueID_out ; emit it
  1865. LOADUI R0 $process_for_string4 ; Our second error message
  1866. LOADUI R1 $semicolon ; Using ";"
  1867. CALLI R15 @require_match ; Verify match
  1868. CALLI R15 @expression ; TEST logic required
  1869. LOADUI R0 $process_for_string5 ; Our comment header
  1870. CALLI R15 @emit_out ; emit it
  1871. COPY R1 R2 ; Using NUMBER_STRING
  1872. LOAD32 R0 R9 8 ; FUNCTION->S
  1873. CALLI R15 @uniqueID_out ; emit it
  1874. LOADUI R0 $process_for_string6 ; Our comment header
  1875. CALLI R15 @emit_out ; emit it
  1876. LOAD32 R0 R9 8 ; FUNCTION->S
  1877. CALLI R15 @uniqueID_out ; emit it
  1878. LOADUI R0 $process_for_string7 ; Our comment header
  1879. CALLI R15 @emit_out ; emit it
  1880. LOAD32 R0 R9 8 ; FUNCTION->S
  1881. CALLI R15 @uniqueID_out ; emit it
  1882. LOADUI R0 $process_for_string8 ; Our third error message
  1883. LOADUI R1 $semicolon ; Using ";"
  1884. CALLI R15 @require_match ; Verify match
  1885. CALLI R15 @expression ; Iterator logic
  1886. LOADUI R0 $process_for_string9 ; Our comment header
  1887. CALLI R15 @emit_out ; emit it
  1888. COPY R1 R2 ; Using NUMBER_STRING
  1889. LOAD32 R0 R9 8 ; FUNCTION->S
  1890. CALLI R15 @uniqueID_out ; emit it
  1891. LOADUI R0 $process_for_string10 ; Our comment header
  1892. CALLI R15 @emit_out ; emit it
  1893. LOAD32 R0 R9 8 ; FUNCTION->S
  1894. CALLI R15 @uniqueID_out ; emit it
  1895. LOADUI R0 $process_for_string11 ; Our final error message
  1896. LOADUI R1 $close_paren ; Using ")"
  1897. CALLI R15 @require_match ; Verify match
  1898. CALLI R15 @statement ; Main body
  1899. LOADUI R0 $process_for_string12 ; Our comment header
  1900. CALLI R15 @emit_out ; emit it
  1901. COPY R1 R2 ; Using NUMBER_STRING
  1902. LOAD32 R0 R9 8 ; FUNCTION->S
  1903. CALLI R15 @uniqueID_out ; emit it
  1904. LOADUI R0 $process_for_string13 ; Our comment header
  1905. CALLI R15 @emit_out ; emit it
  1906. LOAD32 R0 R9 8 ; FUNCTION->S
  1907. CALLI R15 @uniqueID_out ; emit it
  1908. CALLI R15 @restore_break_frame ; Restore break frame
  1909. POPR R0 R15 ; Restore R0
  1910. POPR R1 R15 ; Restore R1
  1911. POPR R2 R15 ; Restore R2
  1912. RET R15
  1913. :process_for_string0
  1914. "FOR_END_"
  1915. :process_for_string1
  1916. "# FOR_initialization_"
  1917. :process_for_string2
  1918. "ERROR in process_for
  1919. MISSING (
  1920. "
  1921. :process_for_string3
  1922. ":FOR_"
  1923. :process_for_string4
  1924. "ERROR in process_for
  1925. MISSING ;1
  1926. "
  1927. :process_for_string5
  1928. "JUMP.Z R0 @FOR_END_"
  1929. :process_for_string6
  1930. "JUMP @FOR_THEN_"
  1931. :process_for_string7
  1932. ":FOR_ITER_"
  1933. :process_for_string8
  1934. "ERROR in process_for
  1935. MISSING ;2
  1936. "
  1937. :process_for_string9
  1938. "JUMP @FOR_"
  1939. :process_for_string10
  1940. ":FOR_THEN_"
  1941. :process_for_string11
  1942. "ERROR in process_for
  1943. MISSING )
  1944. "
  1945. :process_for_string12
  1946. "JUMP @FOR_ITER_"
  1947. :process_for_string13
  1948. ":FOR_END_"
  1949. ;; process_do function
  1950. ;; struct token_list* out in R12,
  1951. ;; struct token_list* string_list in R11
  1952. ;; struct token_list* global_list in R10
  1953. ;; and struct token_list* FUNC in R9
  1954. ;; and struct token_list* current_target in R8
  1955. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  1956. ;; Returns the token_lists modified
  1957. :process_do
  1958. PUSHR R2 R15 ; Protect R2
  1959. PUSHR R1 R15 ; Protect R1
  1960. PUSHR R0 R15 ; Protect R0
  1961. CALLI R15 @save_break_frame ; Save break frame
  1962. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  1963. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  1964. STORER32 R1 @current_count ; Update CURRENT_COUNT
  1965. CALLI R15 @numerate_number ; Convert to string
  1966. COPY R2 R0 ; Protect NUMBER_STRING
  1967. LOADUI R1 $process_do_string0 ; Using our desired head
  1968. CALLI R15 @set_break_frame ; Set the break frame values
  1969. LOADUI R0 $process_do_string1 ; Our label
  1970. CALLI R15 @emit_out ; emit it
  1971. COPY R1 R2 ; Using NUMBER_STRING
  1972. LOAD32 R0 R9 8 ; FUNCTION->S
  1973. CALLI R15 @uniqueID_out ; emit it
  1974. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  1975. CALLI R15 @statement ; Collect our Do statement
  1976. LOADUI R0 $process_do_string2 ; our first error message
  1977. LOADUI R1 $while_string ; Using "while"
  1978. CALLI R15 @require_match ; Check for match
  1979. LOADUI R0 $process_do_string3 ; our second error message
  1980. LOADUI R1 $open_paren ; Using "("
  1981. CALLI R15 @require_match ; Check for match
  1982. CALLI R15 @expression ; Our logical expression
  1983. LOADUI R0 $process_do_string4 ; our third error message
  1984. LOADUI R1 $close_paren ; Using ")"
  1985. CALLI R15 @require_match ; Check for match
  1986. LOADUI R0 $process_do_string5 ; our final error message
  1987. LOADUI R1 $semicolon ; Using ";"
  1988. CALLI R15 @require_match ; Check for match
  1989. LOADUI R0 $process_do_string6 ; Our test string
  1990. CALLI R15 @emit_out ; emit it
  1991. COPY R1 R2 ; Put NUMBER_STRING in right place
  1992. LOAD32 R0 R9 8 ; FUNCTION->S
  1993. CALLI R15 @uniqueID_out ; emit it
  1994. LOADUI R0 $process_do_string7 ; Our end label string
  1995. CALLI R15 @emit_out ; emit it
  1996. LOAD32 R0 R9 8 ; FUNCTION->S
  1997. CALLI R15 @uniqueID_out ; emit it
  1998. CALLI R15 @restore_break_frame ; Restore break frame
  1999. POPR R0 R15 ; Restore R0
  2000. POPR R1 R15 ; Restore R1
  2001. POPR R2 R15 ; Restore R2
  2002. RET R15
  2003. :process_do_string0
  2004. "DO_END_"
  2005. :process_do_string1
  2006. ":DO_"
  2007. :process_do_string2
  2008. "ERROR in process_do
  2009. MISSING while
  2010. "
  2011. :process_do_string3
  2012. "ERROR in process_do
  2013. MISSING (
  2014. "
  2015. :process_do_string4
  2016. "ERROR in process_do
  2017. MISSING )
  2018. "
  2019. :process_do_string5
  2020. "ERROR in process_do
  2021. MISSING ;
  2022. "
  2023. :process_do_string6
  2024. "JUMP.NZ R0 @DO_"
  2025. :process_do_string7
  2026. ":DO_END_"
  2027. ;; process_while function
  2028. ;; struct token_list* out in R12,
  2029. ;; struct token_list* string_list in R11
  2030. ;; struct token_list* global_list in R10
  2031. ;; and struct token_list* FUNC in R9
  2032. ;; and struct token_list* current_target in R8
  2033. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2034. ;; Returns the token_lists modified
  2035. :process_while
  2036. PUSHR R2 R15 ; Protect R2
  2037. PUSHR R1 R15 ; Protect R1
  2038. PUSHR R0 R15 ; Protect R0
  2039. CALLI R15 @save_break_frame ; Save break frame
  2040. LOADR32 R0 @current_count ; Using CURRENT_COUNT
  2041. ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
  2042. STORER32 R1 @current_count ; Update CURRENT_COUNT
  2043. CALLI R15 @numerate_number ; Convert to string
  2044. COPY R2 R0 ; Protect NUMBER_STRING
  2045. LOADUI R1 $process_while_string0 ; Set HEAD
  2046. CALLI R15 @set_break_frame ; Set the break frame values
  2047. LOADUI R0 $process_while_string1 ; Our head label
  2048. CALLI R15 @emit_out ; emit it
  2049. COPY R1 R2 ; Using NUMBER_STRING
  2050. LOAD32 R0 R9 8 ; FUNCTION->S
  2051. CALLI R15 @uniqueID_out ; emit it
  2052. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2053. LOADUI R0 $process_while_string2 ; Our first error message
  2054. LOADUI R1 $open_paren ; Using "("
  2055. CALLI R15 @require_match ; Check for match
  2056. CALLI R15 @expression ; Collect test expression
  2057. LOADUI R0 $process_while_string3 ; Our test and jump
  2058. CALLI R15 @emit_out ; emit it
  2059. COPY R1 R2 ; Using NUMBER_STRING
  2060. LOAD32 R0 R9 8 ; FUNCTION->S
  2061. CALLI R15 @uniqueID_out ; emit it
  2062. LOADUI R0 $process_while_string4 ; Our trailing comment
  2063. CALLI R15 @emit_out ; emit it
  2064. LOAD32 R0 R9 8 ; FUNCTION->S
  2065. CALLI R15 @uniqueID_out ; emit it
  2066. LOADUI R0 $process_while_string5 ; Our first error message
  2067. LOADUI R1 $close_paren ; Using ")"
  2068. CALLI R15 @require_match ; Check for match
  2069. CALLI R15 @statement ; Collect our loop statement
  2070. LOADUI R0 $process_while_string6 ; Our test and jump
  2071. CALLI R15 @emit_out ; emit it
  2072. COPY R1 R2 ; Using NUMBER_STRING
  2073. LOAD32 R0 R9 8 ; FUNCTION->S
  2074. CALLI R15 @uniqueID_out ; emit it
  2075. LOADUI R0 $process_while_string7 ; Our trailing comment
  2076. CALLI R15 @emit_out ; emit it
  2077. LOAD32 R0 R9 8 ; FUNCTION->S
  2078. CALLI R15 @uniqueID_out ; emit it
  2079. CALLI R15 @restore_break_frame ; Restore break frame
  2080. POPR R0 R15 ; Restore R0
  2081. POPR R1 R15 ; Restore R1
  2082. POPR R2 R15 ; Restore R2
  2083. RET R15
  2084. :process_while_string0
  2085. "END_WHILE_"
  2086. :process_while_string1
  2087. ":WHILE_"
  2088. :process_while_string2
  2089. "ERROR in process_while
  2090. MISSING (
  2091. "
  2092. :process_while_string3
  2093. "JUMP.Z R0 @END_WHILE_"
  2094. :process_while_string4
  2095. "# THEN_while_"
  2096. :process_while_string5
  2097. "ERROR in process_while
  2098. MISSING )
  2099. "
  2100. :process_while_string6
  2101. "JUMP @WHILE_"
  2102. :process_while_string7
  2103. ":END_WHILE_"
  2104. ;; return_result function
  2105. ;; Receives nothing
  2106. ;; Returns nothing
  2107. ;; and struct token_list* FUNC in R9
  2108. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2109. :return_result
  2110. PUSHR R0 R15 ; Protect R0
  2111. PUSHR R1 R15 ; Protect R1
  2112. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2113. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2114. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2115. CMPSKIPI.E R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
  2116. CALLI R15 @expression ; Evaluate expression
  2117. LOADUI R0 $return_result_string0 ; Using or error message
  2118. LOADUI R1 $semicolon ; Using ";"
  2119. CALLI R15 @require_match ; Require a match to ";"
  2120. LOADUI R0 $return_result_string1 ; Our pop command
  2121. LOAD32 R1 R9 4 ; FUNCTION->LOCALS
  2122. :return_result_iter
  2123. JUMP.Z R1 @return_result_done ; Be done when we hit NULL
  2124. CALLI R15 @emit_out ; Put the string every iteration
  2125. LOAD32 R1 R1 0 ; I = I->NEXT
  2126. JUMP @return_result_iter ; Keep looping
  2127. :return_result_done
  2128. LOADUI R0 $return_result_string2 ; Our footer
  2129. CALLI R15 @emit_out ; emit it
  2130. POPR R1 R15 ; Restore R1
  2131. POPR R0 R15 ; Restore R0
  2132. RET R15
  2133. :return_result_string0
  2134. "ERROR in return_result
  2135. MISSING ;
  2136. "
  2137. :return_result_string1
  2138. "POPR R1 R15 # _return_result_locals
  2139. "
  2140. :return_result_string2
  2141. "RET R15
  2142. "
  2143. ;; process_break function
  2144. ;; Receives nothing
  2145. ;; and struct token_list* FUNC in R9
  2146. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2147. ;; Returns the token_lists modified
  2148. :process_break
  2149. PUSHR R0 R15 ; Protect R0
  2150. PUSHR R1 R15 ; Protect R1
  2151. PUSHR R2 R15 ; Protect R2
  2152. LOADR32 R0 @break_target_head ; BREAK_TARGET_HEAD
  2153. JUMP.NZ R0 @process_break_NON_NULL
  2154. ;; Deal with NULL == BREAK_TARGET_HEAD
  2155. LOADUI R0 $process_break_string0 ; Our first error message
  2156. FALSE R1 ; Write for User
  2157. CALLI R15 @file_print ; write it
  2158. CALLI R15 @line_error ; Give useful info
  2159. LOADUI R0 $newline ; Using "\n"
  2160. CALLI R15 @file_print ; Print it
  2161. HALT
  2162. :process_break_NON_NULL
  2163. LOADR32 R2 @break_frame ; BREAK_FRAME
  2164. LOAD32 R1 R9 4 ; I = FUNCTION->LOCALS
  2165. LOADUI R0 $process_break_string1 ; Our pop string
  2166. :process_break_iter
  2167. CMPJUMPI.E R1 R2 @process_break_done ; IF I == BREAK_FRAME
  2168. JUMP.Z R1 @process_break_done ; IF NULL == I break
  2169. CALLI R15 @emit_out ; emit pop
  2170. LOAD32 R1 R1 0 ; I = I->NEXT
  2171. JUMP @process_break_iter ; Loop
  2172. :process_break_done
  2173. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2174. LOADUI R0 $process_break_string2 ; Our jump string
  2175. CALLI R15 @emit_out ; emit it
  2176. LOADR32 R0 @break_target_head ; Our HEAD string
  2177. CALLI R15 @emit_out ; emit it
  2178. LOADR32 R0 @break_target_func ; Our FUNC string
  2179. CALLI R15 @emit_out ; emit it
  2180. LOADUI R0 $underline ; Using "_"
  2181. CALLI R15 @emit_out ; emit it
  2182. LOADR32 R0 @break_target_num ; Our NUM string
  2183. CALLI R15 @emit_out ; emit it
  2184. LOADUI R0 $newline ; Using "\n"
  2185. CALLI R15 @emit_out ; emit it
  2186. LOADUI R0 $process_break_string3 ; Our final error string
  2187. LOADUI R1 $semicolon ; Using ";"
  2188. CALLI R15 @require_match ; Make sure we get that match
  2189. POPR R2 R15 ; Restore R2
  2190. POPR R1 R15 ; Restore R1
  2191. POPR R0 R15 ; Restore R0
  2192. RET R15
  2193. :process_break_string0
  2194. "Not inside of a loop or case statement
  2195. "
  2196. :process_break_string1
  2197. "POPR R1 R15 # break_cleanup_locals
  2198. "
  2199. :process_break_string2
  2200. "JUMP @"
  2201. :process_break_string3
  2202. "ERROR in break statement
  2203. Missing ;
  2204. "
  2205. :break_frame
  2206. NOP
  2207. :break_target_head
  2208. NOP
  2209. :break_target_func
  2210. NOP
  2211. :break_target_num
  2212. NOP
  2213. ;; process_asm function
  2214. ;; Receives struct token_list* global_token in R13,
  2215. ;; struct token_list* out in R12,
  2216. ;; struct token_list* string_list in R11
  2217. ;; struct token_list* global_list in R10
  2218. ;; and struct token_list* FUNC in R9
  2219. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2220. ;; Returns the token_lists modified
  2221. :process_asm
  2222. PUSHR R0 R15 ; Protect R0
  2223. PUSHR R1 R15 ; Protect R1
  2224. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2225. ;; First required match
  2226. LOADUI R0 $process_asm_string0 ; Using our First error message
  2227. LOADUI R1 $open_paren ; Using "("
  2228. CALLI R15 @require_match ; Make sure of our required match
  2229. :process_asm_iter
  2230. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2231. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2232. CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
  2233. JUMP @process_asm_done ; Otherwise be done
  2234. ;; Add block of assembly
  2235. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2236. ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
  2237. CALLI R15 @emit_out ; emit it
  2238. LOADUI R0 $newline ; Using "\n"
  2239. CALLI R15 @emit_out ; emit it
  2240. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2241. JUMP @process_asm_iter
  2242. :process_asm_done
  2243. LOADUI R0 $process_asm_string1 ; Using our First error message
  2244. LOADUI R1 $close_paren ; Using ")"
  2245. CALLI R15 @require_match ; Make sure of our required match
  2246. LOADUI R0 $process_asm_string2 ; Using our First error message
  2247. LOADUI R1 $semicolon ; Using ";"
  2248. CALLI R15 @require_match ; Make sure of our required match
  2249. POPR R1 R15 ; Restore R1
  2250. POPR R0 R15 ; Restore R0
  2251. RET R15
  2252. :process_asm_string0
  2253. "ERROR in process_asm
  2254. MISSING (
  2255. "
  2256. :process_asm_string1
  2257. "ERROR in process_asm
  2258. MISSING )
  2259. "
  2260. :process_asm_string2
  2261. "ERROR in process_asm
  2262. MISSING ;
  2263. "
  2264. ;; recursive_statement function
  2265. ;; Receives struct token_list* global_token in R13,
  2266. ;; struct token_list* out in R12,
  2267. ;; struct token_list* string_list in R11
  2268. ;; struct token_list* global_list in R10
  2269. ;; and struct token_list* FUNC in R9
  2270. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2271. ;; Returns the token_lists modified
  2272. :recursive_statement
  2273. PUSHR R0 R15 ; Protect R0
  2274. PUSHR R1 R15 ; Protect R1
  2275. PUSHR R2 R15 ; Protect R2
  2276. PUSHR R3 R15 ; Protect R3
  2277. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2278. LOAD32 R3 R9 4 ; FRAME = FUNCTION->LOCALS
  2279. :recursive_statement_iter
  2280. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2281. LOADUI R0 $close_curly_brace ; '}'
  2282. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "}"
  2283. JUMP.NZ R0 @recursive_statement_cleanup
  2284. ;; Lets collect those statements
  2285. CALLI R15 @statement ; Collect next statement
  2286. JUMP @recursive_statement_iter ; Iterate
  2287. :recursive_statement_cleanup
  2288. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2289. LOAD32 R1 R12 8 ; OUT->S
  2290. LOADUI R0 $recursive_statement_string0 ; "RET R15\n"
  2291. CALLI R15 @match ; IF OUT->S == "RET R15\n"
  2292. JUMP.NZ R0 @recursive_statement_done ; Save some work
  2293. ;; Lets pop them all off
  2294. LOAD32 R2 R9 4 ; FUNC->LOCALS
  2295. LOADUI R0 $recursive_statement_string1 ; Our POP string
  2296. :recursive_statement_pop
  2297. CMPJUMPI.E R2 R3 @recursive_statement_done
  2298. CALLI R15 @emit_out ; emit it
  2299. LOAD32 R2 R2 0 ; I = I->NEXT
  2300. JUMP.NZ R2 @recursive_statement_pop ; Keep looping
  2301. :recursive_statement_done
  2302. STORE32 R3 R9 4 ; FUNC->LOCALS = FRAME
  2303. POPR R3 R15 ; Restore R3
  2304. POPR R2 R15 ; Restore R2
  2305. POPR R1 R15 ; Restore R1
  2306. POPR R0 R15 ; Restore R0
  2307. RET R15
  2308. :recursive_statement_string0
  2309. "RET R15
  2310. "
  2311. :recursive_statement_string1
  2312. "POPR R1 R15 # _recursive_statement_locals
  2313. "
  2314. ;; statement function
  2315. ;; Receives struct token_list* global_token in R13,
  2316. ;; struct token_list* out in R12,
  2317. ;; struct token_list* string_list in R11
  2318. ;; struct token_list* global_list in R10
  2319. ;; and struct token_list* FUNC in R9
  2320. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2321. ;; Returns the token_lists modified
  2322. :statement
  2323. PUSHR R0 R15 ; Protect R0
  2324. PUSHR R1 R15 ; Protect R1
  2325. PUSHR R2 R15 ; Protect R2
  2326. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  2327. LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
  2328. CMPSKIPI.E R0 123 ; If GLOBAL_TOKEN->S[0] != '{'
  2329. JUMP @statement_label ; Try next match
  2330. ;; Deal with { statements }
  2331. CALLI R15 @recursive_statement
  2332. JUMP @statement_done ; All done
  2333. :statement_label
  2334. CMPSKIPI.E R0 58 ; If GLOBAL_TOKEN->S[0] != ':'
  2335. JUMP @statement_collect_local ; Try next match
  2336. ;; Deal with :label
  2337. LOAD32 R0 R13 8 ; Using GLOBAL_TOKEN->S
  2338. CALLI R15 @emit_out ; emit it
  2339. LOADUI R0 $statement_string0 ; Using label string
  2340. CALLI R15 @emit_out ; emit it
  2341. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2342. JUMP @statement_done ; Move on to next thing
  2343. :statement_collect_local
  2344. LOADUI R0 $struct ; Using "struct"
  2345. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2346. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "struct"
  2347. JUMP.NZ R0 @statement_collect_local_0
  2348. ;; Otherwise check if it is a primitive
  2349. LOADUI R0 $prim_types ; Using the Primitive types list
  2350. SWAP R0 R1 ; Put in correct order
  2351. CALLI R15 @lookup_type ; Check if a primitive type
  2352. JUMP.Z R0 @statement_process_if ; If not try the next one
  2353. :statement_collect_local_0
  2354. CALLI R15 @collect_local ; Collect the local
  2355. JUMP @statement_done ; And move on
  2356. :statement_process_if
  2357. LOADUI R0 $if_string ; Using "if"
  2358. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2359. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "if"
  2360. JUMP.Z R0 @statement_process_do
  2361. CALLI R15 @process_if ; Collect that if statement
  2362. JUMP @statement_done ; Move on to next thing
  2363. :statement_process_do
  2364. LOADUI R0 $do_string ; Using "do"
  2365. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2366. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "do"
  2367. JUMP.Z R0 @statement_process_while
  2368. CALLI R15 @process_do ; Collect that do statement
  2369. JUMP @statement_done ; Move on to next thing
  2370. :statement_process_while
  2371. LOADUI R0 $while_string ; Using "while"
  2372. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2373. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "while"
  2374. JUMP.Z R0 @statement_process_for
  2375. CALLI R15 @process_while ; Collect that while statement
  2376. JUMP @statement_done ; Move on to next thing
  2377. :statement_process_for
  2378. LOADUI R0 $for_string ; Using "for"
  2379. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2380. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "for"
  2381. JUMP.Z R0 @statement_process_asm
  2382. CALLI R15 @process_for ; Collect that FOR statement
  2383. JUMP @statement_done ; Move on to next thing
  2384. :statement_process_asm
  2385. LOADUI R0 $asm_string ; Using "asm"
  2386. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2387. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "asm"
  2388. JUMP.Z R0 @statement_goto
  2389. CALLI R15 @process_asm ; Collect that ASM statement
  2390. JUMP @statement_done ; Move on to next thing
  2391. :statement_goto
  2392. LOADUI R0 $goto_string ; Using "goto"
  2393. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2394. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "goto"
  2395. JUMP.Z R0 @statement_return_result
  2396. ;; Deal with goto label:
  2397. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2398. LOADUI R0 $statement_string1 ; Using our JUMP string
  2399. CALLI R15 @emit_out ; emit it
  2400. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2401. CALLI R15 @emit_out ; emit it
  2402. LOADUI R0 $newline ; "\n"
  2403. CALLI R15 @emit_out ; emit it
  2404. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2405. LOADUI R0 $statement_string2 ; Using our error message
  2406. LOADUI R1 $semicolon ; Using ";"
  2407. CALLI R15 @require_match ; Make sure of our required match
  2408. JUMP @statement_done ; Move on
  2409. :statement_return_result
  2410. LOADUI R0 $return_string ; Using "return"
  2411. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2412. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "return"
  2413. JUMP.Z R0 @statement_break
  2414. ;; Deal with return statements in functions
  2415. CALLI R15 @return_result ; Do all of the work
  2416. JUMP @statement_done ; Move on to next
  2417. :statement_break
  2418. LOADUI R0 $break_string ; Using "break"
  2419. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2420. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "break"
  2421. JUMP.Z R0 @statement_continue
  2422. ;; Let break function deal with updating out
  2423. CALLI R15 @process_break ; Do all the work
  2424. JUMP @statement_done ; Move on to next
  2425. :statement_continue
  2426. LOADUI R0 $continue_string ; Using "continue"
  2427. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2428. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "continue"
  2429. JUMP.Z R0 @statement_expression
  2430. ;; Simple Continue compatibility
  2431. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2432. LOADUI R0 $statement_string3 ; Using our continue comment string
  2433. CALLI R15 @emit_out ; emit it
  2434. LOADUI R0 $statement_string2 ; Using our error message
  2435. LOADUI R1 $semicolon ; Using ";"
  2436. CALLI R15 @require_match ; Make sure of our required match
  2437. JUMP @statement_done ; Move on
  2438. :statement_expression
  2439. CALLI R15 @expression ; Do expression evaluation
  2440. LOADUI R0 $statement_string2 ; Load our error message
  2441. LOADUI R1 $semicolon ; use ";"
  2442. CALLI R15 @require_match ; Make sure GLOBAL_TOKEN-> == ";"
  2443. :statement_done
  2444. POPR R2 R15 ; Restore R2
  2445. POPR R1 R15 ; Restore R1
  2446. POPR R0 R15 ; Restore R0
  2447. RET R15
  2448. :statement_string0
  2449. " #C goto label
  2450. "
  2451. :statement_string1
  2452. "JUMP @"
  2453. :statement_string2
  2454. "ERROR in statement
  2455. MISSING ;
  2456. "
  2457. :statement_string3
  2458. "
  2459. #continue statement
  2460. "
  2461. ;; collect_local function
  2462. ;; Receives struct token_list* global_token in R13,
  2463. ;; struct token_list* out in R12,
  2464. ;; struct token_list* string_list in R11
  2465. ;; struct token_list* global_list in R10
  2466. ;; and struct token_list* FUNC in R9
  2467. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2468. ;; Returns the token_lists modified
  2469. :collect_local
  2470. PUSHR R0 R15 ; Protect R0
  2471. PUSHR R1 R15 ; Protect R1
  2472. PUSHR R2 R15 ; Protect R2
  2473. CALLI R15 @type_name ; Get it's type
  2474. MOVE R1 R0 ; Prepare for call
  2475. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2476. LOAD32 R2 R9 4 ; FUNC->LOCALS
  2477. CALLI R15 @sym_declare ; SET A
  2478. MOVE R2 R0 ; Protect A
  2479. ;; Figure out depth
  2480. LOADUI R0 $main_string ; Using "main"
  2481. LOAD32 R1 R9 8 ; FUNC->S
  2482. CALLI R15 @match ; IF FUNC->S == "main"
  2483. JUMP.Z R0 @collect_local_0 ; Try next
  2484. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2485. JUMP.NZ R0 @collect_local_0 ; Try next
  2486. LOADI R0 4 ; The default depth for main
  2487. STORE32 R0 R2 16 ; A->DEPTH = 4
  2488. JUMP @collect_local_output ; Deal with header
  2489. :collect_local_0
  2490. LOAD32 R0 R9 16 ; FUNC->ARGS
  2491. JUMP.NZ R0 @collect_local_1 ; Try Next
  2492. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2493. JUMP.NZ R0 @collect_local_1 ; Try Next
  2494. LOADI R0 4 ; The default depth for foo()
  2495. STORE32 R0 R2 16 ; A->DEPTH = 4
  2496. JUMP @collect_local_output ; Deal with header
  2497. :collect_local_1
  2498. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2499. JUMP.NZ R0 @collect_local_2 ; Try Next
  2500. LOAD32 R0 R9 16 ; FUNC->ARGS
  2501. LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
  2502. ADDI R0 R0 8 ; DEPTH = FUNC->ARGS->DEPTH + 8
  2503. STORE32 R0 R2 16 ; A->DEPTH = DEPTH
  2504. JUMP @collect_local_output ; Deal with header
  2505. :collect_local_2
  2506. LOAD32 R0 R9 4 ; FUNC->LOCALS
  2507. LOAD32 R0 R0 16 ; FUNC->LOCALS->DEPTH
  2508. ADDI R0 R0 4 ; DEPTH = FUNC->LOCALS->DEPTH + 4
  2509. STORE32 R0 R2 16 ; A->DEPTH = DEPTH
  2510. :collect_local_output
  2511. STORE32 R2 R9 4 ; FUNC->LOCALS = A
  2512. ;; Output header
  2513. LOADUI R0 $collect_local_string0 ; Starting with the comment
  2514. CALLI R15 @emit_out ; emit it
  2515. LOAD32 R0 R2 8 ; A->S
  2516. CALLI R15 @emit_out ; emit it
  2517. LOADUI R0 $newline ; Using "\n"
  2518. CALLI R15 @emit_out ; emit it
  2519. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2520. ;; Deal with possible assignment
  2521. LOADUI R0 $equal ; Using "="
  2522. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2523. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
  2524. JUMP.Z R0 @collect_local_nonassign
  2525. ;; Deal with assignment of the local
  2526. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2527. CALLI R15 @expression ; Update OUT with the evaluation of the Expression
  2528. :collect_local_nonassign
  2529. LOADUI R0 $collect_local_string1 ; Our error message
  2530. LOADUI R1 $semicolon ; Using ";"
  2531. CALLI R15 @require_match ; Make sure GLOBAL_TOKEN->S == ";"
  2532. ;; Final Footer
  2533. LOADUI R0 $collect_local_string2 ; Add our PUSH statement
  2534. CALLI R15 @emit_out ; emit it
  2535. LOAD32 R0 R2 8 ; A->S
  2536. CALLI R15 @emit_out ; emit it
  2537. LOADUI R0 $newline ; Using "\n"
  2538. CALLI R15 @emit_out ; emit it
  2539. POPR R2 R15 ; Restore R2
  2540. POPR R1 R15 ; Restore R1
  2541. POPR R0 R15 ; Restore R0
  2542. RET R15
  2543. :collect_local_string0
  2544. "# Defining local "
  2545. :collect_local_string1
  2546. "ERROR in collect_local
  2547. Missing ;
  2548. "
  2549. :collect_local_string2
  2550. "PUSHR R0 R15 #"
  2551. ;; collect_arguments function
  2552. ;; Receives struct token_list* global_token in R13,
  2553. ;; struct token_list* out in R12,
  2554. ;; struct token_list* string_list in R11
  2555. ;; struct token_list* global_list in R10
  2556. ;; and struct token_list* FUNC in R9
  2557. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2558. ;; Returns the token_lists modified
  2559. :collect_arguments
  2560. PUSHR R0 R15 ; Protect R0
  2561. PUSHR R1 R15 ; Protect R1
  2562. PUSHR R2 R15 ; Protect R2
  2563. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2564. :collect_arguments_iter
  2565. LOADUI R0 $close_paren ; Using ")"
  2566. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2567. CALLI R15 @match ; IF GLOBAL_TOKEN->S == ")"
  2568. JUMP.NZ R0 @collect_arguments_done ; Be done
  2569. ;; Collect the arguments
  2570. CALLI R15 @type_name ; Get what type we are working with
  2571. MOVE R1 R0 ; Put TYPE where it will be used
  2572. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2573. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2574. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ')'
  2575. JUMP @collect_arguments_iter3 ; foo(int,char,void) doesn't need anything done
  2576. ;; Check for foo(int a,...)
  2577. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ','
  2578. JUMP @collect_arguments_iter3 ; Looks like final case
  2579. ;; Deal with foo(int a, ...)
  2580. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2581. LOAD32 R2 R9 16 ; FUNC->ARGUMENTS
  2582. CALLI R15 @sym_declare ; Get A
  2583. MOVE R2 R0 ; Get A out of the way
  2584. :collect_arguments_func
  2585. LOAD32 R0 R9 16 ; FUNC->ARGS
  2586. JUMP.Z R0 @collect_arguments_func_0 ; IF NULL == FUNC->ARGS then FUNC->ARGS->DEPTH = 0
  2587. LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
  2588. ADDI R0 R0 4 ; FUNC->ARGS->DEPTH + 4
  2589. :collect_arguments_func_0
  2590. STORE32 R0 R2 16 ; A->DEPTH = VALUE
  2591. :collect_arguments_iter2
  2592. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2593. STORE32 R2 R9 16 ; FUNC->ARGUMENTS = A
  2594. :collect_arguments_iter3
  2595. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2596. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2597. CMPSKIPI.NE R0 44 ; IF GLOBAL_TOKEN->S[0] == ','
  2598. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2599. JUMP @collect_arguments_iter ; Keep looping
  2600. :collect_arguments_done
  2601. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2602. POPR R2 R15 ; Restore R2
  2603. POPR R1 R15 ; Restore R1
  2604. POPR R0 R15 ; Restore R0
  2605. RET R15
  2606. ;; declare_function function
  2607. ;; Receives struct token_list* global_token in R13,
  2608. ;; struct token_list* out in R12,
  2609. ;; struct token_list* string_list in R11
  2610. ;; and struct token_list* global_list in R10
  2611. ;; SETS R9 to struct token_list* FUNC
  2612. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2613. ;; Returns the token_lists modified
  2614. :declare_function
  2615. PUSHR R0 R15 ; Protect R0
  2616. PUSHR R1 R15 ; Protect R1
  2617. PUSHR R2 R15 ; Protect R2
  2618. FALSE R0 ; Using Zero
  2619. STORER32 R0 @current_count ; CURRENT_COUNT = 0
  2620. LOAD32 R0 R13 4 ; GLOBAL_TOKEN->PREV
  2621. LOAD32 R0 R0 8 ; GLOBAL_TOKEN->PREV->S
  2622. FALSE R1 ; Passing NULL
  2623. LOADR32 R2 @global_function_list ; where the global function list is located
  2624. CALLI R15 @sym_declare ; declare FUNC
  2625. STORER32 R0 @global_function_list ; GLOBAL_FUNCTION_LIST = FUNC
  2626. MOVE R9 R0 ; SETS FUNC
  2627. CALLI R15 @collect_arguments ; Collect function arguments
  2628. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  2629. LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
  2630. CMPSKIPI.NE R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
  2631. JUMP @declare_function_prototype ; Don't waste time
  2632. ;; Looks like it is an actual function definition
  2633. LOADUI R0 $declare_function_string0 ; Using first string
  2634. CALLI R15 @emit_out ; emit it
  2635. LOAD32 R0 R9 8 ; Using FUNC->S
  2636. CALLI R15 @emit_out ; emit it
  2637. LOADUI R0 $newline ; Using "\n"
  2638. CALLI R15 @emit_out ; emit it
  2639. LOADUI R0 $declare_function_string1 ; Using second string
  2640. CALLI R15 @emit_out ; emit it
  2641. LOAD32 R0 R9 8 ; Using FUNC->S
  2642. CALLI R15 @emit_out ; emit it
  2643. LOADUI R0 $newline ; Using "\n"
  2644. CALLI R15 @emit_out ; emit it
  2645. :declare_function_nonmain
  2646. FALSE R1 ; Cleaning up before call
  2647. CALLI R15 @statement ; Collect the statement
  2648. ;; Prevent Duplicate Returns
  2649. LOAD32 R1 R12 8 ; OUT->S
  2650. LOADUI R0 $declare_function_string2 ; Our final string
  2651. CALLI R15 @match ; Check for Match
  2652. JUMP.NZ R0 @declare_function_done ; Clean up
  2653. ;; Deal with adding the return
  2654. LOADUI R0 $declare_function_string2 ; Our final string
  2655. CALLI R15 @emit_out ; emit it
  2656. :declare_function_done
  2657. POPR R2 R15 ; Restore R2
  2658. POPR R1 R15 ; Restore R1
  2659. POPR R0 R15 ; Restore R0
  2660. RET R15
  2661. :declare_function_prototype
  2662. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2663. JUMP @declare_function_done ; Clean up
  2664. :declare_function_string0
  2665. "# Defining function "
  2666. :declare_function_string1
  2667. ":FUNCTION_"
  2668. :declare_function_string2
  2669. "RET R15
  2670. "
  2671. :current_count
  2672. NOP
  2673. ;; program function
  2674. ;; Receives struct token_list* global_token in R13,
  2675. ;; struct token_list* out in R12,
  2676. ;; struct token_list* string_list in R11
  2677. ;; and struct token_list* global_list in R10
  2678. ;; and struct token_list* FUNC in R9
  2679. ;; and struct token_list* current_target in R8
  2680. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2681. ;; Returns the token_lists modified
  2682. :program
  2683. PUSHR R0 R15 ; Protect R0
  2684. PUSHR R1 R15 ; Protect R1
  2685. PUSHR R2 R15 ; Protect R2
  2686. PUSHR R3 R15 ; Protect R3
  2687. :program_iter
  2688. JUMP.Z R13 @program_done ; Looks like we read all the tokens
  2689. LOADUI R0 $constant ; Using the constant string
  2690. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2691. CALLI R15 @match ; Check if they match
  2692. JUMP.Z R0 @program_type ; Looks like not
  2693. ;; Deal with CONSTANT case
  2694. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2695. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2696. FALSE R1 ; Set NULL
  2697. LOADR32 R2 @global_constant_list ; GLOBAL_CONSTANTS_LIST
  2698. CALLI R15 @sym_declare ; Declare the global constant
  2699. STORER32 R0 @global_constant_list ; Update global constant
  2700. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2701. STORE32 R13 R0 16 ; GLOBAL_CONSTANT_LIST->ARGUMENTS = GLOBAL_TOKEN
  2702. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2703. JUMP @program_iter ; Loop again
  2704. :program_type
  2705. CALLI R15 @type_name ; Get the type
  2706. JUMP.Z R0 @program_iter ; If newly defined type iterate
  2707. ;; Looks like we got a defined type
  2708. MOVE R1 R0 ; Put the type where it can be used
  2709. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2710. LOADUI R3 $global_symbol_list ; Get address of global symbol list
  2711. LOAD32 R2 R3 0 ; GLOBAL_SYMBOLS_LIST
  2712. CALLI R15 @sym_declare ; Declare that global symbol
  2713. STORE32 R0 R3 0 ; Update global symbol list
  2714. LOAD32 R3 R13 8 ; GLOBAL_TOKEN->S
  2715. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2716. LOADUI R0 $semicolon ; Get semicolon string
  2717. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  2718. CALLI R15 @match ; Check if they match
  2719. JUMP.Z R0 @program_function ; If not a match
  2720. ;; Deal with case of TYPE NAME;
  2721. COPY R1 R10 ; Using GLOBALS_LIST
  2722. LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
  2723. CALLI R15 @emit ; emit it
  2724. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2725. MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
  2726. CALLI R15 @emit ; emit it
  2727. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2728. LOADUI R0 $program_string1 ; Using the NOP postfix
  2729. CALLI R15 @emit ; emit it
  2730. MOVE R10 R0 ; Move new GLOBALS_LIST into Place
  2731. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2732. JUMP @program_iter
  2733. :program_function
  2734. LOADUI R0 $open_paren ; Get open paren string
  2735. CALLI R15 @match ; Check if they match
  2736. JUMP.Z R0 @program_assign ; If not a match
  2737. ;; Deal with case of TYPE NAME(...)
  2738. CALLI R15 @declare_function
  2739. JUMP @program_iter
  2740. :program_assign
  2741. LOADUI R0 $equal ; Get equal string
  2742. CALLI R15 @match ; Check if they match
  2743. JUMP.Z R0 @program_error ; If not a match
  2744. COPY R1 R10 ; Using GLOBALS_LIST
  2745. LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
  2746. CALLI R15 @emit ; emit it
  2747. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2748. MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
  2749. CALLI R15 @emit ; emit it
  2750. MOVE R1 R0 ; Move new GLOBALS_LIST into Place
  2751. LOADUI R0 $newline ; Using the Newline postfix
  2752. CALLI R15 @emit ; emit it
  2753. MOVE R10 R0 ; Update GLOBALS_LIST
  2754. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2755. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2756. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2757. LOADUI R1 $digit_chars ; 0-9
  2758. CALLI R15 @in_set ; Figure out if in set
  2759. JUMP.Z R0 @program_assign_string ; If not in sets
  2760. ;; Looks like we have an int
  2761. COPY R1 R10 ; Using GLOBALS_LIST
  2762. LOADUI R0 $percent ; Using percent prefix
  2763. CALLI R15 @emit ; emit it
  2764. MOVE R1 R0 ; Put GLOBALS_LIST into Place
  2765. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2766. CALLI R15 @emit ; emit it
  2767. MOVE R1 R0 ; Put GLOBALS_LIST into Place
  2768. LOADUI R0 $newline ; Using newline postfix
  2769. CALLI R15 @emit ; emit it
  2770. MOVE R10 R0 ; Update GLOBALS_LIST
  2771. JUMP @program_assign_done ; Move on
  2772. :program_assign_string
  2773. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2774. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2775. CMPSKIPI.E R0 34 ; If GLOBAL_TOKEN->S[0] == '"'
  2776. JUMP @program_error ; If not we hit an error
  2777. ;; Looks like we have a string
  2778. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2779. CALLI R15 @parse_string ; Parse it into useful form
  2780. COPY R1 R10 ; GLOBALS_LIST
  2781. CALLI R15 @emit ; emit it
  2782. MOVE R10 R0 ; Update GLOBALS_LIST
  2783. :program_assign_done
  2784. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2785. LOADUI R0 $program_string4 ; Potential error message
  2786. LOADUI R1 $semicolon ; Checking for ;
  2787. CALLI R15 @require_match ; Catch those errors
  2788. JUMP @program_iter
  2789. :program_error
  2790. LOADUI R0 $program_string2 ; message part 1
  2791. FALSE R1 ; Show to user
  2792. CALLI R15 @file_print ; write
  2793. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2794. CALLI R15 @file_print ; write
  2795. LOADUI R0 $program_string3 ; message part 2
  2796. CALLI R15 @file_print ; write
  2797. CALLI R15 @line_error ; Provide a meaningful error message
  2798. HALT
  2799. :program_done
  2800. POPR R3 R15 ; Restore R3
  2801. POPR R2 R15 ; Restore R2
  2802. POPR R1 R15 ; Restore R1
  2803. POPR R0 R15 ; Restore R0
  2804. RET R15
  2805. :program_string0
  2806. ":GLOBAL_"
  2807. :program_string1
  2808. "
  2809. NULL
  2810. "
  2811. :program_string2
  2812. "Received "
  2813. :program_string3
  2814. " in program
  2815. "
  2816. :program_string4
  2817. "ERROR in Program
  2818. Missing ;
  2819. "
  2820. ;; sym_declare function
  2821. ;; Receives char* in R0, struct type* in R1, struct token_list* in R2
  2822. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2823. ;; Returns struct token_list* in R0
  2824. :sym_declare
  2825. STORE32 R2 R14 0 ; A->NEXT = LIST
  2826. STORE32 R0 R14 8 ; A->S = S
  2827. STORE32 R1 R14 12 ; A->TYPE = T
  2828. ADDUI R0 R14 20 ; CALLOC struct token_list
  2829. SWAP R0 R14 ; Prepare for Return
  2830. RET R15
  2831. ;; sym_lookup function
  2832. ;; Receives char* in R0 and struct token_list in R1
  2833. ;; Returns struct token_list* or NULL in R0
  2834. :sym_lookup
  2835. PUSHR R2 R15 ; Protect R2
  2836. MOVE R2 R1 ; Protect I
  2837. MOVE R1 R0 ; Put S in proper place
  2838. :sym_lookup_iter
  2839. JUMP.Z R2 @sym_lookup_done ; Stop if NULL
  2840. LOAD32 R0 R2 8 ; I->S
  2841. CALLI R15 @match ; if I->S == S
  2842. JUMP.NZ R0 @sym_lookup_done ; Stop if match
  2843. LOAD32 R2 R2 0 ; I = I->NEXT
  2844. JUMP @sym_lookup_iter ; Keep looping
  2845. :sym_lookup_done
  2846. MOVE R0 R2 ; Using R2 as our result
  2847. POPR R2 R15 ; Restore R2
  2848. RET R15
  2849. ;; function_call function
  2850. ;; Receives CHAR* S in R0 and INT BOOL in R1
  2851. ;; struct token_list* out in R12,
  2852. ;; struct token_list* string_list in R11
  2853. ;; and struct token_list* global_list in R10
  2854. ;; and struct token_list* FUNC in R9
  2855. ;; and struct token_list* current_target in R8
  2856. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2857. ;; Returns the token_lists modified
  2858. :function_call
  2859. PUSHR R0 R15 ; Protect R0
  2860. PUSHR R1 R15 ; Protect R1
  2861. PUSHR R2 R15 ; Protect R2
  2862. PUSHR R3 R15 ; Protect R3
  2863. PUSHR R4 R15 ; Protect R4
  2864. MOVE R2 R0 ; Protect S
  2865. MOVE R3 R1 ; Protect BOOL
  2866. LOADUI R0 $function_call_string0 ; Our first error message
  2867. LOADUI R1 $open_paren ; Using "("
  2868. CALLI R15 @require_match ; Make sure of a match
  2869. FALSE R4 ; PASSED = 0
  2870. LOADUI R0 $function_call_string1 ; Our first header
  2871. CALLI R15 @emit_out ; emit it
  2872. LOADUI R0 $function_call_string2 ; Our second header
  2873. CALLI R15 @emit_out ; emit it
  2874. LOADUI R0 $function_call_string3 ; Our third header
  2875. CALLI R15 @emit_out ; emit it
  2876. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2877. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2878. CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] != ')'
  2879. JUMP @function_call_collect_done ; looks like function()
  2880. ;; Collect arguments
  2881. CALLI R15 @expression ; Deal with first argument
  2882. LOADUI R0 $function_call_string4 ; Push it onto stack
  2883. CALLI R15 @emit_out ; emit it
  2884. ADDUI R4 R4 1 ; PASSED = 1
  2885. :function_call_collect_iter
  2886. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  2887. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  2888. CMPSKIPI.E R0 44 ; IF GLOBAL_TOKEN->S[0] != ','
  2889. JUMP @function_call_collect_done ; looks like we are done collecting arguments
  2890. ;; Collect another argument
  2891. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  2892. CALLI R15 @expression ; Deal with Nth argument
  2893. LOADUI R0 $function_call_string5 ; Push it onto stack
  2894. CALLI R15 @emit_out ; emit it
  2895. ADDUI R4 R4 1 ; PASSED = PASSED + 1
  2896. JUMP @function_call_collect_iter ; Keep looping
  2897. :function_call_collect_done
  2898. LOADUI R0 $function_call_string6 ; Our second error message
  2899. LOADUI R1 $close_paren ; Using ")"
  2900. CALLI R15 @require_match ; Make sure of a match
  2901. JUMP.Z R3 @function_call_call_false ; if BOOL != TRUE
  2902. ;; Deal with TRUE == BOOL
  2903. LOADUI R0 $function_call_string7 ; Our first prefix
  2904. CALLI R15 @emit_out ; emit it
  2905. MOVE R0 R2 ; Using S
  2906. CALLI R15 @emit_out ; emit it
  2907. LOADUI R0 $function_call_string8 ; Our first postfix
  2908. CALLI R15 @emit_out ; emit it
  2909. LOADUI R0 $function_call_string9 ; Our second postfix
  2910. CALLI R15 @emit_out ; emit it
  2911. LOADUI R0 $function_call_string10 ; Our last postfix
  2912. CALLI R15 @emit_out ; emit it
  2913. JUMP @function_call_call_done ; Move on
  2914. :function_call_call_false
  2915. ;; Deal with FALSE == BOOL
  2916. LOADUI R0 $function_call_string11 ; Our first prefix
  2917. CALLI R15 @emit_out ; emit it
  2918. LOADUI R0 $function_call_string12 ; Our last prefix
  2919. CALLI R15 @emit_out ; emit it
  2920. MOVE R0 R2 ; Using S
  2921. CALLI R15 @emit_out ; emit it
  2922. LOADUI R0 $function_call_string16 ; The terminator
  2923. CALLI R15 @emit_out ; emit it
  2924. :function_call_call_done
  2925. LOADUI R0 $function_call_string13 ; Our POP
  2926. :function_call_pop_iter
  2927. JUMP.Z R4 @function_call_pop_done ; Skip POP if out of args on Stack
  2928. CALLI R15 @emit_out ; emit our POP
  2929. SUBI R4 R4 1 ; PASSED = PASSED - 1
  2930. JUMP @function_call_pop_iter ; Loop
  2931. :function_call_pop_done
  2932. LOADUI R0 $function_call_string14 ; Our first postfix
  2933. CALLI R15 @emit_out ; emit it
  2934. LOADUI R0 $function_call_string15 ; Our final postfix
  2935. CALLI R15 @emit_out ; emit it
  2936. POPR R4 R15 ; Restore R4
  2937. POPR R3 R15 ; Restore R3
  2938. POPR R2 R15 ; Restore R2
  2939. POPR R1 R15 ; Restore R1
  2940. POPR R0 R15 ; Restore R0
  2941. RET R15
  2942. :function_call_string0
  2943. "ERROR in process_expression_list
  2944. No ( was found
  2945. "
  2946. :function_call_string1
  2947. "PUSHR R13 R15 # Prevent overwriting in recursion
  2948. "
  2949. :function_call_string2
  2950. "PUSHR R14 R15 # Protect the old base pointer
  2951. "
  2952. :function_call_string3
  2953. "COPY R13 R15 # Copy new base pointer
  2954. "
  2955. :function_call_string4
  2956. "PUSHR R0 R15 #_process_expression1
  2957. "
  2958. :function_call_string5
  2959. "PUSHR R0 R15 #_process_expression2
  2960. "
  2961. :function_call_string6
  2962. "ERROR in process_expression_list
  2963. No ) was found
  2964. "
  2965. :function_call_string7
  2966. "LOAD R0 R14 "
  2967. :function_call_string8
  2968. "
  2969. "
  2970. :function_call_string9
  2971. "MOVE R14 R13
  2972. "
  2973. :function_call_string10
  2974. "CALL R0 R15
  2975. "
  2976. :function_call_string11
  2977. "MOVE R14 R13
  2978. "
  2979. :function_call_string12
  2980. "LOADR R0 4
  2981. JUMP 4
  2982. &FUNCTION_"
  2983. :function_call_string13
  2984. "POPR R1 R15 # _process_expression_locals
  2985. "
  2986. :function_call_string14
  2987. "POPR R14 R15 # Restore old base pointer
  2988. "
  2989. :function_call_string15
  2990. "POPR R13 R15 # Prevent overwrite
  2991. "
  2992. :function_call_string16
  2993. "
  2994. CALL R0 R15
  2995. "
  2996. ;; emit function
  2997. ;; Receives char* in R0, struct token_list* in R1
  2998. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  2999. ;; Returns struct token_list* in R0
  3000. :emit
  3001. PUSHR R2 R15 ; Protect R2
  3002. COPY R2 R14 ; Pointer to T
  3003. ADDUI R14 R14 20 ; CALLOC struct token_list
  3004. STORE32 R1 R2 0 ; T->NEXT = HEAD
  3005. STORE32 R0 R2 8 ; T->S = S
  3006. MOVE R0 R2 ; Put T in proper spot for return
  3007. POPR R2 R15 ; Restore R2
  3008. RET R15
  3009. ;; emit_out function
  3010. ;; Receives char* in R0
  3011. ;; struct token_list* out in R12,
  3012. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3013. ;; Returns struct token_list* in R0
  3014. :emit_out
  3015. STORE32 R12 R14 0 ; T->NEXT = OUT
  3016. ADDUI R12 R14 20 ; Get T
  3017. SWAP R12 R14 ; CALLOC struct token_list
  3018. STORE32 R0 R12 8 ; T->S = S
  3019. RET R15
  3020. ;; uniqueID function
  3021. ;; Receives char* in R0, struct token_list* in R1 and char* in R2
  3022. ;; Calls emit repeatedly
  3023. ;; Returns struct token_list* in R0
  3024. :uniqueID
  3025. CALLI R15 @emit ; emit S
  3026. MOVE R1 R0 ; Put L in the correct place
  3027. LOADUI R0 $underline ; Using "_"
  3028. CALLI R15 @emit ; emit it
  3029. MOVE R1 R0 ; Put L in the correct place
  3030. COPY R0 R2 ; Put NUM in the correct place
  3031. CALLI R15 @emit ; emit NUM
  3032. MOVE R1 R0 ; Put L in the correct place
  3033. LOADUI R0 $newline ; Using "\n"
  3034. CALLI R15 @emit ; emit it
  3035. RET R15
  3036. ;; uniqueID_out function
  3037. ;; Receives char* in R0, char* in R1
  3038. ;; Calls emit_out repeatedly
  3039. ;; Returns nothing
  3040. :uniqueID_out
  3041. CALLI R15 @emit_out ; emit S
  3042. LOADUI R0 $underline ; Using "_"
  3043. CALLI R15 @emit_out ; emit it
  3044. COPY R0 R1 ; Put NUM in the correct place
  3045. CALLI R15 @emit_out ; emit NUM
  3046. LOADUI R0 $newline ; Using "\n"
  3047. CALLI R15 @emit_out ; emit it
  3048. RET R15
  3049. ;; file_print function
  3050. ;; Receives pointer to string in R0 and FILE* in R1
  3051. ;; Returns nothing
  3052. :file_print
  3053. PUSHR R2 R15 ; Protect R2 from Overwrite
  3054. MOVE R2 R0 ; Put string pointer into place
  3055. :file_print_read
  3056. LOAD8 R0 R2 0 ; Get a char
  3057. JUMP.Z R0 @file_print_done ; If NULL be done
  3058. FPUTC ; Write the Char
  3059. ADDUI R2 R2 1 ; Point at next CHAR
  3060. JUMP @file_print_read ; Loop again
  3061. :file_print_done
  3062. POPR R2 R15 ; Restore R2
  3063. RET R15
  3064. ;; recursive_output function
  3065. ;; Receives token_list in R0 and FILE* in R1
  3066. ;; Returns nothing and alters nothing
  3067. :recursive_output
  3068. JUMP.Z R0 @recursive_output_abort ; Abort if NULL
  3069. PUSHR R2 R15 ; Preserve R2 from recursion
  3070. MOVE R2 R0 ; Preserve R0 from recursion
  3071. LOAD32 R0 R2 0 ; Using I->NEXT
  3072. CALLI R15 @recursive_output ; Recurse
  3073. LOAD32 R0 R2 8 ; Using I->S
  3074. CALLI R15 @file_print ; Write the string
  3075. MOVE R0 R2 ; Put R0 back
  3076. POPR R2 R15 ; Restore R0
  3077. :recursive_output_abort
  3078. RET R15
  3079. ;; match function
  3080. ;; Receives a CHAR* in R0, CHAR* in R1
  3081. ;; Returns Bool in R0 indicating if strings match
  3082. :match
  3083. PUSHR R1 R15 ; Protect R1
  3084. PUSHR R2 R15 ; Protect R2
  3085. PUSHR R3 R15 ; Protect R3
  3086. PUSHR R4 R15 ; Protect R4
  3087. MOVE R2 R0 ; Put First string in place
  3088. MOVE R3 R1 ; Put Second string in place
  3089. LOADUI R4 0 ; Set initial index of 0
  3090. :match_cmpbyte
  3091. LOADXU8 R0 R2 R4 ; Get a byte of our first string
  3092. LOADXU8 R1 R3 R4 ; Get a byte of our second string
  3093. ADDUI R4 R4 1 ; Prep for next loop
  3094. CMPSKIP.NE R1 R0 ; Compare the bytes
  3095. JUMP.NZ R1 @match_cmpbyte ; Loop if bytes are equal
  3096. ;; Done
  3097. FALSE R2 ; Default answer
  3098. CMPSKIP.NE R0 R1 ; If ended loop with everything matching
  3099. TRUE R2 ; Set as TRUE
  3100. MOVE R0 R2 ; Prepare for return
  3101. POPR R4 R15 ; Restore R4
  3102. POPR R3 R15 ; Restore R3
  3103. POPR R2 R15 ; Restore R2
  3104. POPR R1 R15 ; Restore R1
  3105. RET R15
  3106. ;; lookup_type function
  3107. ;; Receives a CHAR* in R0 and struct type* in R1
  3108. ;; Returns struct type* in R0 or NULL if no match
  3109. :lookup_type
  3110. PUSHR R1 R15 ; Protect R1
  3111. PUSHR R2 R15 ; Protect R2
  3112. MOVE R2 R1 ; Put START in correct place
  3113. MOVE R1 R0 ; Put S in correct place
  3114. :lookup_type_iter
  3115. LOAD32 R0 R2 24 ; Get I->NAME
  3116. CALLI R15 @match ; Check if I->NAME == S
  3117. JUMP.NZ R0 @lookup_type_done ; If match found be done
  3118. LOAD32 R2 R2 0 ; I = I->NEXT
  3119. JUMP.NZ R2 @lookup_type_iter ; Otherwise iterate until I == NULL
  3120. :lookup_type_done
  3121. MOVE R0 R2 ; Our answer (I or NULL)
  3122. POPR R2 R15 ; Restore R2
  3123. POPR R1 R15 ; Restore R1
  3124. RET R15
  3125. ;; lookup_member function
  3126. ;; Receives struct type* parent in R0 and char* name in R1
  3127. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3128. ;; Returns struct type* of member in R0 or aborts with error
  3129. :lookup_member
  3130. PUSHR R1 R15 ; Protect R1
  3131. PUSHR R2 R15 ; Protect R2
  3132. PUSHR R3 R15 ; Protect R3
  3133. LOAD32 R3 R0 24 ; PARENT->NAME for error
  3134. MOVE R2 R0 ; I = PARENT
  3135. :lookup_member_iter
  3136. LOAD32 R2 R2 16 ; I = I->MEMBERS
  3137. JUMP.Z R2 @lookup_member_error ; We failed hard
  3138. LOAD32 R0 R2 24 ; I->NAME
  3139. CALLI R15 @match ; IF I->NAME == NAME
  3140. JUMP.Z R0 @lookup_member_iter ; Loop again
  3141. :lookup_member_done
  3142. MOVE R0 R2 ; Put I in the correct place
  3143. POPR R3 R15 ; Restore R3
  3144. POPR R2 R15 ; Restore R2
  3145. POPR R1 R15 ; Restore R1
  3146. RET R15
  3147. :lookup_member_error
  3148. FALSE R1 ; Write to TTY
  3149. LOADUI R0 $lookup_member_string0 ; Our header string
  3150. CALLI R15 @file_print ; Print it
  3151. MOVE R0 R3 ; Using PARENT->NAME
  3152. CALLI R15 @file_print ; Print it
  3153. LOADUI R0 $arrow_string ; Using "->"
  3154. CALLI R15 @file_print ; Print it
  3155. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3156. CALLI R15 @file_print ; Print it
  3157. LOADUI R0 $lookup_member_string1 ; Our footer string
  3158. CALLI R15 @file_print ; Print it
  3159. CALLI R15 @line_error ; Give line info
  3160. LOADUI R0 $newline ; Our final addition
  3161. CALLI R15 @file_print ; Print it
  3162. HALT
  3163. :lookup_member_string0
  3164. "ERROR in lookup_member "
  3165. :lookup_member_string1
  3166. " does not exist
  3167. "
  3168. ;; build_member function
  3169. ;; Receives a struct type* in R0, int in R1 and int in R2
  3170. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3171. ;; Modifies R2 to current member_size
  3172. ;; Returns struct type* in R0
  3173. :build_member
  3174. PUSHR R3 R15 ; Protect R3
  3175. PUSHR R4 R15 ; Protect R4
  3176. PUSHR R5 R15 ; Protect R5
  3177. PUSHR R6 R15 ; Protect R6
  3178. MOVE R6 R1 ; Protect OFFSET
  3179. MOVE R4 R0 ; Protect LAST
  3180. CALLI R15 @type_name ; Get MEMBER_TYPE
  3181. MOVE R5 R0 ; Protect MEMBER_TYPE
  3182. ADDUI R3 R14 28 ; CALLOC struct type
  3183. SWAP R3 R14 ; SET I
  3184. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3185. STORE32 R0 R3 24 ; I->NAME = GLOBAL_TOKEN->S
  3186. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3187. STORE32 R4 R3 16 ; I->MEMBERS = LAST
  3188. LOADUI R0 $open_bracket ; Using "["
  3189. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3190. CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
  3191. JUMP.Z R0 @build_member_single
  3192. ;; Deal with type name [ number ] ;
  3193. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3194. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3195. CALLI R15 @numerate_string ; Convert string to int NUMBER
  3196. LOAD32 R1 R5 20 ; MEMBER_TYPE->TYPE
  3197. LOAD32 R1 R1 4 ; MEMBER_TYPE->TYPE->SIZE
  3198. MULU R0 R0 R1 ; MEMBER_TYPE->TYPE->SIZE * NUMBER
  3199. STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->TYPE->SIZE * NUMBER
  3200. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3201. LOADUI R0 $build_member_string0 ; Our error message
  3202. LOADUI R1 $close_bracket ; Using "]"
  3203. CALLI R15 @require_match ; Make sure it is right
  3204. JUMP @build_member_done ; Skip over single steps
  3205. :build_member_single
  3206. LOAD32 R0 R5 4 ; MEMBER_TYPE->SIZE
  3207. STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->SIZE
  3208. :build_member_done
  3209. LOAD32 R2 R3 4 ; MEMBER_SIZE = I->SIZE
  3210. STORE32 R5 R3 20 ; I->TYPE = MEMBER_TYPE
  3211. STORE32 R6 R3 8 ; I->OFFSET = OFFSET
  3212. MOVE R1 R6 ; Restore OFFSET
  3213. MOVE R0 R3 ; RETURN I in R0
  3214. POPR R6 R15 ; Restore R6
  3215. POPR R5 R15 ; Restore R5
  3216. POPR R4 R15 ; Restore R4
  3217. POPR R3 R15 ; Restore R3
  3218. RET R15
  3219. :build_member_string0
  3220. "Struct only supports [num] form
  3221. "
  3222. ;; build_union function
  3223. ;; Receives a struct type* in R0, int in R1 and int in R2
  3224. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3225. ;; Modifies R2 to current member_size
  3226. ;; Returns struct type* in R0
  3227. :build_union
  3228. PUSHR R3 R15 ; Protect R3
  3229. PUSHR R4 R15 ; Protect R4
  3230. PUSHR R5 R15 ; Protect R5
  3231. MOVE R4 R0 ; Protect LAST
  3232. MOVE R3 R1 ; Protect OFFSET
  3233. FALSE R5 ; SIZE = 0
  3234. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3235. LOADUI R0 $build_union_string0 ; ERROR MESSAGE
  3236. LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
  3237. CALLI R15 @require_match ; Ensure we have that curly brace
  3238. :build_union_iter
  3239. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3240. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  3241. LOADUI R1 125 ; numerical value of }
  3242. CMPJUMPI.E R0 R1 @build_union_done ; No more looping required
  3243. MOVE R0 R4 ; We are passing last to be overwritten
  3244. MOVE R1 R3 ; We are also passing OFFSET
  3245. CALLI R15 @build_member ; To build_member to get new LAST and new member_size
  3246. CMPSKIP.LE R2 R5 ; If MEMBER_SIZE > SIZE
  3247. COPY R5 R2 ; SIZE = MEMMER_SIZE
  3248. MOVE R4 R0 ; Protect LAST
  3249. MOVE R3 R1 ; Protect OFFSET
  3250. LOADUI R0 $build_union_string1 ; ERROR MESSAGE
  3251. LOADUI R1 $semicolon ; SEMICOLON
  3252. CALLI R15 @require_match ; Ensure we have that curly brace
  3253. JUMP @build_union_iter ; Loop until we get that closing curly brace
  3254. :build_union_done
  3255. MOVE R2 R5 ; Setting MEMBER_SIZE = SIZE
  3256. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3257. MOVE R1 R3 ; Restore OFFSET
  3258. MOVE R0 R4 ; Restore LAST as we are turning that
  3259. POPR R5 R15 ; Restore R5
  3260. POPR R4 R15 ; Restore R4
  3261. POPR R3 R15 ; Restore R3
  3262. RET R15
  3263. :build_union_string0
  3264. "ERROR in build_union
  3265. Missing {
  3266. "
  3267. :build_union_string1
  3268. "ERROR in build_union
  3269. Missing ;
  3270. "
  3271. ;; create_struct function
  3272. ;; Receives Nothing
  3273. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3274. ;; Returns Nothing
  3275. :create_struct
  3276. PUSHR R0 R15 ; Protect R0
  3277. PUSHR R1 R15 ; Protect R1
  3278. PUSHR R2 R15 ; Protect R2
  3279. PUSHR R3 R15 ; Protect R3
  3280. PUSHR R4 R15 ; Protect R4
  3281. PUSHR R5 R15 ; Protect R5
  3282. PUSHR R6 R15 ; Protect R6
  3283. FALSE R5 ; OFFSET = 0
  3284. FALSE R2 ; MEMBER_SIZE = 0
  3285. COPY R3 R14 ; SET HEAD
  3286. ADDUI R14 R14 28 ; CALLOC struct type
  3287. COPY R4 R14 ; SET I
  3288. ADDUI R14 R14 28 ; CALLOC struct type
  3289. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3290. STORE32 R0 R3 24 ; HEAD->NAME = GLOBAL_TOKEN->S
  3291. STORE32 R0 R4 24 ; I->NAME = GLOBAL_TOKEN->S
  3292. STORE32 R4 R3 12 ; HEAD->INDIRECT = I
  3293. STORE32 R3 R4 12 ; I->INDIRECT - HEAD
  3294. LOADR32 R0 @global_types ; Get Address of GLOBAL_TYPES
  3295. STORE R0 R3 0 ; HEAD->NEXT = GLOBAL_TYPES
  3296. STORER32 R3 @global_types ; GLOBAL_TYPES = HEAD
  3297. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3298. LOADUI R0 4 ; Standard Pointer SIZE
  3299. STORE32 R0 R4 4 ; I->SIZE = 4
  3300. LOADUI R0 $create_struct_string0 ; ERROR MESSAGE
  3301. LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
  3302. CALLI R15 @require_match ; Ensure we have that curly brace
  3303. FALSE R6 ; LAST = NULL
  3304. :create_struct_iter
  3305. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3306. LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
  3307. LOADUI R1 125 ; Numerical value of }
  3308. CMPJUMPI.E R0 R1 @create_struct_done ; Stop looping if match
  3309. LOADUI R1 $union ; Pointer to string UNION
  3310. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3311. CALLI R15 @match ; Check if they Match
  3312. SWAP R0 R6 ; Put LAST in place
  3313. MOVE R1 R5 ; Put OFFSET in place
  3314. JUMP.NZ R6 @create_struct_union ; Deal with union case
  3315. ;; Deal with standard member case
  3316. CALLI R15 @build_member ; Sets new LAST and MEMBER_SIZE
  3317. JUMP @create_struct_iter2 ; reset for loop
  3318. :create_struct_union
  3319. CALLI R15 @build_union
  3320. :create_struct_iter2
  3321. ADD R5 R1 R2 ; OFFSET = OFFSET + MEMBER_SIZE
  3322. SWAP R0 R6 ; Put LAST in place
  3323. LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
  3324. LOADUI R1 $semicolon ; SEMICOLON
  3325. CALLI R15 @require_match ; Ensure we have that semicolon
  3326. JUMP @create_struct_iter ; Keep Looping
  3327. :create_struct_done
  3328. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3329. LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
  3330. LOADUI R1 $semicolon ; SEMICOLON
  3331. CALLI R15 @require_match ; Ensure we have that semicolon
  3332. STORE32 R5 R3 4 ; HEAD->SIZE = OFFSET
  3333. STORE32 R6 R3 16 ; HEAD->MEMBERS = LAST
  3334. STORE32 R6 R4 16 ; I->MEMBERS = LAST
  3335. POPR R6 R15 ; Restore R6
  3336. POPR R5 R15 ; Restore R5
  3337. POPR R4 R15 ; Restore R4
  3338. POPR R3 R15 ; Restore R3
  3339. POPR R2 R15 ; Restore R2
  3340. POPR R1 R15 ; Restore R1
  3341. POPR R0 R15 ; Restore R0
  3342. RET R15
  3343. :create_struct_string0
  3344. "ERROR in create_struct
  3345. Missing {
  3346. "
  3347. :create_struct_string1
  3348. "ERROR in create_struct
  3349. Missing ;
  3350. "
  3351. ;; type_name function
  3352. ;; Receives Nothing
  3353. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3354. ;; Returns struct type* in R0
  3355. :type_name
  3356. PUSHR R1 R15 ; Protect R1
  3357. PUSHR R2 R15 ; Protect R2
  3358. LOADUI R0 $struct ; String for struct for comparison
  3359. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3360. CALLI R15 @match ; Check if they match
  3361. CMPSKIPI.E R0 0 ; If STRUCTURE
  3362. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3363. LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
  3364. LOADR32 R1 @global_types ; Check using the GLOBAL TYPES LIST
  3365. SWAP R0 R2 ; Put GLOBAL_TOKEN->S in the right place
  3366. CALLI R15 @lookup_type ; RET = lookup_type(GLOBAL_TOKEN->S)
  3367. MOVE R1 R2 ; Put STRUCTURE in the right place
  3368. CMPSKIP.E R0 R1 ; If RET == NULL and !STRUCTURE
  3369. JUMP @type_name_struct ; Guess not
  3370. ;; Exit with useful error message
  3371. FALSE R1 ; We will want to be writing the error message for the Human
  3372. LOADUI R0 $type_name_string0 ; The first string
  3373. CALLI R15 @file_print ; Display it
  3374. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3375. CALLI R15 @file_print ; Display it
  3376. LOADUI R0 $newline ; Terminating linefeed
  3377. CALLI R15 @file_print ; Display it
  3378. CALLI R15 @line_error ; Give useful debug info
  3379. HALT ; Just exit
  3380. :type_name_struct
  3381. JUMP.NZ R0 @type_name_iter ; If was found
  3382. CALLI R15 @create_struct ; Otherwise create it
  3383. JUMP @type_name_done ; and be done
  3384. :type_name_iter
  3385. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3386. LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
  3387. LOADU8 R1 R1 0 ; GLOBAL_TOKEN->S[0]
  3388. CMPSKIPI.E R1 42 ; if GLOBAL_TOKEN->S[0] == '*'
  3389. JUMP @type_name_done ; Looks like Nope
  3390. LOAD32 R0 R0 12 ; RET = RET->INDIRECT
  3391. JUMP @type_name_iter ; Keep looping
  3392. :type_name_done
  3393. POPR R2 R15 ; Restore R2
  3394. POPR R1 R15 ; Restore R1
  3395. RET R15
  3396. :type_name_string0
  3397. "Unknown type "
  3398. ;; line_error function
  3399. ;; Receives Nothing
  3400. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3401. ;; Returns nothing
  3402. :line_error
  3403. PUSHR R0 R15 ; Protect R0
  3404. PUSHR R1 R15 ; Protect R1
  3405. LOADUI R0 $line_error_string0 ; Our leading string
  3406. FALSE R1 ; We want the user to see
  3407. CALLI R15 @file_print ; Print it
  3408. LOAD32 R0 R13 16 ; GLOBAL_TOKEN->LINENUMBER
  3409. CALLI R15 @numerate_number ; Get a string pointer for number
  3410. CALLI R15 @file_print ; And print it
  3411. POPR R1 R15 ; Restore R1
  3412. POPR R0 R15 ; Restore R0
  3413. RET R15
  3414. :line_error_string0
  3415. "In file: TTY1 On line: "
  3416. ;; require_match function
  3417. ;; Receives char* in R0 and char* in R1
  3418. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3419. ;; Returns Nothing
  3420. :require_match
  3421. PUSHR R0 R15 ; Protect R0
  3422. PUSHR R2 R15 ; Protect R2
  3423. MOVE R2 R0 ; Get MESSAGE out of the way
  3424. LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
  3425. CALLI R15 @match ; Check if GLOBAL_TOKEN->S == REQUIRED
  3426. JUMP.NZ R0 @require_match_done ; Looks like it was a match
  3427. ;; Terminate with an error
  3428. MOVE R0 R2 ; Put MESSAGE in required spot
  3429. FALSE R1 ; We want to write for user
  3430. CALLI R15 @file_print ; Write it
  3431. CALLI R15 @line_error ; And provide some debug info
  3432. HALT ; Then Stop immediately
  3433. :require_match_done
  3434. LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
  3435. POPR R2 R15 ; Restore R2
  3436. POPR R0 R15 ; Restore R0
  3437. RET R15
  3438. ;; numerate_number function
  3439. ;; Receives int in R0
  3440. ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
  3441. ;; Returns pointer to string generated
  3442. :numerate_number
  3443. PUSHR R1 R15 ; Preserve R1
  3444. PUSHR R2 R15 ; Preserve R2
  3445. PUSHR R3 R15 ; Preserve R3
  3446. PUSHR R4 R15 ; Preserve R4
  3447. PUSHR R5 R15 ; Preserve R5
  3448. PUSHR R6 R15 ; Preserve R6
  3449. MOVE R3 R0 ; Move Integer out of the way
  3450. COPY R1 R14 ; Get pointer result
  3451. ADDUI R14 R14 16 ; CALLOC the 16 chars of space
  3452. FALSE R6 ; Set index to 0
  3453. JUMP.Z R3 @numerate_number_ZERO ; Deal with Special case of ZERO
  3454. JUMP.P R3 @numerate_number_Positive
  3455. LOADUI R0 45 ; Using -
  3456. STOREX8 R0 R1 R6 ; write leading -
  3457. ADDUI R6 R6 1 ; Increment by 1
  3458. NOT R3 R3 ; Flip into positive
  3459. ADDUI R3 R3 1 ; Adjust twos
  3460. :numerate_number_Positive
  3461. LOADR R2 @Max_Decimal ; Starting from the Top
  3462. LOADUI R5 10 ; We move down by 10
  3463. FALSE R4 ; Flag leading Zeros
  3464. :numerate_number_0
  3465. DIVIDE R0 R3 R3 R2 ; Break off top 10
  3466. CMPSKIPI.E R0 0 ; If Not Zero
  3467. TRUE R4 ; Flip the Flag
  3468. JUMP.Z R4 @numerate_number_1 ; Skip leading Zeros
  3469. ADDUI R0 R0 48 ; Shift into ASCII
  3470. STOREX8 R0 R1 R6 ; write digit
  3471. ADDUI R6 R6 1 ; Increment by 1
  3472. :numerate_number_1
  3473. DIV R2 R2 R5 ; Look at next 10
  3474. CMPSKIPI.E R2 0 ; If we reached the bottom STOP
  3475. JUMP @numerate_number_0 ; Otherwise keep looping
  3476. :numerate_number_done
  3477. FALSE R0 ; NULL Terminate
  3478. STOREX8 R0 R1 R6 ; write
  3479. MOVE R0 R1 ; Return pointer to our string
  3480. ;; Cleanup
  3481. POPR R6 R15 ; Restore R6
  3482. POPR R5 R15 ; Restore R5
  3483. POPR R4 R15 ; Restore R4
  3484. POPR R3 R15 ; Restore R3
  3485. POPR R2 R15 ; Restore R2
  3486. POPR R1 R15 ; Restore R1
  3487. RET R15
  3488. :numerate_number_ZERO
  3489. LOADUI R0 48 ; Using Zero
  3490. STOREX8 R0 R1 R6 ; write
  3491. ADDUI R6 R6 1 ; Increment by 1
  3492. JUMP @numerate_number_done ; Be done
  3493. :Max_Decimal
  3494. '3B9ACA00'
  3495. ;; numerate_string function
  3496. ;; Receives pointer To string in R0
  3497. ;; Returns number in R0 equal to value of string
  3498. ;; Or Zero in the event of invalid string
  3499. :numerate_string
  3500. PUSHR R1 R15 ; Protect R1
  3501. PUSHR R2 R15 ; Protect R2
  3502. PUSHR R3 R15 ; Protect R3
  3503. PUSHR R4 R15 ; Protect R4
  3504. ;; Initialize
  3505. MOVE R1 R0 ; Get Text pointer out of the way
  3506. FALSE R2 ; Set Negative flag to false
  3507. FALSE R3 ; Set current count to Zero
  3508. LOAD8 R0 R1 1 ; Get second byte
  3509. CMPSKIPI.NE R0 120 ; If the second byte is x
  3510. JUMP @numerate_string_hex ; treat string like hex
  3511. ;; Deal with Decimal input
  3512. LOADUI R4 10 ; Multiply by 10
  3513. LOAD8 R0 R1 0 ; Get a byte
  3514. CMPSKIPI.NE R0 45 ; If - toggle flag
  3515. TRUE R2 ; So that we know to negate
  3516. CMPSKIPI.E R2 0 ; If toggled
  3517. ADDUI R1 R1 1 ; Move to next
  3518. :numerate_string_dec
  3519. LOAD8 R0 R1 0 ; Get a byte
  3520. CMPSKIPI.NE R0 0 ; If NULL
  3521. JUMP @numerate_string_done ; Be done
  3522. MUL R3 R3 R4 ; Shift counter by 10
  3523. SUBI R0 R0 48 ; Convert ascii to number
  3524. CMPSKIPI.GE R0 0 ; If less than a number
  3525. JUMP @numerate_string_done ; Terminate NOW
  3526. CMPSKIPI.L R0 10 ; If more than a number
  3527. JUMP @numerate_string_done ; Terminate NOW
  3528. ADDU R3 R3 R0 ; Don't add to the count
  3529. ADDUI R1 R1 1 ; Move onto next byte
  3530. JUMP @numerate_string_dec
  3531. ;; Deal with Hex input
  3532. :numerate_string_hex
  3533. LOAD8 R0 R1 0 ; Get a byte
  3534. CMPSKIPI.E R0 48 ; All hex strings start with 0x
  3535. JUMP @numerate_string_done ; Be done if not a match
  3536. ADDUI R1 R1 2 ; Move to after leading 0x
  3537. :numerate_string_hex_0
  3538. LOAD8 R0 R1 0 ; Get a byte
  3539. CMPSKIPI.NE R0 0 ; If NULL
  3540. JUMP @numerate_string_done ; Be done
  3541. SL0I R3 4 ; Shift counter by 16
  3542. SUBI R0 R0 48 ; Convert ascii number to number
  3543. CMPSKIPI.L R0 10 ; If A-F
  3544. SUBI R0 R0 7 ; Shove into Range
  3545. CMPSKIPI.L R0 16 ; If a-f
  3546. SUBI R0 R0 32 ; Shove into Range
  3547. ADDU R3 R3 R0 ; Add to the count
  3548. ADDUI R1 R1 1 ; Get next Hex
  3549. JUMP @numerate_string_hex_0
  3550. ;; Clean up
  3551. :numerate_string_done
  3552. CMPSKIPI.E R2 0 ; If Negate flag has been set
  3553. NEG R3 R3 ; Make the number negative
  3554. MOVE R0 R3 ; Put number in R0
  3555. POPR R4 R15 ; Restore R4
  3556. POPR R3 R15 ; Restore R3
  3557. POPR R2 R15 ; Restore R2
  3558. POPR R1 R15 ; Restore R1
  3559. RET R15
  3560. ;; Keywords
  3561. :union
  3562. "union"
  3563. :struct
  3564. "struct"
  3565. :constant
  3566. "CONSTANT"
  3567. :main_string
  3568. "main"
  3569. :argc_string
  3570. "argc"
  3571. :argv_string
  3572. "argv"
  3573. :if_string
  3574. "if"
  3575. :else_string
  3576. "else"
  3577. :do_string
  3578. "do"
  3579. :while_string
  3580. "while"
  3581. :for_string
  3582. "for"
  3583. :asm_string
  3584. "asm"
  3585. :goto_string
  3586. "goto"
  3587. :return_string
  3588. "return"
  3589. :break_string
  3590. "break"
  3591. :continue_string
  3592. "continue"
  3593. :sizeof_string
  3594. "sizeof"
  3595. :plus_string
  3596. "+"
  3597. :minus_string
  3598. "-"
  3599. :multiply_string
  3600. "*"
  3601. :divide_string
  3602. "/"
  3603. :modulus_string
  3604. "%"
  3605. :left_shift_string
  3606. "<<"
  3607. :right_shift_string
  3608. ">>"
  3609. :less_than_string
  3610. "<"
  3611. :less_than_equal_string
  3612. "<="
  3613. :greater_than_equal_string
  3614. ">="
  3615. :greater_than_string
  3616. ">"
  3617. :equal_to_string
  3618. "=="
  3619. :not_equal_string
  3620. "!="
  3621. :bitwise_and
  3622. "&"
  3623. :logical_and
  3624. "&&"
  3625. :bitwise_or
  3626. "|"
  3627. :logical_or
  3628. "||"
  3629. :bitwise_xor
  3630. "^"
  3631. :arrow_string
  3632. "->"
  3633. ;; Frequently Used strings
  3634. ;; Generally used by require_match
  3635. :open_curly_brace
  3636. "{"
  3637. :close_curly_brace
  3638. "}"
  3639. :open_paren
  3640. "("
  3641. :close_paren
  3642. ")"
  3643. :open_bracket
  3644. "["
  3645. :close_bracket
  3646. "]"
  3647. :semicolon
  3648. ";"
  3649. :equal
  3650. "="
  3651. :percent
  3652. "%"
  3653. :newline
  3654. "
  3655. "
  3656. :underline
  3657. "_"
  3658. ;; Global types
  3659. ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
  3660. :global_types
  3661. &type_void
  3662. :prim_types
  3663. :type_void
  3664. &type_int ; NEXT
  3665. '00 00 00 04' ; SIZE
  3666. NOP ; OFFSET
  3667. &type_void ; INDIRECT
  3668. NOP ; MEMBERS
  3669. &type_void ; TYPE
  3670. &type_void_name ; NAME
  3671. :type_void_name
  3672. "void"
  3673. :type_int
  3674. &type_char ; NEXT
  3675. '00 00 00 04' ; SIZE
  3676. NOP ; OFFSET
  3677. &type_int ; INDIRECT
  3678. NOP ; MEMBERS
  3679. &type_int ; TYPE
  3680. &type_int_name ; NAME
  3681. :type_int_name
  3682. "int"
  3683. :type_char
  3684. &type_file ; NEXT
  3685. '00 00 00 01' ; SIZE
  3686. NOP ; OFFSET
  3687. &type_char_indirect ; INDIRECT
  3688. NOP ; MEMBERS
  3689. &type_char ; TYPE
  3690. &type_char_name ; NAME
  3691. :type_char_name
  3692. "char"
  3693. :type_char_indirect
  3694. &type_file ; NEXT
  3695. '00 00 00 04' ; SIZE
  3696. NOP ; OFFSET
  3697. &type_char_double_indirect ; INDIRECT
  3698. NOP ; MEMBERS
  3699. &type_char_indirect ; TYPE
  3700. &type_char_indirect_name ; NAME
  3701. :type_char_indirect_name
  3702. "char*"
  3703. :type_char_double_indirect
  3704. &type_file ; NEXT
  3705. '00 00 00 04' ; SIZE
  3706. NOP ; OFFSET
  3707. &type_char_double_indirect ; INDIRECT
  3708. NOP ; MEMBERS
  3709. &type_char_indirect ; TYPE
  3710. &type_char_double_indirect_name ; NAME
  3711. :type_char_double_indirect_name
  3712. "char**"
  3713. :type_file
  3714. &type_function ; NEXT
  3715. '00 00 00 04' ; SIZE
  3716. NOP ; OFFSET
  3717. &type_file ; INDIRECT
  3718. NOP ; MEMBERS
  3719. &type_file ; TYPE
  3720. &type_file_name ; NAME
  3721. :type_file_name
  3722. "FILE"
  3723. :type_function
  3724. &type_unsigned ; NEXT
  3725. '00 00 00 04' ; SIZE
  3726. NOP ; OFFSET
  3727. &type_function ; INDIRECT
  3728. NOP ; MEMBERS
  3729. &type_function ; TYPE
  3730. &type_function_name ; NAME
  3731. :type_function_name
  3732. "FUNCTION"
  3733. :type_unsigned
  3734. NOP ; NEXT (NULL)
  3735. '00 00 00 04' ; SIZE
  3736. NOP ; OFFSET
  3737. &type_unsigned ; INDIRECT
  3738. NOP ; MEMBERS
  3739. &type_unsigned ; TYPE
  3740. &type_unsigned_name ; NAME
  3741. :type_unsigned_name
  3742. "unsigned"
  3743. ;; debug_list function
  3744. ;; Receives struct token_list* in R0
  3745. ;; Prints contents of list and HALTS
  3746. ;; Does not return
  3747. :debug_list
  3748. MOVE R9 R0 ; Protect the list Pointer
  3749. FALSE R1 ; Write to TTY
  3750. :debug_list_iter
  3751. ;; Header
  3752. LOADUI R0 $debug_list_string0 ; Using our first string
  3753. CALLI R15 @file_print ; Print it
  3754. COPY R0 R9 ; Use address of pointer
  3755. CALLI R15 @numerate_number ; Convert it into a string
  3756. CALLI R15 @file_print ; Print it
  3757. ;; NEXT
  3758. LOADUI R0 $debug_list_string1 ; Using our second string
  3759. CALLI R15 @file_print ; Print it
  3760. LOAD32 R0 R9 0 ; Use address of pointer
  3761. CALLI R15 @numerate_number ; Convert it into a string
  3762. CALLI R15 @file_print ; Print it
  3763. ;; PREV
  3764. LOADUI R0 $debug_list_string2 ; Using our third string
  3765. CALLI R15 @file_print ; Print it
  3766. LOAD32 R0 R9 4 ; Use address of pointer
  3767. CALLI R15 @numerate_number ; Convert it into a string
  3768. CALLI R15 @file_print ; Print it
  3769. ;; S
  3770. LOADUI R0 $debug_list_string3 ; Using our fourth string
  3771. CALLI R15 @file_print ; Print it
  3772. LOAD32 R0 R9 8 ; Use address of pointer
  3773. CALLI R15 @numerate_number ; Convert it into a string
  3774. CALLI R15 @file_print ; Print it
  3775. ;; S Contents
  3776. LOADUI R0 $debug_list_string4 ; Using our Prefix string
  3777. CALLI R15 @file_print ; Print it
  3778. LOAD32 R0 R9 8 ; Use address of pointer
  3779. CMPSKIPI.NE R0 0 ; If NULL Pointer
  3780. LOADUI R0 $debug_list_string_null ; Give meaningful message instead
  3781. CALLI R15 @file_print ; Print it
  3782. ;; TYPE
  3783. LOADUI R0 $debug_list_string5 ; Using our fifth string
  3784. CALLI R15 @file_print ; Print it
  3785. LOAD32 R0 R9 12 ; Use address of pointer
  3786. CALLI R15 @numerate_number ; Convert it into a string
  3787. CALLI R15 @file_print ; Print it
  3788. ;; PREV
  3789. LOADUI R0 $debug_list_string6 ; Using our sixth string
  3790. CALLI R15 @file_print ; Print it
  3791. LOAD32 R0 R9 16 ; Use address of pointer
  3792. CALLI R15 @numerate_number ; Convert it into a string
  3793. CALLI R15 @file_print ; Print it
  3794. ;; Add some space
  3795. LOADUI R0 10 ; Using NEWLINE
  3796. FPUTC
  3797. FPUTC
  3798. ;; Iterate if next not NULL
  3799. LOAD32 R9 R9 0 ; TOKEN = TOKEN->NEXT
  3800. JUMP.NZ R9 @debug_list_iter
  3801. ;; Looks lke we are done, wrap it up
  3802. HALT
  3803. :debug_list_string0
  3804. "Token_list node at address: "
  3805. :debug_list_string1
  3806. "
  3807. NEXT address: "
  3808. :debug_list_string2
  3809. "
  3810. PREV address: "
  3811. :debug_list_string3
  3812. "
  3813. S address: "
  3814. :debug_list_string4
  3815. "
  3816. The contents of S are: "
  3817. :debug_list_string5
  3818. "
  3819. TYPE address: "
  3820. :debug_list_string6
  3821. "
  3822. ARGUMENTS address: "
  3823. :debug_list_string_null
  3824. ">::<NULL>::<"
  3825. :STACK