1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435 |
- ; Copyright (C) 2016 Jeremiah Orians
- ; This file is part of stage0.
- ;
- ; stage0 is free software: you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, either version 3 of the License, or
- ; (at your option) any later version.
- ;
- ; stage0 is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with stage0. If not, see <http://www.gnu.org/licenses/>.
- ;; A Minimal C Compiler
- ;; type Cells are in the following form:
- ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
- ;; token_list Cells are in the following form:
- ;; NEXT (0), LOCALS/PREV (4), S (8), TYPE/FILENAME (12), ARGUMENTS/DEPTH/LINENUMBER (16)
- ;; Each being the length of a register [32bits]
- ;;
- ;; STACK space: End of program -> 512KB (0x80000) [Could be reduced]
- ;; HEAP space: 512KB -> End of Memory
- ;; R15 is the STACK pointer
- ;; R14 is the HEAP pointer
- :start
- ;; Prep TAPE_02
- LOADUI R0 0x1101
- FOPEN_WRITE
- ;; Prep TAPE_01
- LOADUI R0 0x1100
- FOPEN_READ
- :main
- LOADUI R0 0x1100 ; Pass Tape_01 for reading
- LOADR32 R14 @HEAP ; Setup Initial HEAP
- LOADUI R15 $STACK ; Setup Initial STACK
- CALLI R15 @read_all_tokens ; Read all Tokens in Tape_01
- CALLI R15 @reverse_list ; Fix Token Order
- ; CALLI R15 @debug_list ; Lets try to debug token errors
- MOVE R13 R0 ; Set global_token for future reading
- FALSE R12 ; Set struct token_list* out to NULL
- FALSE R11 ; Set struct token_list* list_strings to NULL
- FALSE R10 ; Set struct token_list* globals_list to NULL
- CALLI R15 @program ; Build our output
- LOADUI R0 $header_string1 ; Using our first header string
- LOADUI R1 0x1101 ; Using Tape_02
- CALLI R15 @file_print ; Write string
- MOVE R0 R12 ; using Contents of output_list
- CALLI R15 @recursive_output ; Recursively write
- LOADUI R0 $header_string2 ; Using our second header string
- CALLI R15 @file_print ; Write string
- MOVE R0 R10 ; using Contents of globals_list
- CALLI R15 @recursive_output ; Recursively write
- LOADUI R0 $header_string3 ; Using our third header string
- CALLI R15 @file_print ; Write string
- MOVE R0 R11 ; using Contents of strings_list
- CALLI R15 @recursive_output ; Recursively write
- LOADUI R0 $header_string4 ; Using our final header string
- CALLI R15 @file_print ; Write string
- HALT ; We have completed compiling our input
- ;; Symbol lists
- :global_constant_list
- NOP
- :global_symbol_list
- NOP
- :global_function_list
- NOP
- ;; Pointer to initial HEAP ADDRESS
- :HEAP
- '00080000'
- ;; Output strings
- :header_string1
- "
- # Core program
- "
- :header_string2
- "
- # Program global variables
- "
- :header_string3
- "
- # Program strings
- "
- :header_string4
- "
- :ELF_end
- "
- ;; clearWhiteSpace function
- ;; Receives a character in R0 and FILE* in R1 and line_num in R11
- ;; Returns first non-whitespace character in R0
- :clearWhiteSpace
- CMPSKIPI.NE R0 32 ; Check for a Space
- JUMP @clearWhiteSpace_reset ; Looks like we need to remove a space
- CMPSKIPI.NE R0 9 ; Check for a tab
- JUMP @clearWhiteSpace_reset ; Looks like we need to remove a tab
- CMPSKIPI.E R0 10 ; Check for a newline
- RET R15 ; Looks we found a non-whitespace
- ADDUI R11 R11 1 ; Increment line number
- ;; Fall through to iterate to next char
- :clearWhiteSpace_reset
- FGETC ; Get next char
- JUMP @clearWhiteSpace ; Iterate
- ;; consume_byte function
- ;; Receives a char in R0, FILE* in R1 and index in R13
- ;; Returns next char in R0
- :consume_byte
- STOREX8 R0 R14 R13 ; Put char onto HEAP
- ADDUI R13 R13 1 ; Increment index
- FGETC ; Get next char
- RET R15
- ;; consume_word function
- ;; Receives a char in R0, FILE* in R1, FREQUENT in R2 and index in R13
- ;; Returns next char in R0
- :consume_word
- PUSHR R3 R15 ; Protect R3
- FALSE R3 ; ESCAPE is FALSE
- :consume_word_reset
- JUMP.NZ R3 @consume_word_iter1
- CMPSKIPI.NE R0 92 ; If \
- TRUE R3 ; Looks like we are in an escape
- JUMP @consume_word_iter2
- :consume_word_iter1
- FALSE R3 ; Looks like we are no longer in an escape
- :consume_word_iter2
- CALLI R15 @consume_byte ; Store the char
- JUMP.NZ R3 @consume_word_reset ; If escape loop
- CMPJUMPI.NE R0 R2 @consume_word_reset ; if not matching frequent loop
- FGETC ; Get a new char to return
- POPR R3 R15 ; Restore R3
- RET R15
- ;; fixup_label function
- ;; Receives nothing (But uses R14 as HEAP pointer)
- ;; Returns 32 in R0 and no other registers altered
- :fixup_label
- PUSHR R1 R15 ; Protect R1 from change
- PUSHR R2 R15 ; Protect R2 from change
- LOADUI R0 58 ; Set HOLD to :
- FALSE R2 ; Set I to 0
- :fixup_label_reset
- MOVE R1 R0 ; Set PREV = HOLD
- LOADXU8 R0 R14 R2 ; Read hold_string[I] into HOLD
- STOREX8 R1 R14 R2 ; Set hold_string[I] = PREV
- ADDUI R2 R2 1 ; increment I
- JUMP.NZ R0 @fixup_label_reset ; Loop until we hit a NULL
- ;; clean up
- ADDUI R2 R2 1 ; increment I
- LOADUI R0 32 ; Put 32 in R0
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; in_set2 function
- ;; Receives a Char in R0, FILE* in R1, char* in R2 and index in R13
- ;; Return result in R2
- :in_set2
- PUSHR R3 R15 ; Protect R3 from changes
- :in_set2_reset
- LOADU8 R3 R2 0 ; Get char from list
- JUMP.Z R3 @in_set2_fail ; Stop when 0 == s[0]
- CMPJUMPI.E R0 R3 @in_set2_done ; We found a match
- ADDUI R2 R2 1 ; Increment to next char
- JUMP.NZ R3 @in_set2_reset ; Iterate if not NULL
- :in_set2_fail
- ;; Looks like not found
- FALSE R2 ; Return FALSE
- :in_set2_done
- CMPSKIPI.E R2 0 ; Provided not FALSE
- TRUE R2 ; The result is true
- POPR R3 R15 ; Restore R3
- RET R15
- ;; in_set function
- ;; Receives a Char in R0, char* in R1
- ;; Return result in R0
- :in_set
- PUSHR R2 R15 ; Protect R3 from changes
- :in_set_reset
- LOADU8 R2 R1 0 ; Get char from list
- JUMP.Z R2 @in_set_fail ; Stop when 0 == s[0]
- CMPJUMPI.E R0 R2 @in_set_done ; We found a match
- ADDUI R1 R1 1 ; Increment to next char
- JUMP.NZ R2 @in_set_reset ; Iterate if not NULL
- :in_set_fail
- ;; Looks like not found
- FALSE R1 ; Return FALSE
- :in_set_done
- CMPSKIPI.E R1 0 ; Provided not FALSE
- TRUE R2 ; The result is true
- MOVE R0 R2 ; Put result in correct place
- POPR R2 R15 ; Restore R3
- RET R15
- ;; Common in_set strings of interest
- ;; As Raw strings (") is forbidden and ' has some restrictions
- :nice_chars
- "
- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
- :keyword_chars
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
- :variable_chars
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
- :symbol_chars
- "<=>|&!-"
- :hex_chars
- "0123456789ABCDEF"
- :digit_chars
- "0123456789"
- :whitespace_chars
- "
- "
- ;; preserve_keyword function
- ;; Receives a Char in R0, FILE* in R1 and index in R13
- ;; Overwrites R2
- ;; Returns next CHAR
- :preserve_keyword
- LOADUI R2 $keyword_chars ; Using keyword list of chars
- CALLI R15 @in_set2 ; Check if in list
- JUMP.Z R2 @preserve_keyword_label ; if not in set, stop iterating
- :preserve_keyword_reset
- CALLI R15 @consume_byte ; Consume another byte
- JUMP @preserve_keyword ; Iterate
- :preserve_keyword_label
- CMPSKIPI.NE R0 58 ; Check for label (:)
- CALLI R15 @fixup_label ; Looks like we found one
- RET R15
- ;; preserve_symbol function
- ;; Receives a Char in R0, FILE* in R1 and index in R13
- ;; Overwrites R2
- ;; Returns next CHAR
- :preserve_symbol
- LOADUI R2 $symbol_chars ; Using symbol list of chars
- CALLI R15 @in_set2 ; Check if in list
- JUMP.NZ R2 @preserve_symbol_reset
- ;; Looks we didn't find anything we wanted to preserve
- RET R15
- :preserve_symbol_reset
- CALLI R15 @consume_byte ; Consume another byte
- JUMP @preserve_symbol ; Iterate
- ;; purge_macro function
- ;; Receives a Char in R0, FILE* in R1 and index in R13
- ;; Returns next CHAR via jumping to get_token_reset
- :purge_macro
- CMPSKIPI.NE R0 10 ; Check for Line Feed
- JUMP @get_token_reset ; Looks like we found it, call it done
- FGETC ; Looks like we need another CHAR
- JUMP @purge_macro ; Keep looping
- ;; get_token function
- ;; Receives a Char in R0, FILE* in R1, line_num in R11 and TOKEN in R10
- ;; sets index in R13 and current in R12
- ;; Overwrites R2
- ;; Returns next CHAR
- :get_token
- PUSHR R12 R15 ; Preserve R12
- PUSHR R13 R15 ; Preserve R13
- COPY R12 R14 ; Save CURRENT's Address
- ADDUI R14 R14 20 ; Update Malloc to free space for string
- :get_token_reset
- FALSE R13 ; Reset string_index to 0
- CALLI R15 @clearWhiteSpace ; Clear any leading whitespace
- CMPSKIPI.NE R0 35 ; Deal with # line macros
- JUMP @purge_macro ; Returns at get_token_reset
- ;; Check for keywords
- LOADUI R2 $keyword_chars ; Using keyword list
- CALLI R15 @in_set2 ; Check if keyword
- JUMP.Z R2 @get_token_symbol ; if not a keyword
- CALLI R15 @preserve_keyword ; Yep its a keyword
- JUMP @get_token_done ; Be done with token
- ;; Check for symbols
- :get_token_symbol
- LOADUI R2 $symbol_chars ; Using symbol list
- CALLI R15 @in_set2 ; Check if symbol
- JUMP.Z R2 @get_token_char ; If not a symbol
- CALLI R15 @preserve_symbol ; Yep its a symbol
- JUMP @get_token_done ; Be done with token
- ;; Check for char
- :get_token_char
- CMPSKIPI.E R0 39 ; Check if '
- JUMP @get_token_string ; Not a '
- COPY R2 R0 ; Prepare for consume_word
- CALLI R15 @consume_word ; Call it
- JUMP @get_token_done ; Be done with token
- ;; Check for string
- :get_token_string
- CMPSKIPI.E R0 34 ; Check if "
- JUMP @get_token_EOF ; Not a "
- COPY R2 R0 ; Prepare for consume_word
- CALLI R15 @consume_word ; Call it
- JUMP @get_token_done ; Be done with token
- ;; Check for EOF
- :get_token_EOF
- CMPSKIPI.L R0 0 ; If c < 0
- JUMP @get_token_comment ; If not EOF
- POPR R13 R15 ; Restore R13
- POPR R12 R15 ; Restore R12
- RET R15 ; Otherwise just return the EOF
- ;; Check for C comments
- :get_token_comment
- CMPSKIPI.E R0 47 ; Deal with non-comments
- JUMP @get_token_else ; immediately
- CALLI R15 @consume_byte ; Deal with another byte
- CMPSKIPI.NE R0 42 ; if * make it a block comment
- JUMP @get_token_comment_block ; and purge it all
- CMPSKIPI.E R0 47 ; Check if not //
- JUMP @get_token_done ; Finish off the token
- ;; Looks like it was //
- FGETC ; Get next char
- JUMP @get_token_reset ; Try again
- ;; Deal with the mess that is C block comments
- :get_token_comment_block
- FGETC ; Get next char
- :get_token_comment_block_outer
- CMPSKIPI.NE R0 47 ; Check for closing /
- JUMP @get_token_comment_block_outer_done ; Yep has closing /
- :get_token_comment_block_inner
- CMPSKIPI.NE R0 42 ; Check for preclosing *
- JUMP @get_token_comment_block_inner_done ; Yep has *
- ;; Otherwise we are just consuming
- FGETC ; Remove another CHAR
- CMPSKIPI.NE R0 10 ; Check for Line Feed
- ADDUI R11 R11 1 ; Found one, updating line number
- JUMP @get_token_comment_block_inner
- :get_token_comment_block_inner_done
- FGETC ; Remove another CHAR
- CMPSKIPI.NE R0 10 ; Check for Line Feed
- ADDUI R11 R11 1 ; Found one, updating line number
- JUMP @get_token_comment_block_outer
- :get_token_comment_block_outer_done
- FGETC ; Remove another CHAR
- JUMP @get_token_reset ; And Try again
- ;; Deal with default case
- :get_token_else
- CALLI R15 @consume_byte ; Consume the byte and be done
- :get_token_done
- ADDUI R13 R13 2 ; Pad with NULL the string
- STORE32 R14 R12 8 ; Set CURRENT->S to String
- ADD R14 R14 R13 ; Add string length to HEAP
- STORE32 R10 R12 0 ; CURRENT->NEXT = TOKEN
- STORE32 R10 R12 4 ; CURRENT->PREV = TOKE
- STORE32 R11 R12 16 ; CURRENT->LINENUM = LINE_NUM
- MOVE R10 R12 ; SET TOKEN to CURRENT
- POPR R13 R15 ; Restore R13
- POPR R12 R15 ; Restore R12
- RET R15
- ;; reverse_list function
- ;; Receives a Token_list in R0
- ;; Returns List in Reverse order in R0
- :reverse_list
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- FALSE R1 ; Set ROOT to NULL
- CMPJUMPI.E R0 R1 @reverse_list_done ; ABORT if given a NULL
- :reverse_list_reset
- LOAD32 R2 R0 0 ; SET next to HEAD->NEXT
- STORE32 R1 R0 0 ; SET HEAD->NEXT to ROOT
- MOVE R1 R0 ; SET ROOT to HEAD
- MOVE R0 R2 ; SET HEAD to NEXT
- JUMP.NZ R0 @reverse_list_reset ; Iterate if HEAD not NULL
- :reverse_list_done
- MOVE R0 R1 ; SET Result to ROOT
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; read_all_tokens function
- ;; Receives a FILE* in R0
- ;; sets line_num in R11 and TOKEN in R10
- ;; Overwrites R2
- ;; Returns struct token_list* in R0
- :read_all_tokens
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R10 R15 ; Protect R10
- PUSHR R11 R15 ; Protect R11
- MOVE R1 R0 ; Set R1 as FILE*
- FGETC ; Read our first CHAR
- LOADUI R11 1 ; Start line_num at 1
- FALSE R10 ; First token is NULL
- :read_all_tokens_reset
- JUMP.NP R0 @read_all_tokens_done
- CALLI R15 @get_token
- JUMP @read_all_tokens_reset
- :read_all_tokens_done
- MOVE R0 R10 ; Return the Token
- POPR R11 R15 ; Restore R11
- POPR R10 R15 ; Restore R10
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; parse_string function
- ;; Receives char* string in R0
- ;; R14 is HEAP Pointer
- ;; Returns char* in R0
- :parse_string
- PUSHR R1 R15 ; Protect R1
- COPY R1 R0 ; Make a copy of STRING
- CALLI R15 @weird ; Check if string is weird
- SWAP R0 R1
- JUMP.Z R1 @parse_string_regular ; Deal with regular strings
- ;; Looks like we have a weirdo
- CALLI R15 @collect_weird_string ; Create our weird string
- JUMP @parse_string_done ; Simply return what was created
- :parse_string_regular
- CALLI R15 @collect_regular_string
- :parse_string_done
- POPR R1 R15 ; Restore R1
- RET R15
- ;; weird function
- ;; Analyze string to determine if it's output would be weird for mescc-tools
- ;; Receives char* in R0
- ;; Returns BOOL in R0
- :weird
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- FALSE R2 ; Assume FALSE
- ADDUI R3 R0 1 ; STRING = STRING + 1
- :weird_iter
- JUMP.NZ R2 @weird_done ; Stop if TRUE
- LOADU8 R4 R3 0 ; C = STRING[0]
- JUMP.Z R4 @weird_done ; Be done at NULL Termination
- CMPSKIPI.E R4 92 ; If not '\\'
- JUMP @weird_post_escape ; Looks like no escape analysis
- ;; Deal with the mess
- COPY R0 R3 ; Using STRING
- CALLI R15 @escape_lookup ; Get our CHAR
- MOVE R4 R0 ; C = ESCAPE_LOOKUP(STRING)
- LOADU8 R0 R3 1 ; STRING[1]
- CMPSKIPI.NE R0 120 ; if 'x' == STRING[1]
- ADDUI R3 R3 2 ; STRING = STRING + 2
- ADDUI R3 R3 1 ; STRING = STRING + 1
- :weird_post_escape
- LOADUI R1 $nice_chars ; using list of nice CHARS
- COPY R0 R4 ; using copy of C
- CALLI R15 @in_set ; Use in_set
- CMPSKIPI.NE R0 0 ; IF TRUE
- TRUE R2 ; Return TRUE
- ADDUI R3 R3 1 ; STRING = STRING + 1
- LOADUI R1 $whitespace_chars ; Check Whitespace Chars
- COPY R0 R4 ; Using copy of C
- CALLI R15 @in_set ; Use in_set
- JUMP.Z R0 @weird_iter ; If False simply loop
- LOADU8 R0 R3 0 ; STRING[1]
- CMPSKIPI.NE R0 58 ; If ':' == STRING[1]
- TRUE R2 ; Flip flag
- JUMP @weird_iter ; Keep trying to find an answer
- :weird_done
- MOVE R0 R2 ; Whatever is in R2 is the answer
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; collect_weird_string function
- ;; Converts weird string into a form mescc-tools can handle cleanly
- ;; Receives char* in R0
- ;; R14 is HEAP Pointer and $hex_chars as the table
- ;; Returns char* in R0
- :collect_weird_string
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- LOADUI R4 $hex_chars ; Pointer to TABLE
- COPY R3 R14 ; Get HOLD
- MOVE R2 R0 ; Put STRING in Place
- LOADUI R0 39 ; Prefix with '
- PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
- :collect_weird_string_iter
- ADDUI R2 R2 1 ; STRING = STRING + 1
- LOADUI R0 32 ; Insert ' '
- PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
- COPY R0 R2 ; copy STRING
- CALLI R15 @escape_lookup ; Get char value
- ANDI R1 R0 0x0F ; Save Bottom out of the way
- SR0I R0 4 ; Isolate Top
- LOADXU8 R0 R4 R0 ; Using Table
- LOADXU8 R1 R4 R1 ; Using Table
- PUSH8 R0 R3 ; HOLD[0] = TABLE[(TEMP >> 4)] && HOLD = HOLD + 1
- PUSH8 R1 R3 ; HOLD[0] = TABLE[(TEMP & 15)] && HOLD = HOLD + 1
- LOADU8 R0 R2 0 ; STRING[0]
- JUMP.Z R0 @collect_weird_string_done ; Stop if NULL
- CMPSKIPI.E R0 92 ; IF STRING[0] != '\\'
- JUMP @collect_weird_string_check ; Deal with iteration
- LOADU8 R0 R2 1 ; STRING[1]
- CMPSKIPI.NE R0 120 ; If STRING[1] == 'x'
- ADDUI R2 R2 2 ; STRING = STRING + 2
- ADDUI R2 R2 1 ; STRING = STRING + 1
- :collect_weird_string_check
- LOADU8 R0 R2 1 ; STRING[1]
- JUMP.NZ R0 @collect_weird_string_iter
- :collect_weird_string_done
- LOADUI R0 32 ; Insert ' '
- PUSH8 R0 R3 ; HOLD[0] = ' ' && HOLD = HOLD + 1
- LOADUI R0 48 ; Insert '0'
- PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
- PUSH8 R0 R3 ; HOLD[0] = '0' && HOLD = HOLD + 1
- LOADUI R0 39 ; Insert '\''
- PUSH8 R0 R3 ; HOLD[0] = '\'' && HOLD = HOLD + 1
- LOADUI R0 10 ; Insert '\n'
- PUSH8 R0 R3 ; HOLD[0] = '\n' && HOLD = HOLD + 1
- ADDUI R3 R3 1 ; NULL Terminate
- SWAP R3 R14 ; CALLOC HOLD
- MOVE R0 R3 ; Return HOLD
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; hex function
- ;; Receives Char in R0
- ;; Return Int in R0
- :hex
- SUBUI R0 R0 48 ; First shift
- CMPSKIPI.GE R0 10 ; If 0-9
- RET R15 ; Be done
- ;; Deal with A-F
- ANDI R0 R0 0xDF ; Unset high bit
- SUBUI R0 R0 7 ; Shift them down
- CMPSKIPI.GE R0 10 ; if between 9 and A
- JUMP @hex_error ; Throw an error
- CMPSKIPI.L R0 16 ; if > F
- JUMP @hex_error ; Throw an error
- RET R15
- :hex_error
- LOADUI R0 $hex_error_message ; Our message
- FALSE R1 ; For human
- CALLI R15 @file_print ; write it
- CALLI R15 @line_error ; More info
- HALT
- :hex_error_message
- "Tried to print non-hex number
- "
- ;; escape_lookup function
- ;; Receives char* in R0
- ;; Returns char in R0
- :escape_lookup
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- MOVE R1 R0 ; Put C in the right spot
- FALSE R2 ; Our flag for done
- LOADU8 R0 R1 0 ; c[0]
- CMPSKIPI.E R0 92 ; If C[0] != '\\'
- JUMP @escape_lookup_none ; Deal with none case
- LOADU8 R0 R1 1 ; c[1]
- CMPSKIPI.NE R0 120 ; if \x??
- JUMP @escape_lookup_hex
- ;; Deal with \? escapes
- CMPSKIPI.NE R0 110 ; If \n
- LOADUI R2 10 ; return \n
- CMPSKIPI.NE R0 116 ; If \t
- LOADUI R2 9 ; return \t
- CMPSKIPI.NE R0 92 ; If \\
- LOADUI R2 92 ; return \\
- CMPSKIPI.NE R0 39 ; If \'
- LOADUI R2 39 ; return \'
- CMPSKIPI.NE R0 34 ; If \"
- LOADUI R2 34 ; return \"
- CMPSKIPI.NE R0 114 ; If \r
- LOADUI R2 13 ; return \r
- JUMP.Z R2 @escape_lookup_error ; Looks like we got something weird
- JUMP @escape_lookup_done ; Otherwise just use our R2
- :escape_lookup_none
- MOVE R2 R0 ; We just return the char at C[0]
- JUMP @escape_lookup_done ; Be done
- :escape_lookup_hex
- LOADU8 R0 R1 2 ; c[2]
- CALLI R15 @hex ; Get first char
- SL0I R0 4 ; Shift our first nybble
- MOVE R2 R0 ; Protect our top nybble
- LOADU8 R0 R1 3 ; c[3]
- CALLI R15 @hex ; Get second char
- ADD R2 R2 R0 ; \x?? => ? << 4 + ?
- :escape_lookup_done
- MOVE R0 R2 ; R2 has our answer
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- :escape_lookup_error
- MOVE R2 R0 ; Protect Char that failed
- LOADUI R0 $escape_lookup_string0 ; Load message
- FALSE R1 ; We want the User to see
- CALLI R15 @file_print ; Write it
- MOVE R0 R2 ; Our CHAR
- FPUTC ; Write it
- LOADUI R0 10 ; '\n'
- FPUTC ; Write it
- CALLI R15 @line_error ; Provide some debug information
- HALT
- :escape_lookup_string0
- "Received invalid escape \\"
- ;; collect_regular_string function
- ;; Converts C string into a RAW string for mescc-tools
- ;; Receives char* in R0
- ;; R14 is HEAP Pointer
- ;; Returns char* in R0
- :collect_regular_string
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- COPY R2 R14 ; MESSAGE
- MOVE R1 R0 ; Put STRING in the right place
- :collect_regular_string_iter
- LOADU8 R0 R1 0 ; STRING[0]
- JUMP.Z R0 @collect_regular_string_done ; End at NULL
- CMPSKIPI.NE R0 92 ; if STRING[0] == '\\'
- JUMP @collect_regular_string_escape ; deal with escapes
- ;; Deal with vannilla chars
- STORE8 R0 R2 0 ; MESSAGE[0] = STRING[0]
- ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
- ADDUI R1 R1 1 ; STRING = STRING + 1
- JUMP @collect_regular_string_iter ; Loop
- :collect_regular_string_escape
- COPY R0 R1 ; Prepare for call
- CALLI R15 @escape_lookup ; Get what weird char we need
- STORE8 R0 R2 0 ; MESSAGE[0] = escape_lookup(string)
- ADDUI R2 R2 1 ; MESSAGE = MESSAGE + 1
- LOADU8 R0 R1 1 ; STRING[1]
- CMPSKIPI.NE R0 120 ; if \x??
- ADDUI R1 R1 2 ; STRING = STRING + 2
- ADDUI R1 R1 2 ; STRING = STRING + 2
- JUMP @collect_regular_string_iter ; Loop
- :collect_regular_string_done
- LOADUI R0 34 ; Using "
- STORE8 R0 R2 0 ; MESSAGE[0] = '"'
- LOADUI R0 10 ; Using '\n'
- STORE8 R0 R2 1 ; MESSAGE[1] = "\n"
- ADDUI R2 R2 3 ; Add extra NULL padding
- SWAP R2 R14 ; Update HEAP
- MOVE R0 R2 ; Put MESSAGE in the right Spot
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; unary_expr_sizeof function
- ;; Receives nothing
- ;; Returns nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :unary_expr_sizeof
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $unary_expr_sizeof_string0 ; Our first error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Ensure a match
- CALLI R15 @type_name ; Get type_name
- MOVE R2 R0 ; Protect A
- LOADUI R0 $unary_expr_sizeof_string1 ; Our final error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Ensure a match
- LOADUI R0 $not ; Using "!"
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R2 4 ; A->SIZE
- CALLI R15 @numerate_number ; Convert to string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $unary_expr_sizeof_string2 ; Our header
- CALLI R15 @emit_out ; emit it
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :unary_expr_sizeof_string0
- "ERROR in unary_expr
- Missing (
- "
- :unary_expr_sizeof_string1
- "ERROR in unary_expr
- Missing )
- "
- :unary_expr_sizeof_string2
- " R0 LOADI8_ALWAYS
- "
- ;; constant_load function
- ;; Receives struct token_list* a in R0
- ;; Returns nothing
- :constant_load
- PUSHR R0 R15 ; Protect R0
- LOADUI R0 $constant_load_string0 ; Our header
- CALLI R15 @emit_out ; emit it
- POPR R0 R15 ; Restore R0
- LOAD32 R0 R0 16 ; A->ARGUMENTS
- LOAD32 R0 R0 8 ; A->ARGUMENTS->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- RET R15
- :constant_load_string0
- "!0 R0 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- %"
- ;; variable_load function
- ;; Receives struct token_list* a in R0
- ;; and struct token_list* current_target in R8
- ;; Returns Nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :variable_load
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- MOVE R2 R0 ; Protect A
- ;; Check if function call
- LOADUI R0 $type_function_name ; Using "FUNCTION"
- LOAD32 R1 R2 12 ; A->TYPE
- LOAD32 R1 R1 24 ; A->TYPE->NAME
- CALLI R15 @match ; IF "FUNCTION" == A->TYPE->NAME
- JUMP.Z R0 @variable_load_regular ; Nope
- LOADUI R0 $open_paren ; Using "("
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF "(" == GLOBAL_TOKEN->S
- JUMP.Z R0 @variable_load_regular ; Nope
- ;; Deal with function call
- LOAD32 R0 R2 16 ; A->DEPTH
- CALLI R15 @numerate_number ; Convert to string
- TRUE R1 ; Passing TRUE
- CALLI R15 @function_call ; DO IT
- JUMP @variable_load_done ; Be done
- :variable_load_regular
- LOAD32 R8 R2 12 ; CURRENT_TARGET = A->TYPE
- LOADUI R0 $not ; Using "!"
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R2 16 ; A->DEPTH
- CALLI R15 @numerate_number ; Convert to string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $variable_load_string0 ; Our prefix
- CALLI R15 @emit_out ; emit it
- ;; check for special case 1
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- JUMP.NZ R0 @variable_load_done ; Be done
- ;; deal with the general case
- LOADUI R0 $variable_load_string1 ; Our postfix
- CALLI R15 @emit_out ; emit it
- :variable_load_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- :variable_load_string0
- " R0 SUB BP ARITH_ALWAYS
- "
- :variable_load_string1
- "!0 R0 LOAD32 R0 MEMORY
- "
- ;; function_load function
- ;; Receives struct token_list* a in R0
- ;; Returns nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :function_load
- PUSHR R1 R15 ; Protect R1
- LOAD32 R0 R0 8 ; A->S
- PUSHR R0 R15 ; Protect A->S
- LOADUI R0 $open_paren ; Using "("
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; If GLOBAL_TOKEN->S == "("
- JUMP.Z R0 @function_load_regular ; If not do the simple thing
- ;; Deal iwth function call
- POPR R0 R15 ; Restore A->S
- FALSE R1 ; FALSE
- CALLI R15 @function_call ; Do the function call
- JUMP @function_load_done ; Clean up
- :function_load_regular
- LOADUI R0 $function_load_string0 ; Using our header string
- CALLI R15 @emit_out ; emit it
- POPR R0 R15 ; Restore A->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- :function_load_done
- POPR R1 R15 ; Restore R1
- RET R15
- :function_load_string0
- "!0 R0 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- &FUNCTION_"
- ;; global_load function
- ;; Receives struct token_list* a in R0
- ;; and struct token_list* current_target in R8
- ;; Returns nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :global_load
- PUSHR R0 R15 ; Protect A
- LOAD32 R8 R0 12 ; CURRENT_TARGET = A->TYPE
- LOADUI R0 $global_load_string0 ; Our header string
- CALLI R15 @emit_out ; emit it
- POPR R0 R15 ; Restore A
- LOAD32 R0 R0 8 ; A->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- PUSHR R1 R15 ; Protect R1
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- JUMP.NZ R0 @global_load_done ; Skip the following
- ;; Deal with non-assignment
- LOADUI R0 $global_load_string1 ; Our footer string
- CALLI R15 @emit_out ; emit it
- :global_load_done
- POPR R1 R15 ; Restore R1
- RET R15
- :global_load_string0
- "!0 R0 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- &GLOBAL_"
- :global_load_string1
- "!0 R0 LOAD32 R0 MEMORY
- "
- ;; primary_expr_failure function
- ;; Fails hard and fast
- ;; Receives nothing
- ;; HALTs and will trash registers
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :primary_expr_failure
- LOADUI R0 $primary_expr_failure_string0 ; Our first string
- FALSE R1 ; Display to User
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @file_print ; Print it
- LOADUI R0 $primary_expr_failure_string1 ; Our last string
- CALLI R15 @file_print ; Print it
- CALLI R15 @line_error ; Make it a line error message too
- HALT
- :primary_expr_failure_string0
- "Received "
- :primary_expr_failure_string1
- " in primary_expr
- "
- ;; primary_expr_string function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :primary_expr_string
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOADR32 R0 @current_count ; Using CURRENT_COUNT
- ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
- STORER32 R1 @current_count ; Update CURRENT_COUNT
- CALLI R15 @numerate_number ; Convert to string
- MOVE R2 R0 ; Put string in safe place
- LOADUI R0 $primary_expr_string_string0 ; Our string prefix
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- COPY R1 R2 ; NUMBER_STRING
- CALLI R15 @uniqueID_out ; Make it unique
- ;; The target
- LOADUI R0 $primary_expr_string_string1
- COPY R1 R11 ; Using STRINGS_LIST
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Put STRINGS_LIST in correct place
- LOAD32 R0 R9 8 ; Using FUNCTION->S
- CALLI R15 @uniqueID ; Make it unique
- MOVE R11 R0 ; Update STRINGS_LIST
- ;; Parse the string
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @parse_string ; Parse it
- COPY R1 R11 ; Using STRINGS_LIST
- CALLI R15 @emit ; emit it
- MOVE R11 R0 ; Update STRINGS_LIST
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :primary_expr_string_string0
- "!0 R0 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- &STRING_"
- :primary_expr_string_string1
- ":STRING_"
- ;; primary_expr_char function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :primary_expr_char
- PUSHR R0 R15 ; Protect R0
- LOADUI R0 $not ; Using "!"
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
- CALLI R15 @escape_lookup ; escape_lookup value
- CALLI R15 @numerate_number ; Make it a string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $primary_expr_char_string0 ; Using our header string
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- POPR R0 R15 ; Restore R0
- RET R15
- :primary_expr_char_string0
- " R0 LOADI8_ALWAYS
- "
- ;; primary_expr_number function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :primary_expr_number
- LOADUI R0 $primary_expr_number_string0 ; Our header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- RET R15
- :primary_expr_number_string0
- "!0 R0 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- %"
- ;; primary_expr_variable function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :primary_expr_variable
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOAD32 R2 R13 8 ; S = GLOBAL_TOKEN->S
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- COPY R0 R2 ; Using S
- LOADR32 R1 @global_constant_list
- CALLI R15 @sym_lookup ; Lookup S in CONSTANTS
- JUMP.Z R0 @primary_expr_variable_locals ; try Locals
- ;; Deal with Constants
- CALLI R15 @constant_load ; A is in R0 already
- JUMP @primary_expr_variable_done ; Moving on
- :primary_expr_variable_locals
- COPY R0 R2 ; Using S
- LOAD32 R1 R9 4 ; Using FUNCTION->LOCALS
- CALLI R15 @sym_lookup ; Lookup S in Locals
- JUMP.Z R0 @primary_expr_variable_arguments ; try arguments
- ;; Deal with Locals
- CALLI R15 @variable_load ; A is in R0 already
- JUMP @primary_expr_variable_done ; Moving on
- :primary_expr_variable_arguments
- COPY R0 R2 ; Using S
- LOAD32 R1 R9 16 ; Using FUNCTION->ARGUMENTS
- CALLI R15 @sym_lookup ; Lookup S in arguments
- JUMP.Z R0 @primary_expr_variable_function ; try Functions
- ;; Deal with argument
- CALLI R15 @variable_load ; A is in R0 already
- JUMP @primary_expr_variable_done ; Moving on
- :primary_expr_variable_function
- COPY R0 R2 ; Using S
- LOADR32 R1 @global_function_list ; Get current GLOBAL_FUNCTION_LIST
- CALLI R15 @sym_lookup ; Lookup S in GLOBAL_FUNCTION_LIST
- JUMP.Z R0 @primary_expr_variable_global ; try Globals
- ;; Deal with function
- CALLI R15 @function_load ; Dothe work
- JUMP @primary_expr_variable_done ; Moving on
- :primary_expr_variable_global
- COPY R0 R2 ; Using S
- LOADR32 R1 @global_symbol_list ; Get current GLOBAL_SYMBOL_LIST
- CALLI R15 @sym_lookup ; Lookup S in GLOBAL_SYMBOL_LIST
- JUMP.Z R0 @primary_expr_variable_failure ; Looks like it isn't anything we know
- ;; Deal with a global
- CALLI R15 @global_load
- :primary_expr_variable_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :primary_expr_variable_failure
- MOVE R0 R2 ; Using S
- FALSE R1 ; We want the user to see
- CALLI R15 @file_print ; Print it
- LOADUI R0 $primary_expr_variable_string0 ; Body
- CALLI R15 @file_print ; Print it
- CALLI R15 @line_error ; Provide useful error info
- HALT
- :primary_expr_variable_string0
- " is not a defined symbol
- "
- ;; promote_type function
- ;; Receives struct type* in R0 and struct type* in R1
- ;; Returns first match struct type* in R0
- :promote_type
- JUMP.Z R1 @promote_type_abort0 ; If B is NULL just abort
- PUSHR R1 R15 ; Protect R1
- SWAP R0 R1 ; Give A a try
- JUMP.Z R1 @promote_type_abort1 ; A is NULL just short abort
- ;; Looks like we have a bunch of work to do
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- PUSHR R5 R15 ; Protect R5
- MOVE R5 R1 ; Put A in the right spot
- MOVE R4 R0 ; Put B in the right spot
- LOADR32 R3 @global_types ; I = GLOBAL_TYPES
- :promote_type_iter
- LOAD32 R1 R3 24 ; I->NAME
- LOAD32 R0 R5 24 ; A->NAME
- CMPJUMPI.E R0 R1 @promote_type_done ; break
- LOAD32 R0 R4 24 ; B->NAME
- CMPJUMPI.E R0 R1 @promote_type_done ; break
- LOAD32 R1 R3 12 ; I->INDIRECT
- LOAD32 R1 R1 24 ; I->INDIRECT->NAME
- LOAD32 R0 R5 24 ; A->NAME
- CMPJUMPI.E R0 R1 @promote_type_done ; break
- LOAD32 R0 R4 24 ; B->NAME
- CMPJUMPI.E R0 R1 @promote_type_done ; break
- LOAD32 R3 R3 0 ; I = I->NEXT
- JUMP.NZ R3 @promote_type_iter ; Loop if not NULL
- :promote_type_done
- MOVE R0 R3 ; Return I
- POPR R5 R15 ; Restore R5
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- :promote_type_abort1
- POPR R1 R15 ; Restore R1
- :promote_type_abort0
- RET R15
- ;; common_recursion function
- ;; Receives FUNCTION* in R0
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :common_recursion
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- MOVE R2 R0 ; Protect F
- COPY R1 R8 ; LAST_TYPE = CURRENT_TARGET
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $common_recursion_string0 ; Header string
- CALLI R15 @emit_out ; Our header
- CALL R2 R15 ; CALL F()
- COPY R0 R8 ; Using CURRENT_TARGET
- CALLI R15 @promote_type ; Promote type
- MOVE R8 R0 ; update CURRENT_TARGET
- LOADUI R0 $common_recursion_string1 ; Footer string
- CALLI R15 @emit_out ; Our footer
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :common_recursion_string0
- "{R0} PUSH_ALWAYS #_common_recursion
- "
- :common_recursion_string1
- "{R1} POP_ALWAYS # _common_recursion
- "
- ;; general_recursion function
- ;; Receives FUNCTION F in R0, char* s in R1, char* name in R2
- ;; and FUNCTION ITERATE in R3
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns nothing
- :general_recursion
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect S
- PUSHR R0 R15 ; Protect F
- COPY R0 R2 ; Using NAME
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == NAME
- JUMP.Z R0 @general_recursion_done
- ;; deal with case of match
- POPR R0 R15 ; Restore F
- CALLI R15 @common_recursion ; Recurse
- POPR R1 R15 ; Restore S
- COPY R0 R1 ; Put S in correct place
- CALLI R15 @emit_out ; emit it
- CALL R3 R15 ; CALL ITERATE()
- POPR R0 R15 ; Restore R0
- RET R15 ; Don't double pop
- :general_recursion_done
- POPR R0 R15 ; Restore F
- POPR R1 R15 ; Restore S
- POPR R0 R15 ; Restore R0
- RET R15
- ;; ceil_log2 function
- ;; Receives INT A in R0
- ;; Returns LOG2(A) in R0
- :ceil_log2
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- FALSE R2 ; RESULT = 0
- SUBI R1 R0 1 ; A - 1
- AND R1 R1 R0 ; A & (A - 1)
- CMPSKIPI.NE R1 0 ; IF (A & (A - 1)) == 0
- LOADI R2 -1 ; RESULT = -1
- :ceil_log2_iter
- JUMP.Z R0 @ceil_log2_done ; IF A > 0
- ADDI R2 R2 1 ; RESULT = RESULT + 1
- SARI R0 1 ; A = A >> 1
- JUMP @ceil_log2_iter ; Loop
- :ceil_log2_done
- MOVE R0 R2 ; Use RESULT
- SARI R0 1 ; RESULT = RESULT >> 1
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; postfix_expr_arrow function
- ;; Receives nothing
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :postfix_expr_arrow
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOADUI R0 $postfix_expr_arrow_string0 ; Our header string
- CALLI R15 @emit_out ; Emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- COPY R0 R8 ; Passing CURRENT_TARGET
- LOAD32 R1 R13 8 ; Using GLOBAL_TOKEN->S
- CALLI R15 @lookup_member ; Look it up
- LOAD32 R2 R0 4 ; Protect I->SIZE
- LOAD32 R8 R0 20 ; CURRENT_TARGET = I->TYPE
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R1 R0 8 ; I->OFFSET
- JUMP.Z R1 @postfix_expr_arrow_offset ; If no offset needed skip the work
- ;; Deal with non-zero offsets
- LOADUI R0 $postfix_expr_arrow_string1 ; Our first prefix
- CALLI R15 @emit_out ; Emit it
- LOADUI R0 $postfix_expr_arrow_string2 ; Our second prefix
- CALLI R15 @emit_out ; Emit it
- MOVE R0 R1 ; Put I->OFFSET in the right place
- CALLI R15 @numerate_number ; Convert to string
- CALLI R15 @emit_out ; Emit it
- LOADUI R0 $postfix_expr_arrow_string3 ; Our postfix
- CALLI R15 @emit_out ; Emit it
- :postfix_expr_arrow_offset
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- JUMP.NZ R0 @postfix_expr_arrow_done
- LOADUI R0 4 ; Compare against 4
- CMPJUMPI.L R0 R2 @postfix_expr_arrow_done
- ;; Deal with special case
- LOADUI R0 $postfix_expr_arrow_string4 ; Our final string
- CALLI R15 @emit_out ; Emit it
- :postfix_expr_arrow_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :postfix_expr_arrow_string0
- "# looking up offset
- "
- :postfix_expr_arrow_string1
- "# -> offset calculation
- "
- :postfix_expr_arrow_string2
- "!0 R1 LOAD32 R15 MEMORY
- ~0 JUMP_ALWAYS
- %"
- :postfix_expr_arrow_string3
- "
- '0' R0 R0 ADD R1 ARITH2_ALWAYS
- "
- :postfix_expr_arrow_string4
- "!0 R0 LOAD32 R0 MEMORY
- "
- ;; postfix_expr_array function
- ;; Receives nothing
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :postfix_expr_array
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- COPY R2 R8 ; ARRAY = CURRENT_TARGET
- LOADUI R0 $expression ; Using EXPRESSION
- CALLI R15 @common_recursion ; Recurse
- MOVE R8 R2 ; CURRENT_TARGET = ARRAY
- LOADUI R2 $postfix_expr_array_string0 ; ASSIGN = load integer
- LOADUI R0 $type_char_indirect_name ; Using "char*"
- LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
- CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
- CMPSKIPI.E R0 0 ; deal with Byte
- LOADUI R2 $postfix_expr_array_string1 ; ASSIGN = load byte
- JUMP.NZ R0 @postfix_expr_array_byte ; Skip if Byte
- ;; Deal with larger than byte
- LOADUI R0 $postfix_expr_array_string2 ; Our shift
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R8 12 ; CURRENT_TARGET->INDIRECT
- LOAD32 R0 R0 4 ; CURRENT_TARGET->INDIRECT->SIZE
- CALLI R15 @ceil_log2 ; LOG2(CURRENT_TARGET->INDIRECT->SIZE)
- CALLI R15 @numerate_number ; Convert to string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $postfix_expr_array_string6 ; Tail of shift
- CALLI R15 @emit_out ; emit it
- :postfix_expr_array_byte
- LOADUI R0 $postfix_expr_array_string3 ; Add the offset
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $postfix_expr_array_string4 ; Our final error message
- LOADUI R1 $close_bracket ; Using "]"
- CALLI R15 @require_match ; Ensure match
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- CMPSKIPI.E R0 0 ; If match
- LOADUI R2 $postfix_expr_array_string5 ; empty string
- MOVE R0 R2 ; What ever string survived
- CALLI R15 @emit_out ; emit it
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :postfix_expr_array_string0
- "!0 R0 LOAD32 R0 MEMORY
- "
- :postfix_expr_array_string1
- "!0 R0 LOAD8 R0 MEMORY
- "
- :postfix_expr_array_string2
- "'0' R0 R0 '"
- :postfix_expr_array_string3
- "'0' R0 R0 ADD R1 ARITH2_ALWAYS
- "
- :postfix_expr_array_string4
- "ERROR in postfix_expr
- Missing ]
- "
- :postfix_expr_array_string5
- ""
- :postfix_expr_array_string6
- "' MOVE_ALWAYS
- "
- ;; postfix_expr_stub function
- ;; Receives nothing
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :postfix_expr_stub
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- LOADUI R0 $open_bracket ; Using "["
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
- JUMP.Z R0 @postfix_expr_stub_next
- ;; Deal with "[" case
- CALLI R15 @postfix_expr_array ; process
- CALLI R15 @postfix_expr_stub ; recurse
- :postfix_expr_stub_next
- LOADUI R0 $arrow_string ; Using "->"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "->"
- JUMP.Z R0 @postfix_expr_stub_done ; clean up
- ;; Deal with "->" case
- CALLI R15 @postfix_expr_arrow ; Process
- CALLI R15 @postfix_expr_stub ; recurse
- :postfix_expr_stub_done
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- ;; postfix_expr function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :postfix_expr
- CALLI R15 @primary_expr ; Walk up the tree
- CALLI R15 @postfix_expr_stub ; Deal with nodes on this level
- RET R15
- ;; additive_expr_stub function
- ;; receives nothing
- ;; returns nothing
- ;; Updates struct token_list*
- :additive_expr_stub
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- ;; Fixed pieces
- LOADUI R0 $postfix_expr ; Set First argument
- LOADUI R3 $additive_expr_stub
- ;; The + bit
- LOADUI R1 $additive_expr_stub_string0 ; Our first operation
- LOADUI R2 $plus_string ; Using "+"
- CALLI R15 @general_recursion
- ;; The - bit
- LOADUI R1 $additive_expr_stub_string1 ; Our second operation
- LOADUI R2 $minus_string ; Using "-"
- CALLI R15 @general_recursion
- ;; The * bit
- LOADUI R1 $additive_expr_stub_string2 ; Our third operation
- LOADUI R2 $multiply_string ; Using "*"
- CALLI R15 @general_recursion
- ;; The / bit
- LOADUI R1 $additive_expr_stub_string3 ; Our fourth operation
- LOADUI R2 $divide_string ; Using "/"
- CALLI R15 @general_recursion
- ;; The % bit
- LOADUI R1 $additive_expr_stub_string4 ; Our fifth operation
- LOADUI R2 $modulus_string ; Using "%"
- CALLI R15 @general_recursion
- ;; The << bit
- LOADUI R1 $additive_expr_stub_string5 ; Our sixth operation
- LOADUI R2 $left_shift_string ; Using "<<"
- CALLI R15 @general_recursion
- ;; The >> bit
- LOADUI R1 $additive_expr_stub_string6 ; Our final operation
- LOADUI R2 $right_shift_string ; Using ">>"
- CALLI R15 @general_recursion
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :additive_expr_stub_string0
- "'0' R0 R0 ADD R1 ARITH2_ALWAYS
- "
- :additive_expr_stub_string1
- "'0' R0 R0 SUB R1 ARITH2_ALWAYS
- "
- :additive_expr_stub_string2
- "'9' R0 '0' R1 MULS R0 ARITH2_ALWAYS
- "
- :additive_expr_stub_string3
- "{LR} PUSH_ALWAYS
- ^~divide CALL_ALWAYS
- {LR} POP_ALWAYS
- "
- :additive_expr_stub_string4
- "{LR} PUSH_ALWAYS
- ^~modulus CALL_ALWAYS
- {LR} POP_ALWAYS
- "
- :additive_expr_stub_string5
- "LEFT R1 R0 R0 SHIFT AUX_ALWAYS
- "
- :additive_expr_stub_string6
- "RIGHT R1 R0 R0 SHIFT AUX_ALWAYS
- "
- ;; additive_expr function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :additive_expr
- CALLI R15 @postfix_expr ; Walk up the tree
- CALLI R15 @additive_expr_stub ; Deal with nodes at this level
- RET R15
- ;; relational_expr_stub function
- ;; receives nothing
- ;; returns nothing
- ;; Updates struct token_list*
- :relational_expr_stub
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- ;; Fixed pieces
- LOADUI R0 $additive_expr ; Set First argument
- LOADUI R3 $relational_expr_stub
- ;; The < bit
- LOADUI R1 $relational_expr_stub_string0 ; Our first operation
- LOADUI R2 $less_than_string ; Using "<"
- CALLI R15 @general_recursion
- ;; The <= bit
- LOADUI R1 $relational_expr_stub_string1 ; Our second operation
- LOADUI R2 $less_than_equal_string ; Using "<="
- CALLI R15 @general_recursion
- ;; The >= bit
- LOADUI R1 $relational_expr_stub_string2 ; Our third operation
- LOADUI R2 $greater_than_equal_string ; Using ">="
- CALLI R15 @general_recursion
- ;; The > bit
- LOADUI R1 $relational_expr_stub_string3 ; Our fourth operation
- LOADUI R2 $greater_than_string ; Using ">"
- CALLI R15 @general_recursion
- ;; The == bit
- LOADUI R1 $relational_expr_stub_string4 ; Our fifth operation
- LOADUI R2 $equal_to_string ; Using "=="
- CALLI R15 @general_recursion
- ;; The != bit
- LOADUI R1 $relational_expr_stub_string5 ; Our final operation
- LOADUI R2 $not_equal_string ; Using "!="
- CALLI R15 @general_recursion
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :relational_expr_stub_string0
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_L
- "
- :relational_expr_stub_string1
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_LE
- "
- :relational_expr_stub_string2
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_GE
- "
- :relational_expr_stub_string3
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_G
- "
- :relational_expr_stub_string4
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_EQUAL
- "
- :relational_expr_stub_string5
- "'0' R0 CMP R1 AUX_ALWAYS
- !0 R0 LOADI8_ALWAYS
- !1 R0 LOADI8_NE
- "
- ;; relational_expr function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :relational_expr
- CALLI R15 @additive_expr ; Walk up the tree
- CALLI R15 @relational_expr_stub ; Deal with nodes at this level
- RET R15
- ;; relational_expr_stub function
- ;; receives nothing
- ;; returns nothing
- ;; Updates struct token_list*
- :bitwise_expr_stub
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- ;; Fixed pieces
- LOADUI R0 $relational_expr ; Set First argument
- LOADUI R3 $bitwise_expr_stub
- ;; The & bit
- LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
- LOADUI R2 $bitwise_and ; Using "&"
- CALLI R15 @general_recursion
- ;; The && bit
- LOADUI R1 $bitwise_expr_stub_string0 ; Our first operation
- LOADUI R2 $logical_and ; Using "&&"
- CALLI R15 @general_recursion
- ;; The | bit
- LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
- LOADUI R2 $bitwise_or ; Using "|"
- CALLI R15 @general_recursion
- ;; The || bit
- LOADUI R1 $bitwise_expr_stub_string1 ; Our second operation
- LOADUI R2 $logical_or ; Using "||"
- CALLI R15 @general_recursion
- ;; The ^ bit
- LOADUI R1 $bitwise_expr_stub_string2 ; Our second operation
- LOADUI R2 $bitwise_xor ; Using "^"
- CALLI R15 @general_recursion
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :bitwise_expr_stub_string0
- "NO_SHIFT R0 R0 AND R1 ARITH2_ALWAYS
- "
- :bitwise_expr_stub_string1
- "NO_SHIFT R0 R0 OR R1 AUX_ALWAYS
- "
- :bitwise_expr_stub_string2
- "'0' R0 R0 XOR R1 ARITH2_ALWAYS
- "
- ;; bitwise_expr function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :bitwise_expr
- CALLI R15 @relational_expr ; Walk up the tree
- CALLI R15 @bitwise_expr_stub ; Deal with nodes at this level
- RET R15
- ;; primary_expr function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :primary_expr
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- LOADUI R0 $sizeof_string ; Load "sizeof"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "sizeof"
- JUMP.Z R0 @primary_expr_negate ; Guess not
- ;; Deal with sizeof expression
- CALLI R15 @unary_expr_sizeof ; Do real work
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_negate
- LOADU8 R0 R1 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 45 ; IF GLOBAL_TOKEN->S[0] == '-'
- JUMP @primary_expr_bang ; If not try '!'
- ;; Deal with -a and -4 expressions
- LOADUI R0 $primary_expr_str0 ; Load HEADER
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $primary_expr ; Using PRIMARY_EXPR
- CALLI R15 @common_recursion ; Recurse
- LOADUI R0 $primary_expr_str1 ; add footer
- CALLI R15 @emit_out ; emit it
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_bang
- CMPSKIPI.E R0 33 ; IF GLOBAL_TOKEN->S[0] == "!"
- JUMP @primary_expr_nested ; If not try '('
- ;; deal with !a expressions
- LOADUI R0 $primary_expr_str2 ; Load HEADER
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $postfix_expr ; Using POSTFIX_EXPR
- CALLI R15 @common_recursion ; Recurse
- LOADUI R0 $primary_expr_str3 ; add footer
- CALLI R15 @emit_out ; emit it
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_nested
- CMPSKIPI.E R0 40 ; IF GLOBAL_TOKEN->S[0] == '('
- JUMP @primary_expr_ch ; If not try 'char'
- ;; Deal with ( expr )
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- CALLI R15 @expression ; Recurse
- LOADUI R0 $primary_expr_str4 ; Using error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Make sure we have closing match
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_ch
- CMPSKIPI.E R0 39 ; IF GLOBAL_TOKEN->S[0] == '\''
- JUMP @primary_expr_st ; If not try "string"
- ;; Deal with 'char'
- CALLI R15 @primary_expr_char ; Collect char
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_st
- CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
- JUMP @primary_expr_var ; If not try variables
- ;; deal with "string"
- CALLI R15 @primary_expr_string ; Collect string
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_var
- LOADUI R1 $variable_chars ; Using a-z+A-Z+_
- CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in a-z+A-Z+_
- JUMP.Z R0 @primary_expr_num
- ;; Deal with foo TODO
- CALLI R15 @primary_expr_variable ; deal with names
- JUMP @primary_expr_done ; Wrap up
- :primary_expr_num
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- LOADUI R1 $digit_chars ; Using 0-9
- CALLI R15 @in_set ; IF GLOBAL_TOKEN->S[0] in 0-9
- JUMP.Z R0 @primary_expr_failure ; Fail HARD
- ;; Deal with 5
- CALLI R15 @primary_expr_number ; deal with number
- :primary_expr_done
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :primary_expr_str0
- "!0 R0 LOADI8_ALWAYS
- "
- :primary_expr_str1
- "'0' R0 R0 SUB R1 ARITH2_ALWAYS
- "
- :primary_expr_str2
- "!1 R0 LOADI8_ALWAYS
- "
- :primary_expr_str3
- "'0' R0 R0 XOR R1 ARITH2_ALWAYS
- "
- :primary_expr_str4
- "Error in Primary expression
- Didn't get )
- "
- ;; expression function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :expression
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- CALLI R15 @bitwise_expr ; Check for more primitives first
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- JUMP.Z R0 @expression_done ; Be done
- ;; Determine store type
- LOADUI R3 $expression_string1 ; Assuming the default of STORE CHAR
- ;; First possible reason for INT
- LOADUI R0 $close_bracket ; Using "]"
- LOAD32 R1 R13 4 ; GLOBAL_TOKEN->PREV
- LOAD32 R1 R1 8 ; GLOBAL_TOKEN->PREV->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->PREV-> == "]"
- CMPSKIPI.NE R0 0 ; IF FALSE
- LOADUI R3 $expression_string0 ; STORE INTEGER
- ;; Second possible reason for INTeger
- LOADUI R0 $type_char_indirect_name ; Using "char*"
- LOAD32 R1 R8 24 ; CURRENT_TARGET->NAME
- CALLI R15 @match ; IF CURRENT_TARGET->NAME == "char*"
- CMPSKIPI.NE R0 0 ; IF FALSE
- LOADUI R3 $expression_string0 ; STORE INTEGER
- ;; Recurse to evaluate expression being stored
- LOADUI R0 $expression ; Using expression
- CALLI R15 @common_recursion ; Perform common recursion
- ;; Put our string and clean up
- MOVE R0 R3 ; Using our STORED string
- CALLI R15 @emit_out ; emit it
- FALSE R8 ; CURRENT_TARGET = NULL
- :expression_done
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :expression_string0
- "!0 R0 STORE32 R1 MEMORY
- "
- :expression_string1
- "!0 R0 STORE8 R1 MEMORY
- "
- ;; process_if function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_if
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOADR32 R0 @current_count ; Using CURRENT_COUNT
- ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
- STORER32 R1 @current_count ; Update CURRENT_COUNT
- CALLI R15 @numerate_number ; Convert CURRENT_COUNT to string
- MOVE R2 R0 ; Protect our string
- LOADUI R0 $process_if_string0 ; using first string
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- COPY R1 R2 ; Using our current count string
- CALLI R15 @uniqueID_out ; Add unique identifier
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $process_if_string1 ; Our first error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Make sure we have what we need
- CALLI R15 @expression ; Recurse to get our boolean expression
- LOADUI R0 $process_if_string2 ; Our test and jump
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- COPY R1 R2 ; Using our current count string
- CALLI R15 @uniqueID_out ; Add unique identifier
- LOADUI R0 $process_if_string7 ; Our test and jump
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $process_if_string3 ; Our second error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Make sure we have what we need
- CALLI R15 @statement ; Collect our if statement
- LOADUI R0 $process_if_string4 ; Our jump over else
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- COPY R1 R2 ; Using our current count string
- CALLI R15 @uniqueID_out ; Add unique identifier
- LOADUI R0 $process_if_string5 ; Our else label
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; Add unique identifier
- LOADUI R0 $else_string ; Using "else"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "else"
- JUMP.Z R0 @process_if_else ; Looks like no else
- ;; Deal with else
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- CALLI R15 @statement ; Grab else statement
- :process_if_else
- LOADUI R0 $process_if_string6 ; Our jump over else
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- COPY R1 R2 ; Using our current count string
- CALLI R15 @uniqueID_out ; Add unique identifier
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :process_if_string0
- "# IF_"
- :process_if_string1
- "ERROR in process_if
- MISSING (
- "
- :process_if_string2
- "!0 CMPI8 R0 IMM_ALWAYS
- ^~ELSE_"
- :process_if_string3
- "ERROR in process_if
- MISSING )
- "
- :process_if_string4
- "^~_END_IF_"
- :process_if_string5
- " JUMP_ALWAYS
- :ELSE_"
- :process_if_string6
- ":_END_IF_"
- :process_if_string7
- " JUMP_EQUAL
- "
- ;; save_break_frame microfunction
- ;; Overwrites R0 and R1
- ;; Saves break frame on stack
- ;; Returns to caller
- :save_break_frame
- POPR R1 R15 ; Save return address
- LOADR32 R0 @break_frame ; Obtain BREAK_FRAME
- PUSHR R0 R15 ; Protect BREAK_FRAME
- LOADR32 R0 @break_target_head ; obtain HEAD
- PUSHR R0 R15 ; Protect HEAD
- LOADR32 R0 @break_target_func ; obtain FUNC
- PUSHR R0 R15 ; Protect FUNC
- LOADR32 R0 @break_target_num ; obtain NUM
- PUSHR R0 R15 ; Protect NUM
- PUSHR R1 R15 ; Set where we are returning to
- RET R15
- ;; restore_break_frame microfunction
- ;; Overwrites R0 and R1
- ;; Restores break frame from stack
- ;; Returns to caller
- :restore_break_frame
- POPR R1 R15 ; Save return address
- POPR R0 R15 ; obtain NUM
- STORER32 R0 @break_target_num ; Restore NUM
- POPR R0 R15 ; obtain FUNC
- STORER32 R0 @break_target_func ; Restore FUNC
- POPR R0 R15 ; obtain HEAD
- STORER32 R0 @break_target_head ; Restore HEAD
- POPR R0 R15 ; obtain BREAK_FRAME
- STORER32 R0 @break_frame ; Restore BREAK_FRAME
- PUSHR R1 R15 ; Set where we are returning to
- RET R15
- ;; set_break_frame microfunction
- ;; Receives char* num in R0, char* head in R1
- ;; Overwrites R0
- ;; Sets break frame using
- ;; R9 holding FUNC
- ;; Returns to calling function
- :set_break_frame
- STORER32 R1 @break_target_head ; update BREAK_TARGET_HEAD
- STORER32 R0 @break_target_num ; Update BREAK_TARGET_NUM
- LOAD32 R0 R9 4 ; Using FUNCTION->LOCALS
- STORER32 R0 @break_frame ; update BREAK_FRAME
- LOAD32 R0 R9 8 ; Using FUNCTION->S
- STORER32 R0 @break_target_func ; update BREAK_TARGET_FUNC
- RET R15
- ;; process_for function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_for
- PUSHR R2 R15 ; Protect R2
- PUSHR R1 R15 ; Protect R1
- PUSHR R0 R15 ; Protect R0
- CALLI R15 @save_break_frame ; Save break frame
- LOADR32 R0 @current_count ; Using CURRENT_COUNT
- ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
- STORER32 R1 @current_count ; Update CURRENT_COUNT
- CALLI R15 @numerate_number ; Convert to string
- COPY R2 R0 ; Protect NUMBER_STRING
- LOADUI R1 $process_for_string0 ; Get new HEAD
- CALLI R15 @set_break_frame ; Set the break frame values
- LOADUI R0 $process_for_string1 ; Our comment header
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $process_for_string2 ; Our first error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Verify match
- LOADUI R0 $semicolon ; Using ";"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S -- ";"
- CMPSKIPI.NE R0 0 ; If GLOBAL_TOKEN->S != ";"
- CALLI R15 @expression ; Skip that step
- LOADUI R0 $process_for_string3 ; Our comment header
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string4 ; Our second error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Verify match
- CALLI R15 @expression ; TEST logic required
- LOADUI R0 $process_for_string5 ; Our comment header
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string6 ; Our comment header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string7 ; Our comment header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string8 ; Our third error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Verify match
- CALLI R15 @expression ; Iterator logic
- LOADUI R0 $process_for_string9 ; Our comment header
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string10 ; Our comment header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string11 ; Our final error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Verify match
- CALLI R15 @statement ; Main body
- LOADUI R0 $process_for_string12 ; Our comment header
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_for_string13 ; Our comment header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- CALLI R15 @restore_break_frame ; Restore break frame
- POPR R0 R15 ; Restore R0
- POPR R1 R15 ; Restore R1
- POPR R2 R15 ; Restore R2
- RET R15
- :process_for_string0
- "FOR_END_"
- :process_for_string1
- "# FOR_initialization_"
- :process_for_string2
- "ERROR in process_for
- MISSING (
- "
- :process_for_string3
- ":FOR_"
- :process_for_string4
- "ERROR in process_for
- MISSING ;1
- "
- :process_for_string5
- "!0 CMPI8 R0 IMM_ALWAYS
- ^~FOR_END_"
- :process_for_string6
- " JUMP_EQUAL
- ^~FOR_THEN_"
- :process_for_string7
- " JUMP_ALWAYS
- :FOR_ITER_"
- :process_for_string8
- "ERROR in process_for
- MISSING ;2
- "
- :process_for_string9
- "^~FOR_"
- :process_for_string10
- " JUMP_ALWAYS
- :FOR_THEN_"
- :process_for_string11
- "ERROR in process_for
- MISSING )
- "
- :process_for_string12
- "^~FOR_ITER_"
- :process_for_string13
- " JUMP_ALWAYS
- :FOR_END_"
- ;; process_do function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_do
- PUSHR R2 R15 ; Protect R2
- PUSHR R1 R15 ; Protect R1
- PUSHR R0 R15 ; Protect R0
- CALLI R15 @save_break_frame ; Save break frame
- LOADR32 R0 @current_count ; Using CURRENT_COUNT
- ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
- STORER32 R1 @current_count ; Update CURRENT_COUNT
- CALLI R15 @numerate_number ; Convert to string
- COPY R2 R0 ; Protect NUMBER_STRING
- LOADUI R1 $process_do_string0 ; Using our desired head
- CALLI R15 @set_break_frame ; Set the break frame values
- LOADUI R0 $process_do_string1 ; Our label
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- CALLI R15 @statement ; Collect our Do statement
- LOADUI R0 $process_do_string2 ; our first error message
- LOADUI R1 $while_string ; Using "while"
- CALLI R15 @require_match ; Check for match
- LOADUI R0 $process_do_string3 ; our second error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Check for match
- CALLI R15 @expression ; Our logical expression
- LOADUI R0 $process_do_string4 ; our third error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Check for match
- LOADUI R0 $process_do_string5 ; our final error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Check for match
- LOADUI R0 $process_do_string6 ; Our test string
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Put NUMBER_STRING in right place
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_do_string7 ; Our end label string
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- CALLI R15 @restore_break_frame ; Restore break frame
- POPR R0 R15 ; Restore R0
- POPR R1 R15 ; Restore R1
- POPR R2 R15 ; Restore R2
- RET R15
- :process_do_string0
- "DO_END_"
- :process_do_string1
- ":DO_"
- :process_do_string2
- "ERROR in process_do
- MISSING while
- "
- :process_do_string3
- "ERROR in process_do
- MISSING (
- "
- :process_do_string4
- "ERROR in process_do
- MISSING )
- "
- :process_do_string5
- "ERROR in process_do
- MISSING ;
- "
- :process_do_string6
- "!0 CMPI8 R0 IMM_ALWAYS
- ^~DO_"
- :process_do_string7
- " JUMP_NE
- :DO_END_"
- ;; process_while function
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_while
- PUSHR R2 R15 ; Protect R2
- PUSHR R1 R15 ; Protect R1
- PUSHR R0 R15 ; Protect R0
- CALLI R15 @save_break_frame ; Save break frame
- LOADR32 R0 @current_count ; Using CURRENT_COUNT
- ADDUI R1 R0 1 ; CURRENT_COUNT = CURRENT_COUNT + 1
- STORER32 R1 @current_count ; Update CURRENT_COUNT
- CALLI R15 @numerate_number ; Convert to string
- COPY R2 R0 ; Protect NUMBER_STRING
- LOADUI R1 $process_while_string0 ; Set HEAD
- CALLI R15 @set_break_frame ; Set the break frame values
- LOADUI R0 $process_while_string1 ; Our head label
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $process_while_string2 ; Our first error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Check for match
- CALLI R15 @expression ; Collect test expression
- LOADUI R0 $process_while_string3 ; Our test and jump
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_while_string4 ; Our trailing comment
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_while_string5 ; Our first error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Check for match
- CALLI R15 @statement ; Collect our loop statement
- LOADUI R0 $process_while_string6 ; Our test and jump
- CALLI R15 @emit_out ; emit it
- COPY R1 R2 ; Using NUMBER_STRING
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- LOADUI R0 $process_while_string7 ; Our trailing comment
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; FUNCTION->S
- CALLI R15 @uniqueID_out ; emit it
- CALLI R15 @restore_break_frame ; Restore break frame
- POPR R0 R15 ; Restore R0
- POPR R1 R15 ; Restore R1
- POPR R2 R15 ; Restore R2
- RET R15
- :process_while_string0
- "END_WHILE_"
- :process_while_string1
- ":WHILE_"
- :process_while_string2
- "ERROR in process_while
- MISSING (
- "
- :process_while_string3
- "!0 CMPI8 R0 IMM_ALWAYS
- ^~END_WHILE_"
- :process_while_string4
- " JUMP_EQUAL # THEN_while_"
- :process_while_string5
- "ERROR in process_while
- MISSING )
- "
- :process_while_string6
- "^~WHILE_"
- :process_while_string7
- " JUMP_ALWAYS
- :END_WHILE_"
- ;; return_result function
- ;; Receives nothing
- ;; Returns nothing
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- :return_result
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
- CALLI R15 @expression ; Evaluate expression
- LOADUI R0 $return_result_string0 ; Using or error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Require a match to ";"
- LOADUI R0 $return_result_string1 ; Our pop command
- LOAD32 R1 R9 4 ; FUNCTION->LOCALS
- :return_result_iter
- JUMP.Z R1 @return_result_done ; Be done when we hit NULL
- CALLI R15 @emit_out ; Put the string every iteration
- LOAD32 R1 R1 0 ; I = I->NEXT
- JUMP @return_result_iter ; Keep looping
- :return_result_done
- LOADUI R0 $return_result_string2 ; Our footer
- CALLI R15 @emit_out ; emit it
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :return_result_string0
- "ERROR in return_result
- MISSING ;
- "
- :return_result_string1
- "{R1} POP_ALWAYS # _return_result_locals
- "
- :return_result_string2
- "'1' LR RETURN
- "
- ;; process_break function
- ;; Receives nothing
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_break
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOADR32 R0 @break_target_head ; BREAK_TARGET_HEAD
- JUMP.NZ R0 @process_break_NON_NULL
- ;; Deal with NULL == BREAK_TARGET_HEAD
- LOADUI R0 $process_break_string0 ; Our first error message
- FALSE R1 ; Write for User
- CALLI R15 @file_print ; write it
- CALLI R15 @line_error ; Give useful info
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @file_print ; Print it
- HALT
- :process_break_NON_NULL
- LOADR32 R2 @break_frame ; BREAK_FRAME
- LOAD32 R1 R9 4 ; I = FUNCTION->LOCALS
- LOADUI R0 $process_break_string1 ; Our pop string
- :process_break_iter
- CMPJUMPI.E R1 R2 @process_break_done ; IF I == BREAK_FRAME
- JUMP.Z R1 @process_break_done ; IF NULL == I break
- CALLI R15 @emit_out ; emit pop
- LOAD32 R1 R1 0 ; I = I->NEXT
- JUMP @process_break_iter ; Loop
- :process_break_done
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $process_break_string2 ; Our jump string
- CALLI R15 @emit_out ; emit it
- LOADR32 R0 @break_target_head ; Our HEAD string
- CALLI R15 @emit_out ; emit it
- LOADR32 R0 @break_target_func ; Our FUNC string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $underline ; Using "_"
- CALLI R15 @emit_out ; emit it
- LOADR32 R0 @break_target_num ; Our NUM string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $process_break_string4 ; Using final jump string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $process_break_string3 ; Our final error string
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Make sure we get that match
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :process_break_string0
- "Not inside of a loop or case statement
- "
- :process_break_string1
- "{R1} POP_ALWAYS # break_cleanup_locals
- "
- :process_break_string2
- "^~"
- :process_break_string3
- "ERROR in break statement
- Missing ;
- "
- :process_break_string4
- " JUMP_ALWAYS
- "
- :break_frame
- NOP
- :break_target_head
- NOP
- :break_target_func
- NOP
- :break_target_num
- NOP
- ;; process_asm function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :process_asm
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- ;; First required match
- LOADUI R0 $process_asm_string0 ; Using our First error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Make sure of our required match
- :process_asm_iter
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 34 ; IF GLOBAL_TOKEN->S[0] == '"'
- JUMP @process_asm_done ; Otherwise be done
- ;; Add block of assembly
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- ADDUI R0 R0 1 ; GLOBAL_TOKEN->S + 1
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @process_asm_iter
- :process_asm_done
- LOADUI R0 $process_asm_string1 ; Using our First error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Make sure of our required match
- LOADUI R0 $process_asm_string2 ; Using our First error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Make sure of our required match
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :process_asm_string0
- "ERROR in process_asm
- MISSING (
- "
- :process_asm_string1
- "ERROR in process_asm
- MISSING )
- "
- :process_asm_string2
- "ERROR in process_asm
- MISSING ;
- "
- ;; recursive_statement function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :recursive_statement
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R3 R9 4 ; FRAME = FUNCTION->LOCALS
- :recursive_statement_iter
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- LOADUI R0 $close_curly_brace ; '}'
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "}"
- JUMP.NZ R0 @recursive_statement_cleanup
- ;; Lets collect those statements
- CALLI R15 @statement ; Collect next statement
- JUMP @recursive_statement_iter ; Iterate
- :recursive_statement_cleanup
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R1 R12 8 ; OUT->S
- LOADUI R0 $recursive_statement_string0 ; "RETURN\n"
- CALLI R15 @match ; IF OUT->S == "RETURN\n"
- JUMP.NZ R0 @recursive_statement_done ; Save some work
- ;; Lets pop them all off
- LOAD32 R2 R9 4 ; FUNC->LOCALS
- LOADUI R0 $recursive_statement_string1 ; Our POP string
- :recursive_statement_pop
- CMPJUMPI.E R2 R3 @recursive_statement_done
- CALLI R15 @emit_out ; emit it
- LOAD32 R2 R2 0 ; I = I->NEXT
- JUMP.NZ R2 @recursive_statement_pop ; Keep looping
- :recursive_statement_done
- STORE32 R3 R9 4 ; FUNC->LOCALS = FRAME
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :recursive_statement_string0
- "'1' LR RETURN
- "
- :recursive_statement_string1
- "{R1} POP_ALWAYS # _recursive_statement_locals
- "
- ;; statement function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :statement
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 123 ; If GLOBAL_TOKEN->S[0] != '{'
- JUMP @statement_label ; Try next match
- ;; Deal with { statements }
- CALLI R15 @recursive_statement
- JUMP @statement_done ; All done
- :statement_label
- CMPSKIPI.E R0 58 ; If GLOBAL_TOKEN->S[0] != ':'
- JUMP @statement_collect_local ; Try next match
- ;; Deal with :label
- LOAD32 R0 R13 8 ; Using GLOBAL_TOKEN->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $statement_string0 ; Using label string
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @statement_done ; Move on to next thing
- :statement_collect_local
- LOADUI R0 $struct ; Using "struct"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "struct"
- JUMP.NZ R0 @statement_collect_local_0
- ;; Otherwise check if it is a primitive
- LOADUI R0 $prim_types ; Using the Primitive types list
- SWAP R0 R1 ; Put in correct order
- CALLI R15 @lookup_type ; Check if a primitive type
- JUMP.Z R0 @statement_process_if ; If not try the next one
- :statement_collect_local_0
- CALLI R15 @collect_local ; Collect the local
- JUMP @statement_done ; And move on
- :statement_process_if
- LOADUI R0 $if_string ; Using "if"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "if"
- JUMP.Z R0 @statement_process_do
- CALLI R15 @process_if ; Collect that if statement
- JUMP @statement_done ; Move on to next thing
- :statement_process_do
- LOADUI R0 $do_string ; Using "do"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "do"
- JUMP.Z R0 @statement_process_while
- CALLI R15 @process_do ; Collect that do statement
- JUMP @statement_done ; Move on to next thing
- :statement_process_while
- LOADUI R0 $while_string ; Using "while"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "while"
- JUMP.Z R0 @statement_process_for
- CALLI R15 @process_while ; Collect that while statement
- JUMP @statement_done ; Move on to next thing
- :statement_process_for
- LOADUI R0 $for_string ; Using "for"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "for"
- JUMP.Z R0 @statement_process_asm
- CALLI R15 @process_for ; Collect that FOR statement
- JUMP @statement_done ; Move on to next thing
- :statement_process_asm
- LOADUI R0 $asm_string ; Using "asm"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "asm"
- JUMP.Z R0 @statement_goto
- CALLI R15 @process_asm ; Collect that ASM statement
- JUMP @statement_done ; Move on to next thing
- :statement_goto
- LOADUI R0 $goto_string ; Using "goto"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "goto"
- JUMP.Z R0 @statement_return_result
- ;; Deal with goto label:
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $statement_string1 ; Using our JUMP string
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $statement_string4 ; Using jump terminator
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $statement_string2 ; Using our error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Make sure of our required match
- JUMP @statement_done ; Move on
- :statement_return_result
- LOADUI R0 $return_string ; Using "return"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "return"
- JUMP.Z R0 @statement_break
- ;; Deal with return statements in functions
- CALLI R15 @return_result ; Do all of the work
- JUMP @statement_done ; Move on to next
- :statement_break
- LOADUI R0 $break_string ; Using "break"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "break"
- JUMP.Z R0 @statement_continue
- ;; Let break function deal with updating out
- CALLI R15 @process_break ; Do all the work
- JUMP @statement_done ; Move on to next
- :statement_continue
- LOADUI R0 $continue_string ; Using "continue"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "continue"
- JUMP.Z R0 @statement_expression
- ;; Simple Continue compatibility
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $statement_string3 ; Using our continue comment string
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $statement_string2 ; Using our error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Make sure of our required match
- JUMP @statement_done ; Move on
- :statement_expression
- CALLI R15 @expression ; Do expression evaluation
- LOADUI R0 $statement_string2 ; Load our error message
- LOADUI R1 $semicolon ; use ";"
- CALLI R15 @require_match ; Make sure GLOBAL_TOKEN-> == ";"
- :statement_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :statement_string0
- " #C goto label
- "
- :statement_string1
- "^~"
- :statement_string2
- "ERROR in statement
- MISSING ;
- "
- :statement_string3
- "
- #continue statement
- "
- :statement_string4
- " JUMP_ALWAYS
- "
- ;; collect_local function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :collect_local
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- CALLI R15 @type_name ; Get it's type
- MOVE R1 R0 ; Prepare for call
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOAD32 R2 R9 4 ; FUNC->LOCALS
- CALLI R15 @sym_declare ; SET A
- MOVE R2 R0 ; Protect A
- ;; Figure out depth
- LOADUI R0 $main_string ; Using "main"
- LOAD32 R1 R9 8 ; FUNC->S
- CALLI R15 @match ; IF FUNC->S == "main"
- JUMP.Z R0 @collect_local_0 ; Try next
- LOAD32 R0 R9 4 ; FUNC->LOCALS
- JUMP.NZ R0 @collect_local_0 ; Try next
- LOADI R0 16 ; The default depth for main
- STORE32 R0 R2 16 ; A->DEPTH = 16
- JUMP @collect_local_output ; Deal with header
- :collect_local_0
- LOAD32 R0 R9 16 ; FUNC->ARGS
- JUMP.NZ R0 @collect_local_1 ; Try Next
- LOAD32 R0 R9 4 ; FUNC->LOCALS
- JUMP.NZ R0 @collect_local_1 ; Try Next
- LOADI R0 8 ; The default depth for foo()
- STORE32 R0 R2 16 ; A->DEPTH = 8
- JUMP @collect_local_output ; Deal with header
- :collect_local_1
- LOAD32 R0 R9 4 ; FUNC->LOCALS
- JUMP.NZ R0 @collect_local_2 ; Try Next
- LOAD32 R0 R9 16 ; FUNC->ARGS
- LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
- ADDI R0 R0 8 ; DEPTH = FUNC->ARGS->DEPTH + 8
- STORE32 R0 R2 16 ; A->DEPTH = DEPTH
- JUMP @collect_local_output ; Deal with header
- :collect_local_2
- LOAD32 R0 R9 4 ; FUNC->LOCALS
- LOAD32 R0 R0 16 ; FUNC->LOCALS->DEPTH
- ADDI R0 R0 4 ; DEPTH = FUNC->LOCALS->DEPTH + 4
- STORE32 R0 R2 16 ; A->DEPTH = DEPTH
- :collect_local_output
- STORE32 R2 R9 4 ; FUNC->LOCALS = A
- ;; Output header
- LOADUI R0 $collect_local_string0 ; Starting with the comment
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R2 8 ; A->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- ;; Deal with possible assignment
- LOADUI R0 $equal ; Using "="
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "="
- JUMP.Z R0 @collect_local_nonassign
- ;; Deal with assignment of the local
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- CALLI R15 @expression ; Update OUT with the evaluation of the Expression
- :collect_local_nonassign
- LOADUI R0 $collect_local_string1 ; Our error message
- LOADUI R1 $semicolon ; Using ";"
- CALLI R15 @require_match ; Make sure GLOBAL_TOKEN->S == ";"
- ;; Final Footer
- LOADUI R0 $collect_local_string2 ; Add our PUSH statement
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R2 8 ; A->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :collect_local_string0
- "# Defining local "
- :collect_local_string1
- "ERROR in collect_local
- Missing ;
- "
- :collect_local_string2
- "{R0} PUSH_ALWAYS #"
- ;; collect_arguments function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :collect_arguments
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- :collect_arguments_iter
- LOADUI R0 $close_paren ; Using ")"
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == ")"
- JUMP.NZ R0 @collect_arguments_done ; Be done
- ;; Collect the arguments
- CALLI R15 @type_name ; Get what type we are working with
- MOVE R1 R0 ; Put TYPE where it will be used
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ')'
- JUMP @collect_arguments_iter3 ; foo(int,char,void) doesn't need anything done
- ;; Check for foo(int a,...)
- CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] == ','
- JUMP @collect_arguments_iter3 ; Looks like final case
- ;; Deal with foo(int a, ...)
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOAD32 R2 R9 16 ; FUNC->ARGUMENTS
- CALLI R15 @sym_declare ; Get A
- MOVE R2 R0 ; Get A out of the way
- :collect_arguments_func
- LOAD32 R0 R9 16 ; FUNC->ARGS
- CMPSKIPI.E R0 0 ; IF NULL == FUNC->ARGS
- LOAD32 R0 R0 16 ; FUNC->ARGS->DEPTH
- ADDI R0 R0 4 ; FUNC->ARGS->DEPTH + 4 or NULL + 4 (4)
- STORE32 R0 R2 16 ; A->DEPTH = VALUE
- :collect_arguments_iter2
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- STORE32 R2 R9 16 ; FUNC->ARGUMENTS = A
- :collect_arguments_iter3
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.NE R0 44 ; IF GLOBAL_TOKEN->S[0] == ','
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @collect_arguments_iter ; Keep looping
- :collect_arguments_done
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- ;; declare_function function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; and struct token_list* global_list in R10
- ;; SETS R9 to struct token_list* FUNC
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :declare_function
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- FALSE R0 ; Using Zero
- STORER32 R0 @current_count ; CURRENT_COUNT = 0
- LOAD32 R0 R13 4 ; GLOBAL_TOKEN->PREV
- LOAD32 R0 R0 8 ; GLOBAL_TOKEN->PREV->S
- FALSE R1 ; Passing NULL
- LOADR32 R2 @global_function_list ; where the global function list is located
- CALLI R15 @sym_declare ; declare FUNC
- STORER32 R0 @global_function_list ; GLOBAL_FUNCTION_LIST = FUNC
- MOVE R9 R0 ; SETS FUNC
- CALLI R15 @collect_arguments ; Collect function arguments
- LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R2 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.NE R0 59 ; IF GLOBAL_TOKEN->S[0] == ';'
- JUMP @declare_function_prototype ; Don't waste time
- ;; Looks like it is an actual function definition
- LOADUI R0 $declare_function_string0 ; Using first string
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; Using FUNC->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $declare_function_string1 ; Using second string
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R9 8 ; Using FUNC->S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- :declare_function_nonmain
- FALSE R1 ; Cleaning up before call
- CALLI R15 @statement ; Collect the statement
- ;; Prevent Duplicate Returns
- LOAD32 R1 R12 8 ; OUT->S
- LOADUI R0 $declare_function_string2 ; Our final string
- CALLI R15 @match ; Check for Match
- JUMP.NZ R0 @declare_function_done ; Clean up
- ;; Deal with adding the return
- LOADUI R0 $declare_function_string2 ; Our final string
- CALLI R15 @emit_out ; emit it
- :declare_function_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :declare_function_prototype
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @declare_function_done ; Clean up
- :declare_function_string0
- "# Defining function "
- :declare_function_string1
- ":FUNCTION_"
- :declare_function_string2
- "'1' LR RETURN
- "
- :current_count
- NOP
- ;; program function
- ;; Receives struct token_list* global_token in R13,
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; and struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :program
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- :program_iter
- JUMP.Z R13 @program_done ; Looks like we read all the tokens
- LOADUI R0 $constant ; Using the constant string
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; Check if they match
- JUMP.Z R0 @program_type ; Looks like not
- ;; Deal with CONSTANT case
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- FALSE R1 ; Set NULL
- LOADR32 R2 @global_constant_list ; GLOBAL_CONSTANTS_LIST
- CALLI R15 @sym_declare ; Declare the global constant
- STORER32 R0 @global_constant_list ; Update global constant
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- STORE32 R13 R0 16 ; GLOBAL_CONSTANT_LIST->ARGUMENTS = GLOBAL_TOKEN
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @program_iter ; Loop again
- :program_type
- CALLI R15 @type_name ; Get the type
- JUMP.Z R0 @program_iter ; If newly defined type iterate
- ;; Looks like we got a defined type
- MOVE R1 R0 ; Put the type where it can be used
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADUI R3 $global_symbol_list ; Get address of global symbol list
- LOAD32 R2 R3 0 ; GLOBAL_SYMBOLS_LIST
- CALLI R15 @sym_declare ; Declare that global symbol
- STORE32 R0 R3 0 ; Update global symbol list
- LOAD32 R3 R13 8 ; GLOBAL_TOKEN->S
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $semicolon ; Get semicolon string
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; Check if they match
- JUMP.Z R0 @program_function ; If not a match
- ;; Deal with case of TYPE NAME;
- COPY R1 R10 ; Using GLOBALS_LIST
- LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Move new GLOBALS_LIST into Place
- MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Move new GLOBALS_LIST into Place
- LOADUI R0 $program_string1 ; Using the NOP postfix
- CALLI R15 @emit ; emit it
- MOVE R10 R0 ; Move new GLOBALS_LIST into Place
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- JUMP @program_iter
- :program_function
- LOADUI R0 $open_paren ; Get open paren string
- CALLI R15 @match ; Check if they match
- JUMP.Z R0 @program_assign ; If not a match
- ;; Deal with case of TYPE NAME(...)
- CALLI R15 @declare_function
- JUMP @program_iter
- :program_assign
- LOADUI R0 $equal ; Get equal string
- CALLI R15 @match ; Check if they match
- JUMP.Z R0 @program_error ; If not a match
- COPY R1 R10 ; Using GLOBALS_LIST
- LOADUI R0 $program_string0 ; Using the GLOBAL_ prefix
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Move new GLOBALS_LIST into Place
- MOVE R0 R3 ; Use GLOBAL_TOKEN->PREV->S
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Move new GLOBALS_LIST into Place
- LOADUI R0 $newline ; Using the Newline postfix
- CALLI R15 @emit ; emit it
- MOVE R10 R0 ; Update GLOBALS_LIST
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- LOADUI R1 $digit_chars ; 0-9
- CALLI R15 @in_set ; Figure out if in set
- JUMP.Z R0 @program_assign_string ; If not in sets
- ;; Looks like we have an int
- COPY R1 R10 ; Using GLOBALS_LIST
- LOADUI R0 $percent ; Using percent prefix
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Put GLOBALS_LIST into Place
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Put GLOBALS_LIST into Place
- LOADUI R0 $newline ; Using newline postfix
- CALLI R15 @emit ; emit it
- MOVE R10 R0 ; Update GLOBALS_LIST
- JUMP @program_assign_done ; Move on
- :program_assign_string
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 34 ; If GLOBAL_TOKEN->S[0] == '"'
- JUMP @program_error ; If not we hit an error
- ;; Looks like we have a string
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @parse_string ; Parse it into useful form
- COPY R1 R10 ; GLOBALS_LIST
- CALLI R15 @emit ; emit it
- MOVE R10 R0 ; Update GLOBALS_LIST
- :program_assign_done
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $program_string4 ; Potential error message
- LOADUI R1 $semicolon ; Checking for ;
- CALLI R15 @require_match ; Catch those errors
- JUMP @program_iter
- :program_error
- LOADUI R0 $program_string2 ; message part 1
- FALSE R1 ; Show to user
- CALLI R15 @file_print ; write
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @file_print ; write
- LOADUI R0 $program_string3 ; message part 2
- CALLI R15 @file_print ; write
- CALLI R15 @line_error ; Provide a meaningful error message
- HALT
- :program_done
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :program_string0
- ":GLOBAL_"
- :program_string1
- "
- NULL
- "
- :program_string2
- "Received "
- :program_string3
- " in program
- "
- :program_string4
- "ERROR in Program
- Missing ;
- "
- ;; sym_declare function
- ;; Receives char* in R0, struct type* in R1, struct token_list* in R2
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns struct token_list* in R0
- :sym_declare
- STORE32 R2 R14 0 ; A->NEXT = LIST
- STORE32 R0 R14 8 ; A->S = S
- STORE32 R1 R14 12 ; A->TYPE = T
- ADDUI R0 R14 20 ; CALLOC struct token_list
- SWAP R0 R14 ; Prepare for Return
- RET R15
- ;; sym_lookup function
- ;; Receives char* in R0 and struct token_list in R1
- ;; Returns struct token_list* or NULL in R0
- :sym_lookup
- PUSHR R2 R15 ; Protect R2
- MOVE R2 R1 ; Protect I
- MOVE R1 R0 ; Put S in proper place
- :sym_lookup_iter
- JUMP.Z R2 @sym_lookup_done ; Stop if NULL
- LOAD32 R0 R2 8 ; I->S
- CALLI R15 @match ; if I->S == S
- JUMP.NZ R0 @sym_lookup_done ; Stop if match
- LOAD32 R2 R2 0 ; I = I->NEXT
- JUMP @sym_lookup_iter ; Keep looping
- :sym_lookup_done
- MOVE R0 R2 ; Using R2 as our result
- POPR R2 R15 ; Restore R2
- RET R15
- ;; function_call function
- ;; Receives CHAR* S in R0 and INT BOOL in R1
- ;; struct token_list* out in R12,
- ;; struct token_list* string_list in R11
- ;; and struct token_list* global_list in R10
- ;; and struct token_list* FUNC in R9
- ;; and struct token_list* current_target in R8
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns the token_lists modified
- :function_call
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- MOVE R2 R0 ; Protect S
- MOVE R3 R1 ; Protect BOOL
- LOADUI R0 $function_call_string0 ; Our first error message
- LOADUI R1 $open_paren ; Using "("
- CALLI R15 @require_match ; Make sure of a match
- FALSE R4 ; PASSED = 0
- LOADUI R0 $function_call_string1 ; Our first header
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string2 ; Our second header
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string3 ; Our third header
- CALLI R15 @emit_out ; emit it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.NE R0 41 ; IF GLOBAL_TOKEN->S[0] != ')'
- JUMP @function_call_collect_done ; looks like function()
- ;; Collect arguments
- CALLI R15 @expression ; Deal with first argument
- LOADUI R0 $function_call_string4 ; Push it onto stack
- CALLI R15 @emit_out ; emit it
- ADDUI R4 R4 1 ; PASSED = 1
- :function_call_collect_iter
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R0 44 ; IF GLOBAL_TOKEN->S[0] != ','
- JUMP @function_call_collect_done ; looks like we are done collecting arguments
- ;; Collect another argument
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- CALLI R15 @expression ; Deal with Nth argument
- LOADUI R0 $function_call_string5 ; Push it onto stack
- CALLI R15 @emit_out ; emit it
- ADDUI R4 R4 1 ; PASSED = PASSED + 1
- JUMP @function_call_collect_iter ; Keep looping
- :function_call_collect_done
- LOADUI R0 $function_call_string6 ; Our second error message
- LOADUI R1 $close_paren ; Using ")"
- CALLI R15 @require_match ; Make sure of a match
- JUMP.Z R3 @function_call_call_false ; if BOOL != TRUE
- ;; Deal with TRUE == BOOL
- LOADUI R0 $function_call_string7 ; Our first prefix
- CALLI R15 @emit_out ; emit it
- MOVE R0 R2 ; Using S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string8 ; Our first postfix
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string9 ; Our second postfix
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string10 ; Our last postfix
- CALLI R15 @emit_out ; emit it
- JUMP @function_call_call_done ; Move on
- :function_call_call_false
- ;; Deal with FALSE == BOOL
- LOADUI R0 $function_call_string11 ; Our first prefix
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string12 ; Our last prefix
- CALLI R15 @emit_out ; emit it
- MOVE R0 R2 ; Using S
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string16 ; Using terminating prefix
- CALLI R15 @emit_out ; emit it
- :function_call_call_done
- LOADUI R0 $function_call_string13 ; Our POP
- :function_call_pop_iter
- JUMP.Z R4 @function_call_pop_done ; Skip POP if out of args on Stack
- CALLI R15 @emit_out ; emit our POP
- SUBI R4 R4 1 ; PASSED = PASSED - 1
- JUMP @function_call_pop_iter ; Loop
- :function_call_pop_done
- LOADUI R0 $function_call_string14 ; Our first postfix
- CALLI R15 @emit_out ; emit it
- LOADUI R0 $function_call_string15 ; Our final postfix
- CALLI R15 @emit_out ; emit it
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :function_call_string0
- "ERROR in process_expression_list
- No ( was found
- "
- :function_call_string1
- "{R11} PUSH_ALWAYS # Prevent overwriting in recursion
- "
- :function_call_string2
- "{BP} PUSH_ALWAYS # Protect the old base pointer
- "
- :function_call_string3
- "'0' SP R11 NO_SHIFT MOVE_ALWAYS # Copy new base pointer
- "
- :function_call_string4
- "{R0} PUSH_ALWAYS #_process_expression1
- "
- :function_call_string5
- "{R0} PUSH_ALWAYS #_process_expression2
- "
- :function_call_string6
- "ERROR in process_expression_list
- No ) was found
- "
- :function_call_string7
- "!"
- :function_call_string8
- " R0 SUB BP ARITH_ALWAYS
- !0 R0 LOAD32 R0 MEMORY
- {LR} PUSH_ALWAYS # Protect the old link register
- "
- :function_call_string9
- "'0' R11 BP NO_SHIFT MOVE_ALWAYS
- "
- :function_call_string10
- "'3' R0 CALL_REG_ALWAYS
- {LR} POP_ALWAYS # Prevent overwrite
- "
- :function_call_string11
- "{LR} PUSH_ALWAYS # Protect the old link register
- '0' R11 BP NO_SHIFT MOVE_ALWAYS
- "
- :function_call_string12
- "^~FUNCTION_"
- :function_call_string13
- "{R1} POP_ALWAYS # _process_expression_locals
- "
- :function_call_string14
- "{BP} POP_ALWAYS # Restore old base pointer
- "
- :function_call_string15
- "{R11} POP_ALWAYS # Prevent overwrite
- "
- :function_call_string16
- " CALL_ALWAYS
- {LR} POP_ALWAYS # Restore the old link register
- "
- ;; emit function
- ;; Receives char* in R0, struct token_list* in R1
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns struct token_list* in R0
- :emit
- PUSHR R2 R15 ; Protect R2
- COPY R2 R14 ; Pointer to T
- ADDUI R14 R14 20 ; CALLOC struct token_list
- STORE32 R1 R2 0 ; T->NEXT = HEAD
- STORE32 R0 R2 8 ; T->S = S
- MOVE R0 R2 ; Put T in proper spot for return
- POPR R2 R15 ; Restore R2
- RET R15
- ;; emit_out function
- ;; Receives char* in R0
- ;; struct token_list* out in R12,
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns struct token_list* in R0
- :emit_out
- STORE32 R12 R14 0 ; T->NEXT = OUT
- ADDUI R12 R14 20 ; Get T
- SWAP R12 R14 ; CALLOC struct token_list
- STORE32 R0 R12 8 ; T->S = S
- RET R15
- ;; uniqueID function
- ;; Receives char* in R0, struct token_list* in R1 and char* in R2
- ;; Calls emit repeatedly
- ;; Returns struct token_list* in R0
- :uniqueID
- CALLI R15 @emit ; emit S
- MOVE R1 R0 ; Put L in the correct place
- LOADUI R0 $underline ; Using "_"
- CALLI R15 @emit ; emit it
- MOVE R1 R0 ; Put L in the correct place
- COPY R0 R2 ; Put NUM in the correct place
- CALLI R15 @emit ; emit NUM
- MOVE R1 R0 ; Put L in the correct place
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit ; emit it
- RET R15
- ;; uniqueID_out function
- ;; Receives char* in R0, char* in R1
- ;; Calls emit_out repeatedly
- ;; Returns nothing
- :uniqueID_out
- CALLI R15 @emit_out ; emit S
- LOADUI R0 $underline ; Using "_"
- CALLI R15 @emit_out ; emit it
- COPY R0 R1 ; Put NUM in the correct place
- CALLI R15 @emit_out ; emit NUM
- LOADUI R0 $newline ; Using "\n"
- CALLI R15 @emit_out ; emit it
- RET R15
- ;; file_print function
- ;; Receives pointer to string in R0 and FILE* in R1
- ;; Returns nothing
- :file_print
- PUSHR R2 R15 ; Protect R2 from Overwrite
- MOVE R2 R0 ; Put string pointer into place
- :file_print_read
- LOAD8 R0 R2 0 ; Get a char
- JUMP.Z R0 @file_print_done ; If NULL be done
- FPUTC ; Write the Char
- ADDUI R2 R2 1 ; Point at next CHAR
- JUMP @file_print_read ; Loop again
- :file_print_done
- POPR R2 R15 ; Restore R2
- RET R15
- ;; recursive_output function
- ;; Receives token_list in R0 and FILE* in R1
- ;; Returns nothing and alters nothing
- :recursive_output
- JUMP.Z R0 @recursive_output_abort ; Abort if NULL
- PUSHR R2 R15 ; Preserve R2 from recursion
- MOVE R2 R0 ; Preserve R0 from recursion
- LOAD32 R0 R2 0 ; Using I->NEXT
- CALLI R15 @recursive_output ; Recurse
- LOAD32 R0 R2 8 ; Using I->S
- CALLI R15 @file_print ; Write the string
- MOVE R0 R2 ; Put R0 back
- POPR R2 R15 ; Restore R0
- :recursive_output_abort
- RET R15
- ;; match function
- ;; Receives a CHAR* in R0, CHAR* in R1
- ;; Returns Bool in R0 indicating if strings match
- :match
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- MOVE R2 R0 ; Put First string in place
- MOVE R3 R1 ; Put Second string in place
- LOADUI R4 0 ; Set initial index of 0
- :match_cmpbyte
- LOADXU8 R0 R2 R4 ; Get a byte of our first string
- LOADXU8 R1 R3 R4 ; Get a byte of our second string
- ADDUI R4 R4 1 ; Prep for next loop
- CMPSKIP.NE R1 R0 ; Compare the bytes
- JUMP.NZ R1 @match_cmpbyte ; Loop if bytes are equal
- ;; Done
- FALSE R2 ; Default answer
- CMPSKIP.NE R0 R1 ; If ended loop with everything matching
- TRUE R2 ; Set as TRUE
- MOVE R0 R2 ; Prepare for return
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; lookup_type function
- ;; Receives a CHAR* in R0 and struct type* in R1
- ;; Returns struct type* in R0 or NULL if no match
- :lookup_type
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- MOVE R2 R1 ; Put START in correct place
- MOVE R1 R0 ; Put S in correct place
- :lookup_type_iter
- LOAD32 R0 R2 24 ; Get I->NAME
- CALLI R15 @match ; Check if I->NAME == S
- JUMP.NZ R0 @lookup_type_done ; If match found be done
- LOAD32 R2 R2 0 ; I = I->NEXT
- JUMP.NZ R2 @lookup_type_iter ; Otherwise iterate until I == NULL
- :lookup_type_done
- MOVE R0 R2 ; Our answer (I or NULL)
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; lookup_member function
- ;; Receives struct type* parent in R0 and char* name in R1
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns struct type* of member in R0 or aborts with error
- :lookup_member
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- LOAD32 R3 R0 24 ; PARENT->NAME for error
- MOVE R2 R0 ; I = PARENT
- :lookup_member_iter
- LOAD32 R2 R2 16 ; I = I->MEMBERS
- JUMP.Z R2 @lookup_member_error ; We failed hard
- LOAD32 R0 R2 24 ; I->NAME
- CALLI R15 @match ; IF I->NAME == NAME
- JUMP.Z R0 @lookup_member_iter ; Loop again
- :lookup_member_done
- MOVE R0 R2 ; Put I in the correct place
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- :lookup_member_error
- FALSE R1 ; Write to TTY
- LOADUI R0 $lookup_member_string0 ; Our header string
- CALLI R15 @file_print ; Print it
- MOVE R0 R3 ; Using PARENT->NAME
- CALLI R15 @file_print ; Print it
- LOADUI R0 $arrow_string ; Using "->"
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @file_print ; Print it
- LOADUI R0 $lookup_member_string1 ; Our footer string
- CALLI R15 @file_print ; Print it
- CALLI R15 @line_error ; Give line info
- LOADUI R0 $newline ; Our final addition
- CALLI R15 @file_print ; Print it
- HALT
- :lookup_member_string0
- "ERROR in lookup_member "
- :lookup_member_string1
- " does not exist
- "
- ;; build_member function
- ;; Receives a struct type* in R0, int in R1 and int in R2
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Modifies R2 to current member_size
- ;; Returns struct type* in R0
- :build_member
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- PUSHR R5 R15 ; Protect R5
- PUSHR R6 R15 ; Protect R6
- MOVE R6 R1 ; Protect OFFSET
- MOVE R4 R0 ; Protect LAST
- CALLI R15 @type_name ; Get MEMBER_TYPE
- MOVE R5 R0 ; Protect MEMBER_TYPE
- ADDUI R3 R14 28 ; CALLOC struct type
- SWAP R3 R14 ; SET I
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- STORE32 R0 R3 24 ; I->NAME = GLOBAL_TOKEN->S
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- STORE32 R4 R3 16 ; I->MEMBERS = LAST
- LOADUI R0 $open_bracket ; Using "["
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; IF GLOBAL_TOKEN->S == "["
- JUMP.Z R0 @build_member_single
- ;; Deal with type name [ number ] ;
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @numerate_string ; Convert string to int NUMBER
- LOAD32 R1 R5 20 ; MEMBER_TYPE->TYPE
- LOAD32 R1 R1 4 ; MEMBER_TYPE->TYPE->SIZE
- MULU R0 R0 R1 ; MEMBER_TYPE->TYPE->SIZE * NUMBER
- STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->TYPE->SIZE * NUMBER
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $build_member_string0 ; Our error message
- LOADUI R1 $close_bracket ; Using "]"
- CALLI R15 @require_match ; Make sure it is right
- JUMP @build_member_done ; Skip over single steps
- :build_member_single
- LOAD32 R0 R5 4 ; MEMBER_TYPE->SIZE
- STORE32 R0 R3 4 ; I->SIZE = MEMBER_TYPE->SIZE
- :build_member_done
- LOAD32 R2 R3 4 ; MEMBER_SIZE = I->SIZE
- STORE32 R5 R3 20 ; I->TYPE = MEMBER_TYPE
- STORE32 R6 R3 8 ; I->OFFSET = OFFSET
- MOVE R1 R6 ; Restore OFFSET
- MOVE R0 R3 ; RETURN I in R0
- POPR R6 R15 ; Restore R6
- POPR R5 R15 ; Restore R5
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- RET R15
- :build_member_string0
- "Struct only supports [num] form
- "
- ;; build_union function
- ;; Receives a struct type* in R0, int in R1 and int in R2
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Modifies R2 to current member_size
- ;; Returns struct type* in R0
- :build_union
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- PUSHR R5 R15 ; Protect R5
- MOVE R4 R0 ; Protect LAST
- MOVE R3 R1 ; Protect OFFSET
- FALSE R5 ; SIZE = 0
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $build_union_string0 ; ERROR MESSAGE
- LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
- CALLI R15 @require_match ; Ensure we have that curly brace
- :build_union_iter
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- LOADUI R1 125 ; numerical value of }
- CMPJUMPI.E R0 R1 @build_union_done ; No more looping required
- MOVE R0 R4 ; We are passing last to be overwritten
- MOVE R1 R3 ; We are also passing OFFSET
- CALLI R15 @build_member ; To build_member to get new LAST and new member_size
- CMPSKIP.LE R2 R5 ; If MEMBER_SIZE > SIZE
- COPY R5 R2 ; SIZE = MEMMER_SIZE
- MOVE R4 R0 ; Protect LAST
- MOVE R3 R1 ; Protect OFFSET
- LOADUI R0 $build_union_string1 ; ERROR MESSAGE
- LOADUI R1 $semicolon ; SEMICOLON
- CALLI R15 @require_match ; Ensure we have that curly brace
- JUMP @build_union_iter ; Loop until we get that closing curly brace
- :build_union_done
- MOVE R2 R5 ; Setting MEMBER_SIZE = SIZE
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- MOVE R1 R3 ; Restore OFFSET
- MOVE R0 R4 ; Restore LAST as we are turning that
- POPR R5 R15 ; Restore R5
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- RET R15
- :build_union_string0
- "ERROR in build_union
- Missing {
- "
- :build_union_string1
- "ERROR in build_union
- Missing ;
- "
- ;; create_struct function
- ;; Receives Nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns Nothing
- :create_struct
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- PUSHR R5 R15 ; Protect R5
- PUSHR R6 R15 ; Protect R6
- FALSE R5 ; OFFSET = 0
- FALSE R2 ; MEMBER_SIZE = 0
- COPY R3 R14 ; SET HEAD
- ADDUI R14 R14 28 ; CALLOC struct type
- COPY R4 R14 ; SET I
- ADDUI R14 R14 28 ; CALLOC struct type
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- STORE32 R0 R3 24 ; HEAD->NAME = GLOBAL_TOKEN->S
- STORE32 R0 R4 24 ; I->NAME = GLOBAL_TOKEN->S
- STORE32 R4 R3 12 ; HEAD->INDIRECT = I
- STORE32 R3 R4 12 ; I->INDIRECT - HEAD
- LOADR32 R0 @global_types ; Get Address of GLOBAL_TYPES
- STORE R0 R3 0 ; HEAD->NEXT = GLOBAL_TYPES
- STORER32 R3 @global_types ; GLOBAL_TYPES = HEAD
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 4 ; Standard Pointer SIZE
- STORE32 R0 R4 4 ; I->SIZE = 4
- LOADUI R0 $create_struct_string0 ; ERROR MESSAGE
- LOADUI R1 $open_curly_brace ; OPEN CURLY BRACE
- CALLI R15 @require_match ; Ensure we have that curly brace
- FALSE R6 ; LAST = NULL
- :create_struct_iter
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R0 R0 0 ; GLOBAL_TOKEN->S[0]
- LOADUI R1 125 ; Numerical value of }
- CMPJUMPI.E R0 R1 @create_struct_done ; Stop looping if match
- LOADUI R1 $union ; Pointer to string UNION
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; Check if they Match
- SWAP R0 R6 ; Put LAST in place
- MOVE R1 R5 ; Put OFFSET in place
- JUMP.NZ R6 @create_struct_union ; Deal with union case
- ;; Deal with standard member case
- CALLI R15 @build_member ; Sets new LAST and MEMBER_SIZE
- JUMP @create_struct_iter2 ; reset for loop
- :create_struct_union
- CALLI R15 @build_union
- :create_struct_iter2
- ADD R5 R1 R2 ; OFFSET = OFFSET + MEMBER_SIZE
- SWAP R0 R6 ; Put LAST in place
- LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
- LOADUI R1 $semicolon ; SEMICOLON
- CALLI R15 @require_match ; Ensure we have that semicolon
- JUMP @create_struct_iter ; Keep Looping
- :create_struct_done
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOADUI R0 $create_struct_string1 ; ERROR MESSAGE
- LOADUI R1 $semicolon ; SEMICOLON
- CALLI R15 @require_match ; Ensure we have that semicolon
- STORE32 R5 R3 4 ; HEAD->SIZE = OFFSET
- STORE32 R6 R3 16 ; HEAD->MEMBERS = LAST
- STORE32 R6 R4 16 ; I->MEMBERS = LAST
- POPR R6 R15 ; Restore R6
- POPR R5 R15 ; Restore R5
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :create_struct_string0
- "ERROR in create_struct
- Missing {
- "
- :create_struct_string1
- "ERROR in create_struct
- Missing ;
- "
- ;; type_name function
- ;; Receives Nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns struct type* in R0
- :type_name
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- LOADUI R0 $struct ; String for struct for comparison
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; Check if they match
- CMPSKIPI.E R0 0 ; If STRUCTURE
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R2 R13 8 ; GLOBAL_TOKEN->S
- LOADR32 R1 @global_types ; Check using the GLOBAL TYPES LIST
- SWAP R0 R2 ; Put GLOBAL_TOKEN->S in the right place
- CALLI R15 @lookup_type ; RET = lookup_type(GLOBAL_TOKEN->S)
- MOVE R1 R2 ; Put STRUCTURE in the right place
- CMPSKIP.E R0 R1 ; If RET == NULL and !STRUCTURE
- JUMP @type_name_struct ; Guess not
- ;; Exit with useful error message
- FALSE R1 ; We will want to be writing the error message for the Human
- LOADUI R0 $type_name_string0 ; The first string
- CALLI R15 @file_print ; Display it
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @file_print ; Display it
- LOADUI R0 $newline ; Terminating linefeed
- CALLI R15 @file_print ; Display it
- CALLI R15 @line_error ; Give useful debug info
- HALT ; Just exit
- :type_name_struct
- JUMP.NZ R0 @type_name_iter ; If was found
- CALLI R15 @create_struct ; Otherwise create it
- JUMP @type_name_done ; and be done
- :type_name_iter
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- LOAD32 R1 R13 8 ; GLOBAL_TOKEN->S
- LOADU8 R1 R1 0 ; GLOBAL_TOKEN->S[0]
- CMPSKIPI.E R1 42 ; if GLOBAL_TOKEN->S[0] == '*'
- JUMP @type_name_done ; Looks like Nope
- LOAD32 R0 R0 12 ; RET = RET->INDIRECT
- JUMP @type_name_iter ; Keep looping
- :type_name_done
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- :type_name_string0
- "Unknown type "
- ;; line_error function
- ;; Receives Nothing
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns nothing
- :line_error
- PUSHR R0 R15 ; Protect R0
- PUSHR R1 R15 ; Protect R1
- LOADUI R0 $line_error_string0 ; Our leading string
- FALSE R1 ; We want the user to see
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R13 16 ; GLOBAL_TOKEN->LINENUMBER
- CALLI R15 @numerate_number ; Get a string pointer for number
- CALLI R15 @file_print ; And print it
- POPR R1 R15 ; Restore R1
- POPR R0 R15 ; Restore R0
- RET R15
- :line_error_string0
- "In file: TTY1 On line: "
- ;; require_match function
- ;; Receives char* in R0 and char* in R1
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns Nothing
- :require_match
- PUSHR R0 R15 ; Protect R0
- PUSHR R2 R15 ; Protect R2
- MOVE R2 R0 ; Get MESSAGE out of the way
- LOAD32 R0 R13 8 ; GLOBAL_TOKEN->S
- CALLI R15 @match ; Check if GLOBAL_TOKEN->S == REQUIRED
- JUMP.NZ R0 @require_match_done ; Looks like it was a match
- ;; Terminate with an error
- MOVE R0 R2 ; Put MESSAGE in required spot
- FALSE R1 ; We want to write for user
- CALLI R15 @file_print ; Write it
- CALLI R15 @line_error ; And provide some debug info
- HALT ; Then Stop immediately
- :require_match_done
- LOAD32 R13 R13 0 ; GLOBAL_TOKEN = GLOBAL_TOKEN->NEXT
- POPR R2 R15 ; Restore R2
- POPR R0 R15 ; Restore R0
- RET R15
- ;; numerate_number function
- ;; Receives int in R0
- ;; R13 Holds pointer to global_token, R14 is HEAP Pointer
- ;; Returns pointer to string generated
- :numerate_number
- PUSHR R1 R15 ; Preserve R1
- PUSHR R2 R15 ; Preserve R2
- PUSHR R3 R15 ; Preserve R3
- PUSHR R4 R15 ; Preserve R4
- PUSHR R5 R15 ; Preserve R5
- PUSHR R6 R15 ; Preserve R6
- MOVE R3 R0 ; Move Integer out of the way
- COPY R1 R14 ; Get pointer result
- ADDUI R14 R14 16 ; CALLOC the 16 chars of space
- FALSE R6 ; Set index to 0
- JUMP.Z R3 @numerate_number_ZERO ; Deal with Special case of ZERO
- JUMP.P R3 @numerate_number_Positive
- LOADUI R0 45 ; Using -
- STOREX8 R0 R1 R6 ; write leading -
- ADDUI R6 R6 1 ; Increment by 1
- NOT R3 R3 ; Flip into positive
- ADDUI R3 R3 1 ; Adjust twos
- :numerate_number_Positive
- LOADR R2 @Max_Decimal ; Starting from the Top
- LOADUI R5 10 ; We move down by 10
- FALSE R4 ; Flag leading Zeros
- :numerate_number_0
- DIVIDE R0 R3 R3 R2 ; Break off top 10
- CMPSKIPI.E R0 0 ; If Not Zero
- TRUE R4 ; Flip the Flag
- JUMP.Z R4 @numerate_number_1 ; Skip leading Zeros
- ADDUI R0 R0 48 ; Shift into ASCII
- STOREX8 R0 R1 R6 ; write digit
- ADDUI R6 R6 1 ; Increment by 1
- :numerate_number_1
- DIV R2 R2 R5 ; Look at next 10
- CMPSKIPI.E R2 0 ; If we reached the bottom STOP
- JUMP @numerate_number_0 ; Otherwise keep looping
- :numerate_number_done
- FALSE R0 ; NULL Terminate
- STOREX8 R0 R1 R6 ; write
- MOVE R0 R1 ; Return pointer to our string
- ;; Cleanup
- POPR R6 R15 ; Restore R6
- POPR R5 R15 ; Restore R5
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- :numerate_number_ZERO
- LOADUI R0 48 ; Using Zero
- STOREX8 R0 R1 R6 ; write
- ADDUI R6 R6 1 ; Increment by 1
- JUMP @numerate_number_done ; Be done
- :Max_Decimal
- '3B9ACA00'
- ;; numerate_string function
- ;; Receives pointer To string in R0
- ;; Returns number in R0 equal to value of string
- ;; Or Zero in the event of invalid string
- :numerate_string
- PUSHR R1 R15 ; Protect R1
- PUSHR R2 R15 ; Protect R2
- PUSHR R3 R15 ; Protect R3
- PUSHR R4 R15 ; Protect R4
- ;; Initialize
- MOVE R1 R0 ; Get Text pointer out of the way
- FALSE R2 ; Set Negative flag to false
- FALSE R3 ; Set current count to Zero
- LOAD8 R0 R1 1 ; Get second byte
- CMPSKIPI.NE R0 120 ; If the second byte is x
- JUMP @numerate_string_hex ; treat string like hex
- ;; Deal with Decimal input
- LOADUI R4 10 ; Multiply by 10
- LOAD8 R0 R1 0 ; Get a byte
- CMPSKIPI.NE R0 45 ; If - toggle flag
- TRUE R2 ; So that we know to negate
- CMPSKIPI.E R2 0 ; If toggled
- ADDUI R1 R1 1 ; Move to next
- :numerate_string_dec
- LOAD8 R0 R1 0 ; Get a byte
- CMPSKIPI.NE R0 0 ; If NULL
- JUMP @numerate_string_done ; Be done
- MUL R3 R3 R4 ; Shift counter by 10
- SUBI R0 R0 48 ; Convert ascii to number
- CMPSKIPI.GE R0 0 ; If less than a number
- JUMP @numerate_string_done ; Terminate NOW
- CMPSKIPI.L R0 10 ; If more than a number
- JUMP @numerate_string_done ; Terminate NOW
- ADDU R3 R3 R0 ; Don't add to the count
- ADDUI R1 R1 1 ; Move onto next byte
- JUMP @numerate_string_dec
- ;; Deal with Hex input
- :numerate_string_hex
- LOAD8 R0 R1 0 ; Get a byte
- CMPSKIPI.E R0 48 ; All hex strings start with 0x
- JUMP @numerate_string_done ; Be done if not a match
- ADDUI R1 R1 2 ; Move to after leading 0x
- :numerate_string_hex_0
- LOAD8 R0 R1 0 ; Get a byte
- CMPSKIPI.NE R0 0 ; If NULL
- JUMP @numerate_string_done ; Be done
- SL0I R3 4 ; Shift counter by 16
- SUBI R0 R0 48 ; Convert ascii number to number
- CMPSKIPI.L R0 10 ; If A-F
- SUBI R0 R0 7 ; Shove into Range
- CMPSKIPI.L R0 16 ; If a-f
- SUBI R0 R0 32 ; Shove into Range
- ADDU R3 R3 R0 ; Add to the count
- ADDUI R1 R1 1 ; Get next Hex
- JUMP @numerate_string_hex_0
- ;; Clean up
- :numerate_string_done
- CMPSKIPI.E R2 0 ; If Negate flag has been set
- NEG R3 R3 ; Make the number negative
- MOVE R0 R3 ; Put number in R0
- POPR R4 R15 ; Restore R4
- POPR R3 R15 ; Restore R3
- POPR R2 R15 ; Restore R2
- POPR R1 R15 ; Restore R1
- RET R15
- ;; Keywords
- :union
- "union"
- :struct
- "struct"
- :constant
- "CONSTANT"
- :main_string
- "main"
- :argc_string
- "argc"
- :argv_string
- "argv"
- :if_string
- "if"
- :else_string
- "else"
- :do_string
- "do"
- :while_string
- "while"
- :for_string
- "for"
- :asm_string
- "asm"
- :goto_string
- "goto"
- :return_string
- "return"
- :break_string
- "break"
- :continue_string
- "continue"
- :sizeof_string
- "sizeof"
- :plus_string
- "+"
- :minus_string
- "-"
- :multiply_string
- "*"
- :divide_string
- "/"
- :modulus_string
- "%"
- :left_shift_string
- "<<"
- :right_shift_string
- ">>"
- :less_than_string
- "<"
- :less_than_equal_string
- "<="
- :greater_than_equal_string
- ">="
- :greater_than_string
- ">"
- :equal_to_string
- "=="
- :not_equal_string
- "!="
- :bitwise_and
- "&"
- :logical_and
- "&&"
- :bitwise_or
- "|"
- :logical_or
- "||"
- :bitwise_xor
- "^"
- :arrow_string
- "->"
- ;; Frequently Used strings
- ;; Generally used by require_match
- :open_curly_brace
- "{"
- :close_curly_brace
- "}"
- :open_paren
- "("
- :close_paren
- ")"
- :open_bracket
- "["
- :close_bracket
- "]"
- :semicolon
- ";"
- :equal
- "="
- :percent
- "%"
- :newline
- "
- "
- :not
- "!"
- :underline
- "_"
- ;; Global types
- ;; NEXT (0), SIZE (4), OFFSET (8), INDIRECT (12), MEMBERS (16), TYPE (20), NAME (24)
- :global_types
- &type_void
- :prim_types
- :type_void
- &type_int ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_void ; INDIRECT
- NOP ; MEMBERS
- &type_void ; TYPE
- &type_void_name ; NAME
- :type_void_name
- "void"
- :type_int
- &type_char ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_int ; INDIRECT
- NOP ; MEMBERS
- &type_int ; TYPE
- &type_int_name ; NAME
- :type_int_name
- "int"
- :type_char
- &type_file ; NEXT
- '00 00 00 01' ; SIZE
- NOP ; OFFSET
- &type_char_indirect ; INDIRECT
- NOP ; MEMBERS
- &type_char ; TYPE
- &type_char_name ; NAME
- :type_char_name
- "char"
- :type_char_indirect
- &type_file ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_char_double_indirect ; INDIRECT
- NOP ; MEMBERS
- &type_char_indirect ; TYPE
- &type_char_indirect_name ; NAME
- :type_char_indirect_name
- "char*"
- :type_char_double_indirect
- &type_file ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_char_double_indirect ; INDIRECT
- NOP ; MEMBERS
- &type_char_indirect ; TYPE
- &type_char_double_indirect_name ; NAME
- :type_char_double_indirect_name
- "char**"
- :type_file
- &type_function ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_file ; INDIRECT
- NOP ; MEMBERS
- &type_file ; TYPE
- &type_file_name ; NAME
- :type_file_name
- "FILE"
- :type_function
- &type_unsigned ; NEXT
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_function ; INDIRECT
- NOP ; MEMBERS
- &type_function ; TYPE
- &type_function_name ; NAME
- :type_function_name
- "FUNCTION"
- :type_unsigned
- NOP ; NEXT (NULL)
- '00 00 00 04' ; SIZE
- NOP ; OFFSET
- &type_unsigned ; INDIRECT
- NOP ; MEMBERS
- &type_unsigned ; TYPE
- &type_unsigned_name ; NAME
- :type_unsigned_name
- "unsigned"
- ;; debug_list function
- ;; Receives struct token_list* in R0
- ;; Prints contents of list and HALTS
- ;; Does not return
- :debug_list
- MOVE R9 R0 ; Protect the list Pointer
- FALSE R1 ; Write to TTY
- :debug_list_iter
- ;; Header
- LOADUI R0 $debug_list_string0 ; Using our first string
- CALLI R15 @file_print ; Print it
- COPY R0 R9 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; NEXT
- LOADUI R0 $debug_list_string1 ; Using our second string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 0 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; PREV
- LOADUI R0 $debug_list_string2 ; Using our third string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 4 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; S
- LOADUI R0 $debug_list_string3 ; Using our fourth string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 8 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; S Contents
- LOADUI R0 $debug_list_string4 ; Using our Prefix string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 8 ; Use address of pointer
- CMPSKIPI.NE R0 0 ; If NULL Pointer
- LOADUI R0 $debug_list_string_null ; Give meaningful message instead
- CALLI R15 @file_print ; Print it
- ;; TYPE
- LOADUI R0 $debug_list_string5 ; Using our fifth string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 12 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; PREV
- LOADUI R0 $debug_list_string6 ; Using our sixth string
- CALLI R15 @file_print ; Print it
- LOAD32 R0 R9 16 ; Use address of pointer
- CALLI R15 @numerate_number ; Convert it into a string
- CALLI R15 @file_print ; Print it
- ;; Add some space
- LOADUI R0 10 ; Using NEWLINE
- FPUTC
- FPUTC
- ;; Iterate if next not NULL
- LOAD32 R9 R9 0 ; TOKEN = TOKEN->NEXT
- JUMP.NZ R9 @debug_list_iter
- ;; Looks lke we are done, wrap it up
- HALT
- :debug_list_string0
- "Token_list node at address: "
- :debug_list_string1
- "
- NEXT address: "
- :debug_list_string2
- "
- PREV address: "
- :debug_list_string3
- "
- S address: "
- :debug_list_string4
- "
- The contents of S are: "
- :debug_list_string5
- "
- TYPE address: "
- :debug_list_string6
- "
- ARGUMENTS address: "
- :debug_list_string_null
- ">::<NULL>::<"
- :STACK
|