diff --git a/stage2/cc_aarch64.s b/stage2/cc_aarch64.s
new file mode 100644
index 0000000..ac46dea
--- /dev/null
+++ b/stage2/cc_aarch64.s
@@ -0,0 +1,4486 @@
+; 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 .
+
+;; 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 $unary_expr_sizeof_string2 ; Our header
+ 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 $newline ; add in our '\n'
+ 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+%"
+
+
+;; 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+%"
+
+
+;; 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 $variable_load_string0 ; Using header
+ 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_string2 ; 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
+ "SET_X0_FROM_BP
+LOAD_W1_AHEAD
+SKIP_32_DATA
+%"
+:variable_load_string1
+ "DEREF_X0
+"
+:variable_load_string2
+ "
+SUB_X0_X0_X1
+
+"
+
+
+;; 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+&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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+&GLOBAL_"
+:global_load_string1
+ "DEREF_X0
+"
+
+
+;; 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+&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 $primary_expr_char_string0 ; Using header
+ 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 $newline ; 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+%"
+
+
+;; 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
+ "LOAD_W0_AHEAD
+SKIP_32_DATA
+%"
+
+
+;; 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
+ "PUSH_X0 #_common_recursion
+"
+:common_recursion_string1
+ "POP_X1 # _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
+ 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 8 ; Compare against 8
+ 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
+ "LOAD_W1_AHEAD
+SKIP_32_DATA
+%"
+:postfix_expr_arrow_string3
+ "
+ADD_X0_X1_X0
+"
+:postfix_expr_arrow_string4
+ "DEREF_X0
+"
+
+
+;; 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
+ "DEREF_X0
+"
+:postfix_expr_array_string1
+ "DEREF_X0_BYTE
+"
+:postfix_expr_array_string2
+ "LOAD_W2_AHEAD
+SKIP_32_DATA
+%"
+:postfix_expr_array_string3
+ "ADD_X0_X1_X0
+"
+:postfix_expr_array_string4
+ "ERROR in postfix_expr
+Missing ]
+"
+:postfix_expr_array_string5
+ ""
+:postfix_expr_array_string6
+"
+LSHIFT_X0_X0_X2
+"
+
+;; 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
+ "ADD_X0_X1_X0
+"
+:additive_expr_stub_string1
+ "SUB_X0_X1_X0
+"
+:additive_expr_stub_string2
+ "MUL_X0_X1_X0
+"
+:additive_expr_stub_string3
+ "UDIV_X0_X1_X0
+"
+:additive_expr_stub_string4
+ "UDIV_X2_X1_X0
+MSUB_X0_X0_X2_X1
+"
+:additive_expr_stub_string5
+ "LSHIFT_X0_X1_X0
+"
+:additive_expr_stub_string6
+ "RSHIFT_X0_X1_X0
+"
+
+
+;; 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
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_LT
+SET_X0_TO_0
+"
+:relational_expr_stub_string1
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_LE
+SET_X0_TO_0
+"
+:relational_expr_stub_string2
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_GE
+SET_X0_TO_0
+"
+:relational_expr_stub_string3
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_GT
+SET_X0_TO_0
+"
+:relational_expr_stub_string4
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_EQ
+SET_X0_TO_0
+"
+:relational_expr_stub_string5
+ "CMP_X1_X0
+SET_X0_TO_1
+SKIP_INST_NE
+SET_X0_TO_0
+"
+
+
+;; 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
+ "AND_X0_X1_X0
+"
+:bitwise_expr_stub_string1
+ "OR_X0_X1_X0
+"
+:bitwise_expr_stub_string2
+ "XOR_X0_X1_X0
+"
+
+
+;; 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
+ "SET_X0_TO_0
+"
+:primary_expr_str1
+ "SUB_X0_X1_X0
+"
+:primary_expr_str2
+ "SET_X0_TO_1
+"
+:primary_expr_str3
+ "XOR_X0_X1_X0
+"
+: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
+ "STR_X0_[X1]
+"
+:expression_string1
+ "STR_BYTE_W0_[X1]
+"
+
+;; 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
+ "CBNZ_X0_PAST_BR
+LOAD_W16_AHEAD
+SKIP_32_DATA
+&ELSE_"
+:process_if_string3
+ "ERROR in process_if
+MISSING )
+"
+:process_if_string4
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&_END_IF_"
+:process_if_string5
+ "
+BR_X16
+:ELSE_"
+:process_if_string6
+ ":_END_IF_"
+:process_if_string7
+ "
+BR_X16
+"
+
+;; 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
+ "CBNZ_X0_PAST_BR
+LOAD_W16_AHEAD
+SKIP_32_DATA
+&FOR_END_"
+:process_for_string6
+ "
+BR_X16
+LOAD_W16_AHEAD
+SKIP_32_DATA
+&FOR_THEN_"
+:process_for_string7
+ "
+BR_X16
+:FOR_ITER_"
+:process_for_string8
+ "ERROR in process_for
+MISSING ;2
+"
+:process_for_string9
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&FOR_"
+:process_for_string10
+ "
+BR_X16
+:FOR_THEN_"
+:process_for_string11
+ "ERROR in process_for
+MISSING )
+"
+:process_for_string12
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&FOR_ITER_"
+:process_for_string13
+ "
+BR_X16
+: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
+ "CBZ_X0_PAST_BR
+LOAD_W16_AHEAD
+SKIP_32_DATA
+&DO_"
+:process_do_string7
+ "
+BR_X16
+: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
+ "CBNZ_X0_PAST_BR
+LOAD_W16_AHEAD
+SKIP_32_DATA
+&END_WHILE_"
+:process_while_string4
+ "
+BR_X16
+# THEN_while_"
+:process_while_string5
+ "ERROR in process_while
+MISSING )
+"
+:process_while_string6
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&WHILE_"
+:process_while_string7
+ "
+BR_X16
+: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
+ "POP_X1 # _return_result_locals
+"
+:return_result_string2
+ "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
+ "POP_X1 # break_cleanup_locals
+"
+:process_break_string2
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&"
+:process_break_string3
+ "ERROR in break statement
+Missing ;
+"
+:process_break_string4
+ "
+BR_X16
+"
+
+: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
+ "RETURN
+"
+:recursive_statement_string1
+ "POP_X1 # _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
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&"
+:statement_string2
+ "ERROR in statement
+MISSING ;
+"
+:statement_string3
+ "
+#continue statement
+"
+:statement_string4
+ "
+BR_X16
+"
+
+;; 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 64 ; The default depth for main
+ STORE32 R0 R2 16 ; A->DEPTH = 64
+ 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 16 ; The default depth for foo()
+ STORE32 R0 R2 16 ; A->DEPTH = 16
+ 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 16 ; DEPTH = FUNC->ARGS->DEPTH + 16
+ 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 16 ; DEPTH = FUNC->LOCALS->DEPTH + 16
+ 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
+ "PUSH_X0 #"
+
+
+;; 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 16 ; FUNC->ARGS->DEPTH + 16 or NULL + 16 (16)
+ 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
+ "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
+ "PUSH_X16 # Protect a tmp register we're going to use
+PUSH_LR # Protect the old return pointer (link)
+"
+:function_call_string2
+ "PUSH_BP # Protect the old base pointer
+"
+:function_call_string3
+ "SET_X16_FROM_SP # The base pointer to-be
+"
+:function_call_string4
+ "PUSH_X0 #_process_expression1
+"
+:function_call_string5
+ "PUSH_X0 #_process_expression2
+"
+:function_call_string6
+ "ERROR in process_expression_list
+No ) was found
+"
+:function_call_string7
+ "SET_X0_FROM_BP
+LOAD_W1_AHEAD
+SKIP_32_DATA
+%"
+:function_call_string8
+ "
+SUB_X0_X0_X1
+DEREF_X0
+"
+:function_call_string9
+ "SET_BP_FROM_X16
+"
+:function_call_string10
+ "SET_X16_FROM_X0
+BLR_X16
+"
+:function_call_string11
+ "SET_BP_FROM_X16
+"
+:function_call_string12
+ "LOAD_W16_AHEAD
+SKIP_32_DATA
+&FUNCTION_"
+:function_call_string13
+ "POP_X1 # _process_expression_locals
+"
+:function_call_string14
+ "POP_BP # Restore the old base pointer
+"
+:function_call_string15
+ "POP_LR # Restore the old return pointer (link)
+POP_X16 # Restore a register we used as tmp
+"
+:function_call_string16
+"
+BLR_X16
+"
+
+;; 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 8 ; Standard Pointer SIZE
+ STORE32 R0 R4 4 ; I->SIZE = 8
+ 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
+ "
+"
+: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 08' ; 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 08' ; 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 08' ; 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 08' ; 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 08' ; 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 08' ; 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
+ ">::::<"
+
+:STACK