diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore
deleted file mode 100644
index 082c2c4..0000000
--- a/bootstrap/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-M2.M1
-M2.hex2
-cc_x86
-hold
-seed.hex2
-
diff --git a/bootstrap/bootstrap-x86.sh b/bootstrap/bootstrap-x86.sh
deleted file mode 100755
index 68e6d57..0000000
--- a/bootstrap/bootstrap-x86.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#! /usr/bin/env bash
-## Copyright (C) 2017 Jeremiah Orians
-## This file is part of M2-Planet.
-##
-## M2-Planet 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.
-##
-## M2-Planet 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 M2-Planet. If not, see .
-
-set -eux
-[ -e ../bin/M2-Planet ] && rm ../bin/M2-Planet
-
-# Make the required bin directry
-[ -d ../bin ] || mkdir ../bin
-
-# Macro assemble with libc written in M1-Macro
-M1 -f x86/cc_x86.M1 \
- --LittleEndian \
- --architecture x86 \
- -o seed.hex2 || exit 1
-
-# Resolve all linkages
-hex2 -f ../test/common_x86/ELF-i386.hex2 \
- -f seed.hex2 \
- --LittleEndian \
- --architecture x86 \
- --BaseAddress 0x8048000 \
- -o cc_x86 \
- --exec_enable || exit 2
-
-# Build M2-Planet from cc_x86
-catm hold ../test/common_x86/functions/file.c \
- ../test/common_x86/functions/malloc.c \
- ../functions/calloc.c \
- ../test/common_x86/functions/exit.c \
- ../functions/match.c \
- ../functions/in_set.c \
- ../functions/numerate_number.c \
- ../functions/file_print.c \
- ../functions/number_pack.c \
- ../functions/fixup.c \
- ../functions/string.c \
- ../cc.h \
- ../cc_reader.c \
- ../cc_strings.c \
- ../cc_types.c \
- ../cc_core.c \
- ../cc.c
-./cc_x86 hold M2.M1
-M1 --architecture x86 \
- --LittleEndian \
- -f ../test/common_x86/x86_defs.M1 \
- -f ../test/common_x86/libc-core.M1 \
- -f M2.M1 \
- -o M2.hex2
-
-hex2 -f ../test/common_x86/ELF-i386.hex2 \
- -f M2.hex2 \
- --LittleEndian \
- --architecture x86 \
- --BaseAddress 0x8048000 \
- -o ../bin/M2-Planet-seed \
- --exec_enable
diff --git a/bootstrap/x86/cc_x86.M1 b/bootstrap/x86/cc_x86.M1
deleted file mode 100644
index c65e590..0000000
--- a/bootstrap/x86/cc_x86.M1
+++ /dev/null
@@ -1,4974 +0,0 @@
-;; Copyright (C) 2017 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 .
-
-DEFINE ADDI8_EAX 83C0
-DEFINE ADDI8_EBX 83C3
-DEFINE ADDI8_ECX 83C1
-DEFINE ADDI8_EDX 83C2
-DEFINE ADDI8_ESI 83C6
-DEFINE ADD_eax_into_ebx 01C3
-DEFINE ADD_ebx_into_eax 01D8
-DEFINE ADD_ecx_into_eax 01C8
-DEFINE ADD_edi_into_ecx 01F9
-DEFINE AND_EAX_EBX 21D8
-DEFINE ANDI32_EAX 25
-DEFINE CALL_EAX FFD0
-DEFINE CALL32 E8
-DEFINE CMPI8_EAX 83F8
-DEFINE CMPI8_EBP 83fd
-DEFINE CMPI8_EBX 83FB
-DEFINE CMPI8_ECX 83F9
-DEFINE CMPI8_EDX 83FA
-DEFINE CMPI8_ESI 83FE
-DEFINE CMP_EAX_EBX 39D8
-DEFINE CMP_EAX_ECX 39C8
-DEFINE CMP_EBX_ECX 39D9
-DEFINE CMP_ECX_EBX 39CB
-DEFINE CMP_EDI_ESI 39FE
-DEFINE CMP_EBX_EDX 39D3
-DEFINE COPY_EAX_to_EBP 89C5
-DEFINE COPY_EAX_to_EBX 89C3
-DEFINE COPY_EAX_to_ECX 89C1
-DEFINE COPY_EAX_to_EDX 89C2
-DEFINE COPY_EAX_to_ESI 89C6
-DEFINE COPY_EBP_to_EAX 89E8
-DEFINE COPY_EBX_to_EAX 89D8
-DEFINE COPY_EBX_to_ECX 89D9
-DEFINE COPY_EBX_to_EDX 89DA
-DEFINE COPY_ECX_to_EAX 89C8
-DEFINE COPY_ECX_to_EBX 89CB
-DEFINE COPY_EDI_to_ESI 89FE
-DEFINE COPY_EDX_to_EAX 89D0
-DEFINE COPY_EDX_to_EBP 89D5
-DEFINE COPY_EDX_to_EBX 89D3
-DEFINE COPY_ESI_to_EAX 89F0
-DEFINE COPY_ESI_to_EDI 89F7
-DEFINE IDIV_EBX F7FB
-DEFINE IMUL_EAX_by_EBX 0FAFC3
-DEFINE IMULI8_EAX 6BC0
-DEFINE IMULI8_EBP 6BED
-DEFINE INT_80 CD80
-DEFINE JBE8 76
-DEFINE JE32 0F84
-DEFINE JG32 0F8F
-DEFINE JG8 7F
-DEFINE JL32 0F8C
-DEFINE JLE32 0F8E
-DEFINE JMP32 E9
-DEFINE JNE32 0F85
-DEFINE LEA32_ECX_from_esp 8D0C24
-DEFINE LOAD32_Absolute32_eax A1
-DEFINE LOAD32_Absolute32_ebx 8B1D
-DEFINE LOAD32_Absolute32_ecx 8B0D
-DEFINE LOAD32_EAX_from_EAX 8B00
-DEFINE LOAD32_EAX_from_EAX_Immediate8 8B40
-DEFINE LOAD32_EAX_from_EBP_Immediate8 8B45
-DEFINE LOAD32_EAX_from_EBX 8B03
-DEFINE LOAD32_EAX_from_EBX_Immediate8 8B43
-DEFINE LOAD32_EAX_from_ECX_Immediate8 8B41
-DEFINE LOAD32_EAX_from_EDX_Immediate8 8B42
-DEFINE LOAD32_EBP_from_EBP 8B6D00
-DEFINE LOAD32_EBX_from_EAX_Immediate8 8B58
-DEFINE LOAD32_EBX_from_EBX 8B1B
-DEFINE LOAD32_EBX_from_EBX_Immediate8 8B5B
-DEFINE LOAD32_EBX_from_ECX_Immediate8 8B59
-DEFINE LOAD32_ECX_from_EAX_Immediate8 8B48
-DEFINE LOAD32_ECX_from_EBX 8B0B
-DEFINE LOAD32_ECX_from_ECX 8B09
-DEFINE LOAD32_ECX_from_ECX_Immediate8 8B49
-DEFINE LOAD32_ECX_from_EDX_Immediate8 8B4A
-DEFINE LOAD32_EDI_from_EDX_Immediate8 8B7A
-DEFINE LOAD32_EDX_from_EDX_Immediate8 8B52
-DEFINE LOAD8_al_from_EAX 8A00
-DEFINE LOAD8_al_from_EBX 8A03
-DEFINE LOAD8_al_from_ECX 8A01
-DEFINE LOAD8_al_from_EDX 8A02
-DEFINE LOAD8_bl_from_EBX 8A1B
-DEFINE LOAD8_bl_from_ECX 8A19
-DEFINE LOAD8_bl_from_EDX 8A1A
-DEFINE LOAD8_cl_from_EBX 8A0B
-DEFINE LOAD8_cl_from_EBX_Immediate8 8A4B
-DEFINE LOADI32_EAX B8
-DEFINE LOADI32_EBX BB
-DEFINE LOADI32_ECX B9
-DEFINE LOADI32_EDI BF
-DEFINE LOADI32_EDX BA
-DEFINE LOADI32_ESI BE
-DEFINE MOVZX_al 0FB6C0
-DEFINE MOVZX_bl 0FB6DB
-DEFINE MOVZX_cl 0FB6C9
-DEFINE NULL 00000000
-DEFINE POP_EAX 58
-DEFINE POP_EBP 5D
-DEFINE POP_EBX 5B
-DEFINE POP_ECX 59
-DEFINE POP_EDI 5F
-DEFINE POP_EDX 5A
-DEFINE POP_ESI 5E
-DEFINE PUSH_EAX 50
-DEFINE PUSH_EBP 55
-DEFINE PUSH_EBX 53
-DEFINE PUSH_ECX 51
-DEFINE PUSH_EDI 57
-DEFINE PUSH_EDX 52
-DEFINE PUSH_ESI 56
-DEFINE RETURN C3
-DEFINE SALI8_EAX C1E0
-DEFINE SHRI8_EAX C1E8
-DEFINE SHRI8_EBX C1EB
-DEFINE STORE32_Absolute32_eax A3
-DEFINE STORE32_Absolute32_ebx 891D
-DEFINE STORE32_Absolute32_ecx 890D
-DEFINE STORE32_Absolute32_edx 8915
-DEFINE STORE32_EAX_into_EBP_Immediate8 8945
-DEFINE STORE32_EAX_into_EBX 8903
-DEFINE STORE32_EAX_into_ECX_Immediate8 8941
-DEFINE STORE32_EAX_into_EDX 8902
-DEFINE STORE32_EAX_into_EDX_Immediate8 8942
-DEFINE STORE32_EBP_into_EDX_Immediate8 896A
-DEFINE STORE32_EBX_into_EAX 8918
-DEFINE STORE32_EBX_into_EAX_Immediate8 8958
-DEFINE STORE32_EBX_into_EDX_Immediate8 895A
-DEFINE STORE32_ECX_into_EAX 8908
-DEFINE STORE32_ECX_into_EAX_Immediate8 8948
-DEFINE STORE32_ECX_into_EDX_Immediate8 894A
-DEFINE STORE32_EDX_into_EAX_Immediate8 8950
-DEFINE STORE32_EDX_into_EBP_Immediate8 8955
-DEFINE STORE32_ESI_into_EBP_Immedate8 8975
-DEFINE STORE32_ESI_into_EDX_Immedate8 8972
-DEFINE STORE8_al_into_Address_EBX 8803
-DEFINE STORE8_al_into_Address_ECX 8801
-DEFINE STORE8_al_into_Address_ESI 8806
-DEFINE STORE8_bl_into_Address_ECX 8819
-DEFINE SUBI8_EAX 83E8
-DEFINE SUBI8_ECX 83E9
-DEFINE SUBI8_ESI 83EE
-DEFINE SWAP_EAX_EBX 93
-
-
- ;; Register usage:
- ;; EAX => Temps
-
- ;; Struct TYPE format: (size 28)
- ;; NEXT => 0
- ;; SIZE => 4
- ;; OFFSET => 8
- ;; INDIRECT => 12
- ;; MEMBERS => 16
- ;; TYPE => 20
- ;; NAME => 24
-
- ;; Struct TOKEN_LIST format: (size 20)
- ;; NEXT => 0
- ;; LOCALS/PREV => 4
- ;; S => 8
- ;; TYPE => 12
- ;; ARGS/DEPTH => 16
-
-; Where the ELF Header is going to hit
-; Simply jump to _start
-; Our main function
-:_start
- POP_EAX ;·Get·the·number·of·arguments
- POP_EBX ;·Get·the·program·name
- POP_EBX ;·Get·the·actual·input name
- LOADI32_ECX %0 ;·prepare·read_only
- LOADI32_EAX %5 ;·the·syscall·number·for·open()
- INT_80 ; Now open that damn file
- STORE32_Absolute32_eax &Input_file ; Preserve the file pointer we were given
-
- POP_EBX ;·Get·the·actual·output name
- LOADI32_ECX %577 ; Prepare file as O_WRONLY|O_CREAT|O_TRUNC
- LOADI32_EDX %384 ; Prepare file as RW for owner only (600 in octal)
- LOADI32_EAX %5 ;·the·syscall·number·for·open()
- INT_80 ; Now open that damn file
- CMPI8_EAX !0 ; Check for missing output
- JG32 %_start_out ; Have real input
- LOADI32_EAX %1 ; Use stdout
-
-:_start_out
- STORE32_Absolute32_eax &Output_file ; Preserve the file pointer we were given
-
- LOADI32_EAX %45 ; the Syscall # for SYS_BRK
- LOADI32_EBX %0 ; Get current brk
- INT_80 ; Let the kernel do the work
- STORE32_Absolute32_eax &MALLOC ; Set our malloc pointer
- LOADI32_EAX %0 ; HEAD = NULL
- CALL32 %read_all_tokens ; Read all tokens
- CALL32 %Reverse_List ; Reverse order
-; CALL32 %debug_list ; Try to figure out what is wrong
- STORE32_Absolute32_eax &global_token ; Set global_token
- CALL32 %program ; Convert into program
- LOADI32_EAX &header_string1 ; Our header string
- CALL32 %File_Print ; Print it
- LOAD32_Absolute32_eax &output_list ; Our output_list
- CALL32 %recursive_output ; Print core program
-; LOADI32_EAX &header_string2 ; Our Enable debug
-; CALL32 %File_Print ; Print it
- LOADI32_EAX &header_string3 ; Our second label
- CALL32 %File_Print ; Print it
- LOAD32_Absolute32_eax &globals_list ; Our globals
- CALL32 %recursive_output ; Get them
- LOADI32_EAX &header_string4 ; Our final header
- CALL32 %File_Print ; Print it
- LOAD32_Absolute32_eax &strings_list ; Our strings
- CALL32 %recursive_output ; Get them
- LOADI32_EAX &header_string5 ; Make this a bare assembly
- CALL32 %File_Print ; Print it
-
-:Done
- ; program completed Successfully
- LOADI32_EBX %0 ; All is well
- LOADI32_EAX %1 ; put the exit syscall number in eax
- INT_80 ; Call it a good day
-
-:header_string1 "
-# Core program
-"
-:header_string2 "
-:ELF_data
-"
-:header_string3 "
-# Program global variables
-"
-:header_string4 "
-# Program strings
-"
-:header_string5 "
-:ELF_end
-"
-
-
-;; read_all_tokens function
-;; Receives Token_List* in EAX
-;; Tokenizes all input and returns updated list in EAX
-;; Returns TOKEN in EAX
-;; Uses EAX for C
-:read_all_tokens
- STORE32_Absolute32_eax &Token
- CALL32 %fgetc
-:read_all_tokens_loop
- CMPI8_EAX !-4 ; Check for EOF
- JE32 %read_all_tokens_done ; Stop if found
- CALL32 %get_token ; Read all tokens
- JMP32 %read_all_tokens_loop ; Loop
-:read_all_tokens_done
- LOAD32_Absolute32_eax &Token
- RETURN
-
-
-;; get_token function
-;; Receives INT in EAX
-;; Makes a list of TOKEN_LIST
-;; C and STRING_INDEX are stored in memory, ECX is used for S and EDX is used for current
-;; Returns C in EAX
-:get_token
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
-
- STORE32_Absolute32_eax &C ; Set C
-
- LOADI32_EAX %20 ; Malloc CURRENT
- CALL32 %malloc ; Get Pointer
- COPY_EAX_to_EDX ; Set CURRENT
-
- LOADI32_EAX %256 ; Malloc the string
- CALL32 %malloc ; Get pointer to S
- COPY_EAX_to_ECX ; Set S
- STORE32_ECX_into_EDX_Immediate8 !8 ; CURRENT->S = S
-:reset
- STORE32_Absolute32_ecx &string_index ; S[0]
- LOAD32_Absolute32_eax &C ; Using C
-
- CALL32 %clear_white_space ; Clear WhiteSpace
- STORE32_Absolute32_eax &C ; Set C
-
- CMPI8_EAX !-4 ; Check for EOF
- JE32 %get_token_abort ; if EOF abort
-
- CMPI8_EAX !35 ; Check for '#'
- JNE32 %get_token_alpha ; Nope
-
- ;; Deal with # line comments
- CALL32 %purge_macro ; Let it handle it
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %reset ; Try again
-
-:get_token_alpha
- LOAD32_Absolute32_eax &C ; Send C
- LOADI32_EBX &alphas ; Get alphanumerics
- CALL32 %In_Set ; See if in set
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %get_token_symbol ; Otherwise
-
- ;; Store keywords
- LOAD32_Absolute32_eax &C ; Send C
- CALL32 %preserve_keyword ; Store
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %get_token_done ; Be done with this token
-
-:get_token_symbol
- LOAD32_Absolute32_eax &C ; Send C
- LOADI32_EBX &symbols ; Get symbols
- CALL32 %In_Set ; See if in set
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %get_token_strings ; Otherwise
-
- ;; Store symbols
- LOAD32_Absolute32_eax &C ; Send C
- CALL32 %preserve_symbol ; Store
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %get_token_done ; Be done with this token
-
-:get_token_strings
- LOAD32_Absolute32_eax &C ; Send C
- LOADI32_EBX &strings ; Get symbols
- CALL32 %In_Set ; See if in set
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %get_token_comment ; Otherwise
-
- ;; Store String
- LOAD32_Absolute32_eax &C ; Send C
- CALL32 %consume_word ; Store
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %get_token_done ; Be done with this token
-
-:get_token_comment
- LOAD32_Absolute32_eax &C ; Send C
- CMPI8_EAX !47 ; IF '/' == C
- JNE32 %get_token_else ; Otherwise
-
- CALL32 %consume_byte ; Hope it just is '/'
- STORE32_Absolute32_eax &C ; Set C
-
- CMPI8_EAX !42 ; IF '*' we have '/*'
- JNE32 %get_token_comment_line ; Check for '//'
-
- ;; Deal with /* block comments */
- CALL32 %fgetc ; get next C
- STORE32_Absolute32_eax &C ; Set C
-:get_token_comment_block_outer
- LOAD32_Absolute32_eax &C ; Using C
- CMPI8_EAX !47 ; IF '/' != C
- JE32 %get_token_comment_block_done ; be done
-
-:get_token_comment_block_inner
- LOAD32_Absolute32_eax &C ; Using C
- CMPI8_EAX !42 ; IF '*' != C
- JE32 %get_token_comment_block_iter ; jump over
-
- ;; Deal with inner loop
- CALL32 %fgetc ; get next C
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %get_token_comment_block_inner ; keep going
-
-:get_token_comment_block_iter
- CALL32 %fgetc ; get next C
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %get_token_comment_block_outer
-
-:get_token_comment_block_done
- CALL32 %fgetc ; get next C
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %reset ; throw away, try again
-
-:get_token_comment_line
- CMPI8_EAX !47 ; IF '/' we have //
- JNE32 %get_token_done ; keep if just '/'
-
- ;; Deal with // line comment
- CALL32 %fgetc ; drop to match
- STORE32_Absolute32_eax &C ; Set C
- JMP32 %reset ; throw away, try again
-
-:get_token_else
- LOAD32_Absolute32_eax &C ; Send C
- CALL32 %consume_byte
- STORE32_Absolute32_eax &C ; Set C
-
-:get_token_done
- LOAD32_Absolute32_eax &Token ; TOKEN
- STORE32_EAX_into_EDX_Immediate8 !4 ; CURRENT->PREV = TOKEN
- STORE32_EAX_into_EDX ; CURRENT->NEXT = TOKEN
- STORE32_Absolute32_edx &Token ; TOKEN = CURRENT
-
-:get_token_abort
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- LOAD32_Absolute32_eax &C ; Return C
- RETURN
-
-
-;; Malloc isn't actually required if the program being built fits in the initial memory
-;; However, it doesn't take much to add it.
-;; Requires [MALLOC] to be initialized and EAX to have the number of desired bytes
-:malloc
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- LOAD32_Absolute32_ebx &MALLOC ; Using the current pointer
- ADD_eax_into_ebx ; Request the number of desired bytes
- LOADI32_EAX %45 ; the Syscall # for SYS_BRK
- INT_80 ; call the Kernel
- LOAD32_Absolute32_eax &MALLOC ; Return pointer
- STORE32_Absolute32_ebx &MALLOC ; Update pointer
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; clear_white_space function
-;; Receives INT C in EAX
-;; Returns first non-whitespace char in EAX
-:clear_white_space
- CMPI8_EAX !32 ; Check for ' '
- JE32 %clear_white_space_wipe ; wipe it out
-
- CMPI8_EAX !10 ; Check for '\n'
- JE32 %clear_white_space_wipe ; wipe it output
-
- CMPI8_EAX !9 ; Check for '\t'
- JNE32 %clear_white_space_done ; looks like non-whitespace
-
-:clear_white_space_wipe
- CALL32 %fgetc ; Read a new byte
- CMPI8_EAX !-4 ; Check for EOF
- JE32 %clear_white_space_done ; Short circuit
- JMP32 %clear_white_space ; iterate
-
-:clear_white_space_done
- RETURN
-
-
-;; In_Set function
-;; Receives Char C in EAX and CHAR* in EBX
-;; Returns 1 if true, zero if false in EAX
-:In_Set
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
-:In_Set_loop
- LOAD8_cl_from_EBX ; Read char
- MOVZX_cl ; Zero extend it
-
- CMP_EAX_ECX ; See if they match
- JE32 %In_Set_True ; return true
-
- CMPI8_ECX !0 ; Check for NULL
- JE32 %In_Set_False ; return false
-
- ADDI8_EBX !1 ; s = s + 1
- JMP32 %In_Set_loop ; Keep looping
-
-:In_Set_True
- LOADI32_EAX %1 ; Set True
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:In_Set_False
- LOADI32_EAX %0 ; Set FALSE
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:alphas "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
-:symbols "<=>|&!-"
-:strings '22 27 00'
-
-
-;; purge_macro function
-;; Receives CH in EAX
-;; Reads chars until Line feed is read
-;; returns line feed
-:purge_macro
- CALL32 %fgetc ; read next char
- CMPI8_EAX !10 ; Check for '\n'
- JNE32 %purge_macro ; Keep going
- RETURN
-
-
-;; preserve_keyword function
-;; Receives INT C in EAX
-;; collects all chars in keyword
-;; Returns C in EAX
-;; Uses ECX for INT C
-:preserve_keyword
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; Setup C
- LOADI32_EBX &alphas ; Concerning ourselves with "abc.."
-:preserve_keyword_loop
- CALL32 %In_Set ; Check if alphanumerics
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %preserve_keyword_label ; Otherwise check for label
-
- COPY_ECX_to_EAX ; Pass C
- CALL32 %consume_byte ; consume that byte
- COPY_EAX_to_ECX ; Update C
- JMP32 %preserve_keyword_loop ; keep looping
-
-:preserve_keyword_label
- COPY_ECX_to_EAX ; Fix return
- CMPI8_EAX !58 ; Check for ':'
- JNE32 %preserve_keyword_done ; be done
-
- ;; Fix our goto label
- CALL32 %fixup_label ; Fix the label
- LOADI32_EAX %32 ; Return Whitespace
-
-:preserve_keyword_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; preserve_symbol function
-;; Receives INT C in EAX
-;; collects all chars in symbol
-;; Returns C in EAX
-;; Uses ECX for INT C
-:preserve_symbol
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; Setup C
- LOADI32_EBX &symbols ; Concerning ourselves with "<=>.."
-:preserve_symbol_loop
- CALL32 %In_Set ; Check if alphanumerics
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %preserve_symbol_done ; Otherwise be done
-
- COPY_ECX_to_EAX ; Pass C
- CALL32 %consume_byte ; consume that byte
- COPY_EAX_to_ECX ; Update C
- JMP32 %preserve_symbol_loop ; keep looping
-
-:preserve_symbol_done
- COPY_ECX_to_EAX ; Fix return
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; consume_word function
-;; receives INT C in EAX
-;; returns INT C in EAX
-;; Uses EAX for C, EBX for FREQ and ECX for ESCAPE
-:consume_word
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_EBX ; FREQ = C
- LOADI32_ECX %0 ; ESCAPE = FALSE
-:consume_word_loop
- CMPI8_ECX !0 ; IF !ESCAPE
- JNE32 %consume_word_escape ; Enable escape
-
- CMPI8_EAX !92 ; if '\\'
- JNE32 %consume_word_iter ; keep state
-
- LOADI32_ECX %1 ; ESCAPE = TRUE
- JMP32 %consume_word_iter ; keep going
-
-:consume_word_escape
- LOADI32_ECX %0 ; ESCAPE = FALSE
-
-:consume_word_iter
- CALL32 %consume_byte ; read next char
-
- CMPI8_ECX !0 ; IF ESCAPE
- JNE32 %consume_word_loop ; keep looping
-
- CMP_EAX_EBX ; IF C != FREQ
- JNE32 %consume_word_loop ; keep going
-
- CALL32 %fgetc ; return next char
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; consume_byte function
-;; Receives INT C in EAX
-;; Inserts C into string S, updates String S
-;; Returns Next char in EAX
-:consume_byte
- PUSH_EBX ; Protect EBX
- LOAD32_Absolute32_ebx &string_index ; S[0]
- STORE8_al_into_Address_EBX ; S[0] = C
- ADDI8_EBX !1 ; S = S + 1
- STORE32_Absolute32_ebx &string_index ; Update S
- CALL32 %fgetc
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; fixup_label function
-;; Receives S in ECX
-;; prepends ':' to string and returns registers un changed
-;; Uses EAX for HOLD, EBX for PREV and ECX for S[0]
-:fixup_label
- PUSH_EAX ; Protect EAX
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOADI32_EAX %58 ; HOLD = ':'
- LOAD32_ECX_from_EDX_Immediate8 !8 ; HOLD_STRING[0]
-:fixup_label_loop
- COPY_EAX_to_EBX ; PREV = HOLD
- LOAD8_al_from_ECX ; HOLD = HOLD_STRING[I]
- MOVZX_al ; make useful
- STORE8_bl_into_Address_ECX ; HOLD_STRING[I] = PREV
- ADDI8_ECX !1 ; I = I + 1
- CMPI8_EAX !0 ; IF NULL == HOLD
- JNE32 %fixup_label_loop ; Keep looping
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- POP_EAX ; Restore EAX
- RETURN
-
-
-;; fgetc function
-;; Loads FILE* from [INPUT_FILE]
-;; Returns -4 (EOF) or char in EAX
-:fgetc
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- LOADI32_EAX %-4 ; Put EOF in eax
- PUSH_EAX ; Assume bad (If nothing read, value will remain EOF)
- LEA32_ECX_from_esp ; Get stack address
- LOAD32_Absolute32_ebx &Input_file ; Where are we reading from
- LOADI32_EAX %3 ; the syscall number for read
- LOADI32_EDX %1 ; set the size of chars we want
- INT_80 ; call the Kernel
- POP_EAX ; Get either char or EOF
- CMPI8_EAX !-4 ; Check for EOF
- JE32 %fgetc_done ; Return as is
- MOVZX_al ; Make it useful
-:fgetc_done
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; Reverse_List function
-;; Receives List in EAX
-;; Returns the list reversed in EAX
-:Reverse_List
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_EBX ; Set HEAD
- LOADI32_EAX %0 ; ROOT = NULL
-:Reverse_List_Loop
- CMPI8_EBX !0 ; WHILE HEAD != NULL
- JE32 %Reverse_List_Done ; Stop otherwise
-
- LOAD32_ECX_from_EBX ; NEXT = HEAD->NEXT
- STORE32_EAX_into_EBX ; HEAD->NEXT = ROOT
- COPY_EBX_to_EAX ; ROOT = HEAD
- COPY_ECX_to_EBX ; HEAD = NEXT
- JMP32 %Reverse_List_Loop ; Keep Going
-
-:Reverse_List_Done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; recursive_output function
-;; Receives list in EAX
-;; walks the list and prints the I->S for all nodes backwards
-;; Uses EBX for I
-:recursive_output
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CMPI8_EAX !0 ; Check for NULL
- JE32 %recursive_output_done ; Skip the work
- COPY_EAX_to_EBX ; I = Head
-
- LOAD32_EAX_from_EBX ; Iterate to next Token
- CALL32 %recursive_output ; Recurse
-
- LOAD32_EAX_from_EBX_Immediate8 !8 ; Using S
- CALL32 %File_Print ; Print it
-
-:recursive_output_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; File_Print function
-;; Receives CHAR* in EAX
-;; calls fputc for every non-null char
-:File_Print
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_EBX ; Protect S
- CMPI8_EAX !0 ; Protect against nulls
- JE32 %File_Print_Done ; Simply don't try to print them
-:File_Print_Loop
- LOAD8_al_from_EBX ; Read byte
- MOVZX_al ; zero extend
- CMPI8_EAX !0 ; Check for NULL
- JE32 %File_Print_Done ; Stop at NULL
-
- CALL32 %fputc ; write it
- ADDI8_EBX !1 ; S = S + 1
- JMP32 %File_Print_Loop ; Keep going
-
-:File_Print_Done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; fputc function
-;; receives CHAR in EAX and load FILE* from [OUTPUT_FILE]
-;; writes char and returns
-:fputc
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_EAX ; We are writing eax
- LEA32_ECX_from_esp ; Get stack address
- LOAD32_Absolute32_ebx &Output_file ; Write to target file
- LOADI32_EAX %4 ; the syscall number for write
- LOADI32_EDX %1 ; set the size of chars we want
- INT_80 ; call the Kernel
- POP_EAX ; Restore stack
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; program function
-;; receives nothing, returns nothing
-;; Uses EAX for type_size
-:program
- ;; The binary initialized the globals to null, so we can skip those steps
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
-
-:new_type
- LOAD32_Absolute32_eax &global_token ; Using global_token
- CMPI8_EAX !0 ; Check if NULL
- JE32 %program_done ; Be done if null
-
- LOAD32_EBX_from_EAX_Immediate8 !8 ; GLOBAL_TOKEN->S
- LOADI32_EAX &constant ; "CONSTANT"
- CALL32 %match ; IF GLOBAL_TOKEN->S == "CONSTANT"
- CMPI8_EAX !0 ; If true
- JNE32 %program_else ; Looks like not a constant
-
- ;; Deal with minimal constant case
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EBX %0 ; NULL
- LOAD32_Absolute32_ecx &global_constant_list ; global_constant_list
- CALL32 %sym_declare ; Declare that constant
- STORE32_Absolute32_eax &global_constant_list ; global_constant_list = sym_declare(global_token->s, NULL, global_constant_list);
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX ; global_token->next
- STORE32_EBX_into_EAX_Immediate8 !16 ; global_constant_list->arguments = global_token->next
-
- LOAD32_EBX_from_EBX ; global_token->next->next
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->next->next
- JMP32 %new_type ; go around again
-
-:program_else
- CALL32 %type_name ; Figure out the type_size
- CMPI8_EAX !0 ; IF NULL == type_size
- JE32 %new_type ; it was a new type
-
- ;; Add to global symbol table
- COPY_EAX_to_EBX ; put type_size in the right spot
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD32_Absolute32_ecx &global_symbol_list ; Using global_symbol_list
- CALL32 %sym_declare ; Declare symbol
- STORE32_Absolute32_eax &global_symbol_list ; global_symbol_list = sym_declare(global_token->s, type_size, global_symbol_list);
- LOAD32_Absolute32_ebx &global_token ; Using global token
- LOAD32_EBX_from_EBX ; global_token->next
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->next
-
- LOAD32_Absolute32_ebx &global_token ; Using global token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &semicolon ; ";"
- CALL32 %match ; if(match(";", global_token->s))
- CMPI8_EAX !0 ; If true
- JNE32 %program_function ; looks like not a match
-
- ;; Deal with the global variable
- LOAD32_Absolute32_ebx &globals_list ; Using globals_list
- LOADI32_EAX &program_string_0 ; ":GLOBAL_"
- CALL32 %emit ; Emit it
- COPY_EAX_to_EBX ; update globals_list
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !4 ; global token->prev
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->prev->s
- CALL32 %emit ; Emit it
-
- COPY_EAX_to_EBX ; update globals_list
- LOADI32_EAX &program_string_1 ; "\nNOP\n"
- CALL32 %emit ; Emit it
- STORE32_Absolute32_eax &globals_list ; update globals_list
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
- JMP32 %new_type ; go around again
-
-:program_function
- LOAD32_Absolute32_ebx &global_token ; Using global token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_paren ; "("
- CALL32 %match ; if(match(";", global_token->s))
- CMPI8_EAX !0 ; If true
- JNE32 %program_error ; Otherwise deal with error case
-
- ;; Deal with function definition
- CALL32 %declare_function ; Lets get the parsing rolling
- JMP32 %new_type ; Keep looping through functions
-
-:program_error
- ;; Deal with the case of something we don't support
- ;; NOT IMPLEMENTED
-
-:program_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-;; Strings needed by the program function
-:program_string_0 ":GLOBAL_"
-:program_string_1 "
-NOP
-"
-
-
-;; declare_function function
-;; Receives nothing and returns nothing
-;; Sets current function and adds it to the global function list
-:declare_function
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOADI32_EAX %0 ; Using NULL
- STORE32_Absolute32_eax ¤t_count ; current_count = 0
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !4 ; global token->prev
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->prev->s
- LOADI32_EBX %0 ; NULL
- LOAD32_Absolute32_ecx &global_function_list ; global_function_list
- CALL32 %sym_declare ; sym_declare(global_token->prev->s, NULL, global_function_list);
- STORE32_Absolute32_eax &function ; function = sym_declare(global_token->prev->s, NULL, global_function_list);
- STORE32_Absolute32_eax &global_function_list ; global_function_list = function
-
- CALL32 %collect_arguments ; collect all of the function arguments
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->s
- LOADI32_EBX &semicolon ; ";"
- CALL32 %match ; IF global token->s == ";"
- CMPI8_EAX !0 ; If true
- JNE32 %declare_function_full ; It was a prototype
-
- ;; Deal with prototypes
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX ; global token->next
- STORE32_Absolute32_eax &global_token ; global token = global token->next
- JMP32 %declare_function_done ; Move on
-
-:declare_function_full
- ;; Deal will full function definitions
- LOADI32_EAX &declare_function_string_0 ; "# Defining function "
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &function ; function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->s
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &declare_function_string_1 ; "\n:FUNCTION_"
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &function ; function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->s
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &declare_function_string_3 ; "\n"
- CALL32 %emit_out ; emit it
-
- CALL32 %statement ; Recursively get the function pieces
-
- LOAD32_Absolute32_eax &output_list ; output
- LOAD32_EAX_from_EAX_Immediate8 !8 ; output->s
- LOADI32_EBX &declare_function_string_2 ; "RETURN\n"
- CALL32 %match ; IF output->s == "RETURN\n"
- CMPI8_EAX !0 ; If true we can skip adding it
- JE32 %declare_function_done ; otherwise we need to add it
-
- ;; Add the return to the end of a function lacking a return;
- LOADI32_EAX &declare_function_string_2 ; "RETURN\n"
- CALL32 %emit_out ; emit it
-
-:declare_function_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:declare_function_string_0 "# Defining function "
-:declare_function_string_1 "
-:FUNCTION_"
-:declare_function_string_2 "RETURN
-"
-:declare_function_string_3 "
-"
-
-
-;; collect_arguments function
-;; Receives nothing
-;; Returns Nothing
-;; Adds arguments to the function definition
-;; holds struct type* type_size in ECX, then replace with struct token_list* a in ECX when type_size is used
-:collect_arguments
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-:collect_arguments_loop
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &close_paren ; ")"
- CALL32 %match ; IF global_token->S == ")"
- CMPI8_EAX !0 ; we reached the end
- JE32 %collect_arguments_done ; be done
-
- ;; deal with the case of there are arguments
- CALL32 %type_name ; Get the type
- COPY_EAX_to_ECX ; put type_size safely out of the way
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &close_paren ; ")"
- CALL32 %match ; IF global_token->S == ")"
- CMPI8_EAX !0 ; is a foo(int, char,void) case
- JE32 %collect_arguments_common ; deal with commas
-
- ;; Trying second else
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &comma ; ","
- CALL32 %match ; IF global_token->S == ","
- CMPI8_EAX !0 ; then deal with the common
- JE32 %collect_arguments_common ; case of commas between arguments
-
- ;; deal with foo(int a, char b)
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- COPY_ECX_to_EBX ; put type_size in the right place
- LOAD32_Absolute32_ecx &function ; Using function
- LOAD32_ECX_from_ECX_Immediate8 !16 ; function->args
- CALL32 %sym_declare ; sym_declare(global_token->s, type_size, function->arguments);
- COPY_EAX_to_ECX ; put a in a safe place
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args
- CMPI8_EAX !0 ; IF function->args == NULL
- JNE32 %collect_arguments_another ; otherwise it isn't the first
-
- ;; Deal with the case of first argument in the function
- LOADI32_EAX %-4 ; -4
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->depth = -4
- JMP32 %collect_arguments_next ; get to next
-
-:collect_arguments_another
- ;; deal with the case of non-first arguments
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args->depth
- SUBI8_EAX !4 ; function->args->depth - 4
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->depth = function->args->depth - 4
-
-:collect_arguments_next
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOAD32_Absolute32_eax &function ; Using function
- STORE32_ECX_into_EAX_Immediate8 !16 ; function->args = a
-
-:collect_arguments_common
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &comma ; ","
- CALL32 %match ; IF global_token->S == ","
- CMPI8_EAX !0 ; then deal with the comma
- JNE32 %collect_arguments_loop ; otherwise loop
-
- ;; keep foo(bar(), 1) expressions working
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
- JMP32 %collect_arguments_loop ; keep going
-
-:collect_arguments_done
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; statement function
-;; Receives nothing
-;; Returns nothing
-;; Walks down global_token recursively to collect the contents of the function
-:statement
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_curly_brace ; "{"
- CALL32 %match ; IF global_token->S == "{"
- JNE32 %statement_label ; otherwise try label
-
- ;; deal with { statement }
- CALL32 %recursive_statement ; Statements inside of statements for days
- JMP32 %statement_done ; Be done
-
-:statement_label
- LOAD8_al_from_EBX ; global_token->S[0]
- MOVZX_al ; make it useful
- CMPI8_EAX !58 ; IF global_token->S == ':'
- JNE32 %statement_local ; otherwise try locals
-
- ;; deal with labels
- COPY_EBX_to_EAX ; put global_token->S in the right spot
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &statement_string_0 ; Using "\t#C goto label\n"
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
- JMP32 %statement_done ; be done
-
-:statement_local
- COPY_EBX_to_EAX ; put global_token->S in the right place
- LOADI32_EBX &prim_types ; pointer to primative types
- CALL32 %lookup_type ; See if found
- CMPI8_EAX !0 ; IF NULL == lookup_type(global_token->S, prim_types)
- JNE32 %statement_local_success ; Sweet a new local
-
- ;; Second chance
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &struct ; "struct"
- CALL32 %match ; IF global_token->S == "struct"
- CMPI8_EAX !0 ; then we are a local
- JNE32 %statement_if ; otherwise try IF
-
-:statement_local_success
- CALL32 %collect_local ; Grab those locals
- JMP32 %statement_done ; be done
-
-:statement_if
- LOADI32_EAX &if_string ; Using "if"
- CALL32 %match ; IF global_token->S == "if"
- CMPI8_EAX !0 ; then we have an if statement
- JNE32 %statement_do ; otherwise try DO
-
- ;; Deal with IF statement
- CALL32 %process_if ; DO IT
- JMP32 %statement_done ; be done
-
-:statement_do
- LOADI32_EAX &do_string ; Using "do"
- CALL32 %match ; IF global_token->S == "do"
- CMPI8_EAX !0 ; then we have a do statement
- JNE32 %statement_while ; otherwise try WHILE
-
- ;; Deal with DO statement
- CALL32 %process_do ; DO IT
- JMP32 %statement_done ; be done
-
-:statement_while
- LOADI32_EAX &while_string ; Using "while"
- CALL32 %match ; IF global_token->S == "while"
- CMPI8_EAX !0 ; then we have a while statement
- JNE32 %statement_for ; otherwise try FOR
-
- ;; Deal with WHILE statement
- CALL32 %process_while ; DO IT
- JMP32 %statement_done ; be done
-
-:statement_for
- LOADI32_EAX &for_string ; Using "for"
- CALL32 %match ; IF global_token->S == "for"
- CMPI8_EAX !0 ; then we have a for statement
- JNE32 %statement_asm ; otherwise try ASM
-
- ;; Deal with FOR statement
- CALL32 %process_for ; DO IT
- JMP32 %statement_done ; be done
-
-:statement_asm
- LOADI32_EAX &asm_string ; Using "asm"
- CALL32 %match ; IF global_token->S == "asm"
- CMPI8_EAX !0 ; then we have an asm statement
- JNE32 %statement_goto ; otherwise try GOTO
-
- ;; Deal with ASM statement
- CALL32 %process_asm ; Hit it
- JMP32 %statement_done ; be done
-
-:statement_goto
- LOADI32_EAX &goto_string ; Using "goto"
- CALL32 %match ; IF global_token->S == "goto"
- CMPI8_EAX !0 ; then we have a goto statement
- JNE32 %statement_return ; Otherwise try RETURN
-
- ;; Deal with GOTO statement
- LOADI32_EAX &statement_string_1 ; Using "JUMP %"
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &statement_string_2 ; Using "\n"
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure it has the required
- JMP32 %statement_done ; Be done
-
-:statement_return
- LOADI32_EAX &return_string ; Using "return"
- CALL32 %match ; IF global_token->S == "return"
- CMPI8_EAX !0 ; then we have a return statement
- JNE32 %statement_break ; Otherwise try BREAK
-
- ;; Deal with RETURN Statement
- CALL32 %return_result ; Return anything they want
- JMP32 %statement_done ; be done
-
-:statement_break
- LOADI32_EAX &break_string ; Using "break"
- CALL32 %match ; IF global_token->S == "break"
- CMPI8_EAX !0 ; then we have a break statement
- JNE32 %statement_continue ; Otherwise try CONTINUE
-
- ;; Deal with BREAK statement
- CALL32 %process_break ; Lets do some damage
- JMP32 %statement_done ; be done
-
-:statement_continue
- LOADI32_EAX &continue_string ; Using "continue"
- CALL32 %match ; IF global_token->S == "continue"
- CMPI8_EAX !0 ; then we have a continue statement
- JNE32 %statement_else ; Otherwise we are punting to an expression
-
- ;; Deal with CONTINUE statement
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOADI32_EAX &statement_string_3 ; Using "\n#continue statement\n"
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Don't forget the ";"
- JMP32 %statement_done ; Be done
-
-:statement_else
- CALL32 %expression ; Collect expression
- LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; make sure we have it
-
-:statement_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:statement_string_0 " #C goto label
-"
-:statement_string_1 "JUMP %"
-:statement_string_2 "
-"
-:statement_string_3 "
-#continue statement
-"
-:statement_string_4 "ERROR in statement
-Missing ;
-"
-
-
-;; recursive_statement function
-;; Receives nothing
-;; Returns nothing
-;; Walks the global_token list to build the contents of statements
-;; Uses struct token_list* frame in ECX
-:recursive_statement
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOAD32_Absolute32_ecx &function ; Using function
- LOAD32_ECX_from_ECX_Immediate8 !4 ; frame = function->locals
-
-:recursive_statement_loop
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &close_curly_brace ; Using "}"
- CALL32 %match ; IF global_token->S == "}"
- CMPI8_EAX !0 ; Then we are done recuring
- JE32 %recursive_statement_cleanup ; and then we clean up
-
- ;; Deal with the recursive calls
- CALL32 %statement ; Deal with another statement
- JMP32 %recursive_statement_loop ; loop some more
-
-:recursive_statement_cleanup
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOADI32_EAX &recursive_statement_string_0 ; Using "RETURN\n"
- LOAD32_Absolute32_ebx &output_list ; Using output
- LOAD32_EBX_from_EBX_Immediate8 !8 ; output->S
- CALL32 %match ; IF output->S == "RETURN\n"
- CMPI8_EAX !0 ; Then we can skip the clean up
- JE32 %recursive_statement_done ; and be done
-
- ;; Deal with cleanup
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EBX_from_EBX_Immediate8 !4 ; i = function->locals
- LOADI32_EAX &recursive_statement_string_1 ; Using "POP_ebx\t# _recursive_statement_locals\n"
-
-:recursive_statement_locals
- CMP_ECX_EBX ; IF frame != i
- JE32 %recursive_statement_done ; Otherwise be done
-
- ;; Lets emit
- CALL32 %emit_out ; emit it
- LOAD32_EBX_from_EBX ; i = i->next
- JMP32 %recursive_statement_locals ; keep going
-
-:recursive_statement_done
- LOAD32_Absolute32_eax &function ; Using function
- STORE32_ECX_into_EAX_Immediate8 !4 ; function->locals = frame
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:recursive_statement_string_0 "RETURN
-"
-:recursive_statement_string_1 "POP_ebx # _recursive_statement_locals
-"
-
-
-;; return_result function
-;; Receives nothing
-;; Returns nothing
-;; Cleans up function and generates return
-;; Also handles returing expressions
-:return_result
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
-
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; make it useful
- CMPI8_EAX !59 ; If global_token->S[0] == ';'
- JE32 %return_result_cleanup ; Go straight to cleanup
-
- CALL32 %expression ; get the expression we are returning
-
-:return_result_cleanup
- LOADI32_EAX &return_result_string_0 ; Using "ERROR in return_result\nMISSING ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EBX_from_EBX_Immediate8 !4 ; function->locals
- LOADI32_EAX &return_result_string_1 ; Using "POP_ebx\t# _return_result_locals\n"
-:return_result_locals
- CMPI8_EBX !0 ; IF NULL == i
- JE32 %return_result_done ; Be done
-
- CALL32 %emit_out ; Emit out pop
- LOAD32_EBX_from_EBX ; i = i->NEXT
- JMP32 %return_result_locals ; Keep going
-
-:return_result_done
- LOADI32_EAX &return_result_string_2 ; Using "RETURN\n"
- CALL32 %emit_out ; Emit it
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:return_result_string_0 "ERROR in return_result
-MISSING ;
-"
-:return_result_string_1 "POP_ebx # _return_result_locals
-"
-:return_result_string_2 "RETURN
-"
-
-
-;; collect_local function
-;; Receives nothing
-;; Returns nothing
-;; Walks global_token list to create function locals
-;; Uses ECX for struct token_list* A
-:collect_local
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %type_name ; Get the local's type
-
- COPY_EAX_to_EBX ; Put struct type* type_size in the right place
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD32_Absolute32_ecx &function ; Using function
- LOAD32_ECX_from_ECX_Immediate8 !4 ; function->locals
- CALL32 %sym_declare ; Declare it
- COPY_EAX_to_ECX ; put it away safely
-
- ;; Try for main
- LOADI32_EAX &main_string ; Using "main"
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EBX_from_EBX_Immediate8 !8 ; function->S
- CALL32 %match ; IF match("main", function->s)
- CMPI8_EAX !0 ; possible
- JNE32 %collect_local_fresh ; try to see if fresh function
-
- ;; Ok we are in main, now to see if main is fresh
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals
- CMPI8_EAX !0 ; IF NULL == function->locals
- JNE32 %collect_local_fresh ; try to see if fresh function
-
- ;; Sweet we are in a fresh main
- LOADI32_EAX %-20 ; We start at -20
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = -20
- JMP32 %collect_local_common ; Go to the commons
-
-:collect_local_fresh
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args
- CMPI8_EAX !0 ; IF NULL == function->locals
- JNE32 %collect_local_first ; Otherwise see if first
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals
- CMPI8_EAX !0 ; IF NULL == function->locals
- JNE32 %collect_local_first ; Otherwise try first
-
- ;; Sweet we are in a fresh function
- LOADI32_EAX %-8 ; We start at -8
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = -8
- JMP32 %collect_local_common ; Go to the commons
-
-:collect_local_first
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals
- CMPI8_EAX !0 ; IF NULL == function->locals
- JNE32 %collect_local_else ; Looks like we are just another local
-
- ;; Ok we are the first local
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args->depth
- SUBI8_EAX !8 ; function->arguments->depth - 8
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = function->arguments->depth - 8
- JMP32 %collect_local_common ; Go to the commons
-
-:collect_local_else
- ;; Always the last to know
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals
- LOAD32_EAX_from_EAX_Immediate8 !16 ; function->locals->depth
- SUBI8_EAX !4 ; function->locals->depth - 4
- STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = function->locals->depth - 4
-
-:collect_local_common
- LOAD32_Absolute32_eax &function ; Using function
-
- STORE32_ECX_into_EAX_Immediate8 !4 ; function->locals = a
- LOAD32_ECX_from_ECX_Immediate8 !8 ; a->S
-
- LOADI32_EAX &collect_local_string_0 ; Using "# Defining local "
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &collect_local_string_1 ; Using "\n"
- CALL32 %emit_out ; emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; Using "="
- CALL32 %match ; IF match("=", global_token->s)
- CMPI8_EAX !0 ; Deal with assignment
- JNE32 %collect_local_done ; Otherwise finish it
-
- ;; Deal with assignment
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- CALL32 %expression ; Recurse
-
-:collect_local_done
- LOADI32_EAX &collect_local_string_2 ; Using "ERROR in collect_local\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &collect_local_string_3 ; Using "PUSH_eax\t#"
- CALL32 %emit_out ; emit it
-
- COPY_ECX_to_EAX ; put A->S where it belongs
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &collect_local_string_1 ; Using "\n"
- CALL32 %emit_out ; emit it
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:collect_local_string_0 "# Defining local "
-:collect_local_string_1 "
-"
-:collect_local_string_2 "ERROR in collect_local
-Missing ;
-"
-:collect_local_string_3 "PUSH_eax #"
-
-
-;; process_asm function
-;; Receives nothing
-;; Returns nothing
-;; Simply inlines the asm statements
-;; Uses EBX for global_token temp storage
-:process_asm
- PUSH_EBX ; Protect EBX
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &process_asm_string_0 ; Using "ERROR in process_asm\nMISSING (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
-:process_asm_iter
- LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !34 ; IF global_token->S[0] == '\"'
- JNE32 %process_asm_done ; Otherwise be done
-
- LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S
- ADDI8_EAX !1 ; global_token->S + 1
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &process_asm_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_EBX_from_EBX ; global_token->NEXT
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->NEXT
- JMP32 %process_asm_iter ; keep going
-
-:process_asm_done
- LOADI32_EAX &process_asm_string_2 ; Using "ERROR in process_asm\nMISSING )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &process_asm_string_3 ; Using "ERROR in process_asm\nMISSING ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- POP_EBX ; Restore EBX
- RETURN
-
-:process_asm_string_0 "ERROR in process_asm
-MISSING (
-"
-:process_asm_string_1 "
-"
-:process_asm_string_2 "ERROR in process_asm
-MISSING )
-"
-:process_asm_string_3 "ERROR in process_asm
-MISSING ;
-"
-
-
-;; process_if function
-;; Receives nothing
-;; Returns Nothing
-;; Increments current_count recurses into expression + statement
-;; Uses ECX for char* NUMBER_STRING
-:process_if
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax ¤t_count ; Using current count
- COPY_EAX_to_EBX ; Preparing for update
- ADDI8_EBX !1 ; current_count + 1
- STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1
- CALL32 %numerate_number ; convert to string
- COPY_EAX_to_ECX ; put NUMBER_STRING in place
-
- LOADI32_EAX &process_if_string_0 ; Using "# IF_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &process_if_string_1 ; Using "ERROR in process_if\nMISSING (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %expression ; Recurse to get the IF(...) part
-
- LOADI32_EAX &process_if_string_2 ; Using "TEST\nJUMP_EQ %ELSE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_if_string_3 ; Using "ERROR in process_if\nMISSING )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %statement ; Recursive to get the IF(){...} part
-
- LOADI32_EAX &process_if_string_4 ; Using "JUMP %_END_IF_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_if_string_5 ; Using ":ELSE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &else_string ; Using "else"
- CALL32 %match ; IF global_token->S == "else"
- CMPI8_EAX !0 ; Then we need to collect the else too
- JNE32 %process_if_done ; Otherwise finish up
-
- ;; deal with else statement
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- CALL32 %statement ; Recurse to get the ELSE {...} part
-
-:process_if_done
- LOADI32_EAX &process_if_string_6 ; Using ":_END_IF_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:process_if_string_0 "# IF_"
-:process_if_string_1 "ERROR in process_if
-MISSING (
-"
-:process_if_string_2 "TEST
-JUMP_EQ %ELSE_"
-:process_if_string_3 "ERROR in process_if
-MISSING )
-"
-:process_if_string_4 "JUMP %_END_IF_"
-:process_if_string_5 ":ELSE_"
-:process_if_string_6 ":_END_IF_"
-
-
-;; save_break_frame microfunction
-;; Overwrites EAX abd EBX
-;; Saves break frame on stack
-;; Returns to caller
-:save_break_frame
- POP_EBX ; Save return Address
- LOAD32_Absolute32_eax &break_frame ; Get break_frame
- PUSH_EAX ; Store as nested_locals
- LOAD32_Absolute32_eax &break_target_head ; Get break_target_head
- PUSH_EAX ; Store as nested_break_head
- LOAD32_Absolute32_eax &break_target_func ; Get break_target_func
- PUSH_EAX ; Store as nested_break_func
- LOAD32_Absolute32_eax &break_target_num ; Get break_target_num
- PUSH_EAX ; Store as nested_break_num
- PUSH_EBX ; Put return back in place
- RETURN ; Return to caller
-
-
-;; restore_break_frame microfunction
-;; Overwrites EAX and EBX
-;; Restores break frame from stack
-;; Returns to caller
-:restore_break_frame
- POP_EBX ; Save return Address
- POP_EAX ; Get nested_break_num
- STORE32_Absolute32_eax &break_target_num ; Restore break_target_num
- POP_EAX ; Get nested_break_func
- STORE32_Absolute32_eax &break_target_func ; Restore break_target_func
- POP_EAX ; Get nested_break_head
- STORE32_Absolute32_eax &break_target_head ; Restore break_target_head
- POP_EAX ; Get nested_locals
- STORE32_Absolute32_eax &break_frame ; Restore break_frame
- PUSH_EBX ; Put return back in place
- RETURN ; Return to caller
-
-
-;; set_break_frame microfunction
-;; Receives char* head in EAX and char* num in EBX
-;; Overwrites EAX and EBX
-;; Returns to calling function
-:set_break_frame
- STORE32_Absolute32_eax &break_target_head ; update break_target_head
- STORE32_Absolute32_ebx &break_target_num ; update break_target_num
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EAX_from_EBX_Immediate8 !4 ; function->LOCALS
- STORE32_Absolute32_eax &break_frame ; break_frame = function->LOCALS
- LOAD32_EAX_from_EBX_Immediate8 !8 ; function->S
- STORE32_Absolute32_eax &break_target_func ; break_target_func = function->S
- RETURN ; Return to sender
-
-
-;; process_do function
-;; Receives Nothing
-;; Returns Nothing
-;; Increments current_count and leverages save/restore_break_frame pieces
-;; Uses ECX for char* NUMBER_STRING
-:process_do
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %save_break_frame ; Save the frame
-
- LOAD32_Absolute32_eax ¤t_count ; Using current count
- COPY_EAX_to_EBX ; Preparing for update
- ADDI8_EBX !1 ; current_count + 1
- STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1
- CALL32 %numerate_number ; convert to string
- COPY_EAX_to_ECX ; put NUMBER_STRING in place
-
- LOADI32_EAX &process_do_string_0 ; Using "DO_END_"
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %set_break_frame ; Set the frame
-
- LOADI32_EAX &process_do_string_1 ; Using ":DO_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- CALL32 %statement ; Do the DO {...} part
-
- LOADI32_EAX &process_do_string_2 ; Using "ERROR in process_do\nMISSING while\n"
- LOADI32_EBX &while_string ; Using "while"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &process_do_string_3 ; Using "ERROR in process_do\nMISSING (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %expression ; Do the WHILE (...) part
-
- LOADI32_EAX &process_do_string_4 ; Using "ERROR in process_do\nMISSING )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &process_do_string_5 ; Using "ERROR in process_do\nMISSING ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &process_do_string_6 ; Using "TEST\nJUMP_NE %DO_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_do_string_7 ; Using ":DO_END_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- CALL32 %restore_break_frame ; Restore the old break frame
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:process_do_string_0 "DO_END_"
-:process_do_string_1 ":DO_"
-:process_do_string_2 "ERROR in process_do
-MISSING while
-"
-:process_do_string_3 "ERROR in process_do
-MISSING (
-"
-:process_do_string_4 "ERROR in process_do
-MISSING )
-"
-:process_do_string_5 "ERROR in process_do
-MISSING ;
-"
-:process_do_string_6 "TEST
-JUMP_NE %DO_"
-:process_do_string_7 ":DO_END_"
-
-
-;; process_while function
-;; Receives nothing
-;; Returns nothing
-;; Increments current_count and leverages save/restore_break_frame pieces
-;; Uses ECX for char* NUMBER_STRING
-:process_while
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %save_break_frame ; Save break_frame
-
- LOAD32_Absolute32_eax ¤t_count ; Using current count
- COPY_EAX_to_EBX ; Preparing for update
- ADDI8_EBX !1 ; current_count + 1
- STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1
- CALL32 %numerate_number ; convert to string
- COPY_EAX_to_ECX ; put NUMBER_STRING in place
-
- LOADI32_EAX &process_while_string_0 ; Using "END_WHILE_"
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %set_break_frame ; Set it and forget it
-
- LOADI32_EAX &process_while_string_1 ; Using ":WHILE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &process_while_string_2 ; Using "ERROR in process_while\nMISSING (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %expression ; Deal with the WHILE (...) part
-
- LOADI32_EAX &process_while_string_3 ; Using "TEST\nJUMP_EQ %END_WHILE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_while_string_4 ; Using "# THEN_while_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_while_string_5 ; Using "ERROR in process_while\nMISSING )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %statement ; Deal with the {....} part
-
- LOADI32_EAX &process_while_string_6 ; Using "JUMP %WHILE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_while_string_7 ; Using ":END_WHILE_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- CALL32 %restore_break_frame ; Restore the old break frame
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:process_while_string_0 "END_WHILE_"
-:process_while_string_1 ":WHILE_"
-:process_while_string_2 "ERROR in process_while
-MISSING (
-"
-:process_while_string_3 "TEST
-JUMP_EQ %END_WHILE_"
-:process_while_string_4 "# THEN_while_"
-:process_while_string_5 "ERROR in process_while
-MISSING )
-"
-:process_while_string_6 "JUMP %WHILE_"
-:process_while_string_7 ":END_WHILE_"
-
-
-;; process_for function
-;; Receives Nothing
-;; Returns Nothing
-;; Increments current_count and leverages save/restore_break_frame pieces
-;; Uses ECX for char* NUMBER_STRING
-:process_for
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %save_break_frame ; Save the frame
-
- LOAD32_Absolute32_eax ¤t_count ; Using current count
- COPY_EAX_to_EBX ; Preparing for update
- ADDI8_EBX !1 ; current_count + 1
- STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1
- CALL32 %numerate_number ; convert to string
- COPY_EAX_to_ECX ; put NUMBER_STRING in place
-
- LOADI32_EAX &process_for_string_0 ; Using "FOR_END_"
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %set_break_frame ; Set it and forget it
-
- LOADI32_EAX &process_for_string_1 ; Using "# FOR_initialization_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &process_for_string_2 ; Using "ERROR in process_for\nMISSING (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make Sure we have it
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &semicolon ; Using ";"
- CALL32 %match ; IF global_token->S == ";"
- CMPI8_EAX !0 ; Then no initializer
- JE32 %process_for_terminator ; And skip getting the expression
-
- ;; Deal with FOR (...; case
- CALL32 %expression ; Get the FOR ( ... ; part
-
-:process_for_terminator
- LOADI32_EAX &process_for_string_3 ; Using ":FOR_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_4 ; Using "ERROR in process_for\nMISSING ;1\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %expression ; Get the FOR ( ; ... ; Part
-
- LOADI32_EAX &process_for_string_5 ; Using "TEST\nJUMP_EQ %FOR_END_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_6 ; Using "JUMP %FOR_THEN_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_7 ; Using ":FOR_ITER_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_8 ; Using "ERROR in process_for\nMISSING ;2\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %expression ; Get the FOR (;;...) part
-
- LOADI32_EAX &process_for_string_9 ; Using "JUMP %FOR_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_10 ; Using ":FOR_THEN_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_11 ; Using "ERROR in process_for\nMISSING )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %statement ; Get FOR (;;) {...} part
-
- LOADI32_EAX &process_for_string_12 ; Using "JUMP %FOR_ITER_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Passing NUMBER_STRING
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- LOADI32_EAX &process_for_string_13 ; Using ":FOR_END_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string)
-
- CALL32 %restore_break_frame ; Restore the old break frame
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:process_for_string_0 "FOR_END_"
-:process_for_string_1 "# FOR_initialization_"
-:process_for_string_2 "ERROR in process_for
-MISSING (
-"
-:process_for_string_3 ":FOR_"
-:process_for_string_4 "ERROR in process_for
-MISSING ;1
-"
-:process_for_string_5 "TEST
-JUMP_EQ %FOR_END_"
-:process_for_string_6 "JUMP %FOR_THEN_"
-:process_for_string_7 ":FOR_ITER_"
-:process_for_string_8 "ERROR in process_for
-MISSING ;2
-"
-:process_for_string_9 "JUMP %FOR_"
-:process_for_string_10 ":FOR_THEN_"
-:process_for_string_11 "ERROR in process_for
-MISSING )
-"
-:process_for_string_12 "JUMP %FOR_ITER_"
-:process_for_string_13 ":FOR_END_"
-
-
-;; process_break function
-;; Receives nothing
-;; Returns nothing
-;; Handles the break out of loops case
-;; Uses EBX for struct token_list* break_frame and ECX for struct token_list* I
-:process_break
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax &break_target_head ; Catch big error
- CMPI8_EAX !0 ; IF(NULL == break_target_head)
- JE32 %process_break_bad ; I'm sorry Mr White but you have stage-3 lung cancer
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_ECX_from_EAX_Immediate8 !4 ; I = function->LOCALS
- LOAD32_Absolute32_ebx &break_frame ; Put break_frame in the right spot
- LOADI32_EAX &process_break_string_1 ; Using "POP_ebx\t# break_cleanup_locals\n"
-
-:process_break_iter
- CMPI8_ECX !0 ; IF (NULL == I)
- JE32 %process_break_cleaned ; We are done
-
- CMP_EBX_ECX ; IF I != break_frame
- JE32 %process_break_cleaned ; We are done
-
- CALL32 %emit_out ; Emit it
- LOAD32_ECX_from_ECX ; I = I->NEXT
- JMP32 %process_break_iter ; Keep looping
-
-:process_break_cleaned
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &process_break_string_2 ; Using "JUMP %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &break_target_head ; Get what we are in
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &break_target_func ; Get what function we are in
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &underline ; Using "_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &break_target_num ; Get dem digits
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &process_break_string_3 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &process_break_string_4 ; Using "ERROR in break statement\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:process_break_bad
- ;; Breaking badly
- LOADI32_EAX %2 ; Using standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
-; CALL32 %line_error ; Write useful debug info
- COPY_ECX_to_EAX ; put S in the right place
- CALL32 %File_Print ; print it
-
- LOADI32_EAX &process_break_string_0 ; Ending string
- CALL32 %File_Print ; print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:process_break_string_0 "Not inside of a loop or case statement"
-:process_break_string_1 "POP_ebx # break_cleanup_locals
-"
-:process_break_string_2 "JUMP %"
-:process_break_string_3 "
-"
-:process_break_string_4 "ERROR in break statement
-Missing ;
-"
-
-
-;; expression function
-;; Receives Nothing
-;; Returns Nothing
-;; Walks global_token and updates output_list
-;; Uses EAX and EBX for match and ECX for char* store
-:expression
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %bitwise_expr ; Collect bitwise expressions
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; "="
- CALL32 %match ; IF global_token->S == "="
- CMPI8_EAX !0 ; We have to deal with assignment
- JNE32 %expression_done ; Looks like nope
-
- ;; Deal with possible assignment
- LOADI32_ECX &expression_string_1 ; Assume "STORE_CHAR\n" by default
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !4 ; global_token->PREV
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->PREV->S
- LOADI32_EAX &close_bracket ; Using "]"
- CALL32 %match ; IF global_token->S == "]"
- CMPI8_EAX !0 ; Then we might have a char
- JNE32 %expression_int ; Otherwise INT
-
- LOAD32_Absolute32_ebx ¤t_target ; Using current_target
- LOAD32_EBX_from_EBX_Immediate8 !24 ; current_target->NAME
- LOADI32_EAX &type_char_indirect_name ; Using "char*"
- CALL32 %match ; Intensional inefficency because I feel like it
- CMPI8_EAX !0 ; IF current_target->NAME == "char*"
- JNE32 %expression_int ; Do char anyway
-
- JMP32 %expression_common ; Looks like we have to use "STORE_CHAR\n"
-
-:expression_int
- LOADI32_ECX &expression_string_0 ; Use "STORE_INTEGER\n"
-
-:expression_common
- LOADI32_EAX &expression ; Passing expression
- CALL32 %common_recursion ; Recurse
- COPY_ECX_to_EAX ; Using Store
- CALL32 %emit_out ; Emit it
- LOADI32_EAX %0 ; Using NULL
- STORE32_Absolute32_eax ¤t_target ; current_target = NULL
-
-:expression_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:expression_string_0 "STORE_INTEGER
-"
-:expression_string_1 "STORE_CHAR
-"
-
-
-;; bitwise_expr function
-;; Receives nothing
-;; Returns nothing
-;; Walks global_token list and updates output list
-;; Just calls other functions
-:bitwise_expr
- CALL32 %relational_expr ; Walk up the tree
- CALL32 %bitwise_expr_stub ; Let general recursion do the work
- RETURN
-
-
-;; bitwise_expr_stub function
-;; Receives nothing
-;; Returns Nothing
-;; Just calls general_recursion a bunch
-;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion
-:bitwise_expr_stub
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
-
- LOADI32_EAX &relational_expr ; Using relational_expr
- LOADI32_EBX &bitwise_expr_stub_string_0 ; Using "AND_eax_ebx\n"
- LOADI32_ECX &bitwise_and ; Using "&"
- LOADI32_EDX &bitwise_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &relational_expr ; Using relational_expr
- LOADI32_EBX &bitwise_expr_stub_string_0 ; Using "AND_eax_ebx\n"
- LOADI32_ECX &logical_and ; Using "&&"
- LOADI32_EDX &bitwise_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &relational_expr ; Using relational_expr
- LOADI32_EBX &bitwise_expr_stub_string_1 ; Using "OR_eax_ebx\n"
- LOADI32_ECX &bitwise_or ; Using "|"
- LOADI32_EDX &bitwise_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &relational_expr ; Using relational_expr
- LOADI32_EBX &bitwise_expr_stub_string_1 ; Using "OR_eax_ebx\n"
- LOADI32_ECX &logical_or ; Using "||"
- LOADI32_EDX &bitwise_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &relational_expr ; Using relational_expr
- LOADI32_EBX &bitwise_expr_stub_string_2 ; Using "XOR_ebx_eax_into_eax\n"
- LOADI32_ECX &bitwise_xor ; Using "^"
- LOADI32_EDX &bitwise_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:bitwise_expr_stub_string_0 "AND_eax_ebx
-"
-:bitwise_expr_stub_string_1 "OR_eax_ebx
-"
-:bitwise_expr_stub_string_2 "XOR_ebx_eax_into_eax
-"
-
-
-;; relational_expr function
-;; Receives nothing
-;; Returns Nothing
-;; Walks global_token list and updates output list
-;; just calls other function
-:relational_expr
- CALL32 %additive_expr ; Walk up the tree
- CALL32 %relational_expr_stub ; Recurse
- RETURN
-
-
-;; relational_expr_stub function
-;; Receives nothing
-;; Returns Nothing
-;; Just calls general_recursion a bunch
-;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion
-:relational_expr_stub
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_0 ; Using "CMP\nSETL\nMOVEZBL\n"
- LOADI32_ECX &less_than_string ; Using "<"
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_1 ; Using "CMP\nSETLE\nMOVEZBL\n"
- LOADI32_ECX &less_than_equal_string ; Using "<="
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_2 ; Using "CMP\nSETGE\nMOVEZBL\n"
- LOADI32_ECX &greater_than_equal_string ; Using ">="
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_3 ; Using "CMP\nSETG\nMOVEZBL\n"
- LOADI32_ECX &greater_than_string ; Using ">"
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_4 ; Using "CMP\nSETE\nMOVEZBL\n"
- LOADI32_ECX &equal_to_string ; Using "=="
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &additive_expr ; Using additive_expr
- LOADI32_EBX &relational_expr_stub_string_5 ; Using "CMP\nSETNE\nMOVEZBL\n"
- LOADI32_ECX ¬_equal_string ; Using "!="
- LOADI32_EDX &relational_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:relational_expr_stub_string_0 "CMP
-SETL
-MOVEZBL
-"
-:relational_expr_stub_string_1 "CMP
-SETLE
-MOVEZBL
-"
-:relational_expr_stub_string_2 "CMP
-SETGE
-MOVEZBL
-"
-:relational_expr_stub_string_3 "CMP
-SETG
-MOVEZBL
-"
-:relational_expr_stub_string_4 "CMP
-SETE
-MOVEZBL
-"
-:relational_expr_stub_string_5 "CMP
-SETNE
-MOVEZBL
-"
-
-
-;; additive_expr function
-;; Receives nothing
-;; Returns Nothing
-;; Walks global_token list and updates output list
-;; just calls other function
-:additive_expr
- CALL32 %postfix_expr ; Walk up the tree
- CALL32 %additive_expr_stub ; Recurse
- RETURN
-
-
-;; additive_expr_stub function
-;; Receives nothing
-;; Returns Nothing
-;; Just calls general_recursion a bunch
-;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion
-:additive_expr_stub
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_0 ; Using "ADD_ebx_to_eax\n"
- LOADI32_ECX &plus_string ; Using "+"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_1 ; Using "SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n"
- LOADI32_ECX &minus_string ; Using "-"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_2 ; Using "MULTIPLY_eax_by_ebx_into_eax\n"
- LOADI32_ECX &multiply_string ; Using "*"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_3 ; Using "XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nDIVIDE_eax_by_ebx_into_eax\n"
- LOADI32_ECX ÷_string ; Using "/"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_4 ; Using "XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nMODULUS_eax_from_ebx_into_ebx\nMOVE_edx_to_eax\n"
- LOADI32_ECX &modulus_string ; Using "%"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_5 ; Using "COPY_eax_to_ecx\nCOPY_ebx_to_eax\nSAL_eax_cl\n"
- LOADI32_ECX &left_shift_string ; Using "<<"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- LOADI32_EAX &postfix_expr ; Using postfix_expr
- LOADI32_EBX &additive_expr_stub_string_6 ; Using "COPY_eax_to_ecx\nCOPY_ebx_to_eax\nSAR_eax_cl\n"
- LOADI32_ECX &right_shift_string ; Using ">>"
- LOADI32_EDX &additive_expr_stub ; And recurse
- CALL32 %general_recursion ; Hit it
-
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:additive_expr_stub_string_0 "ADD_ebx_to_eax
-"
-:additive_expr_stub_string_1 "SUBTRACT_eax_from_ebx_into_ebx
-MOVE_ebx_to_eax
-"
-:additive_expr_stub_string_2 "MULTIPLY_eax_by_ebx_into_eax
-"
-:additive_expr_stub_string_3 "XCHG_eax_ebx
-LOAD_IMMEDIATE_edx %0
-DIVIDE_eax_by_ebx_into_eax
-"
-:additive_expr_stub_string_4 "XCHG_eax_ebx
-LOAD_IMMEDIATE_edx %0
-MODULUS_eax_from_ebx_into_ebx
-MOVE_edx_to_eax
-"
-:additive_expr_stub_string_5 "COPY_eax_to_ecx
-COPY_ebx_to_eax
-SAL_eax_cl
-"
-:additive_expr_stub_string_6 "COPY_eax_to_ecx
-COPY_ebx_to_eax
-SAR_eax_cl
-"
-
-
-;; postfix_expr function
-;; Receives nothing
-;; Returns Nothing
-;; Walks global_token list and updates output list
-;; just calls other function
-:postfix_expr
- CALL32 %primary_expr ; Walk up the tree
- CALL32 %postfix_expr_stub ; Recurse
- RETURN
-
-
-;; postfix_expr_stub function
-;; Receives nothing
-;; Returns Nothing
-;; Checks for "[" and "->" and deals with them otherwise does nothing
-;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion
-:postfix_expr_stub
- PUSH_EBX ; Protect EBX
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_bracket ; Using "["
- CALL32 %match ; IF global_token->S == "["
- CMPI8_EAX !0 ; then we have an array
- JNE32 %postfix_expr_stub_arrow ; Otherwise try arrow
-
- ;; Deal with array
- CALL32 %postfix_expr_array ; Get it
- CALL32 %postfix_expr_stub ; Recurse
-
-:postfix_expr_stub_arrow
- LOADI32_EAX &arrow_string ; Using "->"
- CALL32 %match ; IF global_token->S == "->"
- CMPI8_EAX !0 ; Then we need to deal with struct offsets
- JNE32 %postfix_expr_stub_done ; Otherwise be done
-
- ;; Deal with arrow
- CALL32 %postfix_expr_arrow ; Get it
- CALL32 %postfix_expr_stub ; Recurse
-
-:postfix_expr_stub_done
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; unary_expr_sizeof function
-;; Receives nothing
-;; Returns nothing
-;; Uses ECX for A->SIZE
-:unary_expr_sizeof
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &unary_expr_sizeof_string_0 ; Using "ERROR in unary_expr\nMissing (\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- CALL32 %type_name ; Get the type
- LOAD32_ECX_from_EAX_Immediate8 !4 ; Set A->TYPE
-
- LOADI32_EAX &unary_expr_sizeof_string_1 ; Using "ERROR in unary_expr\nMissing )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &unary_expr_sizeof_string_2 ; Using "LOAD_IMMEDIATE_eax %"
- CALL32 %emit_out ; Emit it
-
- COPY_ECX_to_EAX ; Put A->SIZE in the right place
- CALL32 %numerate_number ; Turn into string
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &unary_expr_sizeof_string_3 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:unary_expr_sizeof_string_0 "ERROR in unary_expr
-Missing (
-"
-:unary_expr_sizeof_string_1 "ERROR in unary_expr
-Missing )
-"
-:unary_expr_sizeof_string_2 "LOAD_IMMEDIATE_eax %"
-:unary_expr_sizeof_string_3 "
-"
-
-
-;; postfix_expr_array function
-;; Receives Nothing
-;; Returns Nothing
-;; Uses EBX for struct type* ARRAY and ECX for char* ASSIGN
-:postfix_expr_array
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax ¤t_target ; ARRAY = current_target
- PUSH_EAX ; Protect it
-
- LOADI32_EAX &expression ; Using expression
- CALL32 %common_recursion ; Recurse
-
- POP_EBX ; Restore array
- STORE32_Absolute32_ebx ¤t_target ; current_target = ARRAY
-
- LOADI32_ECX &postfix_expr_array_string_0 ; ASSIGN = "LOAD_INTEGER\n"
-
- LOADI32_EAX &type_char_indirect_name ; Using "char*"
- LOAD32_EBX_from_EBX_Immediate8 !24 ; current_target->NAME
- CALL32 %match ; IF current_target->NAME == "char*"
- CMPI8_EAX !0 ; load a byte
- JNE32 %postfix_expr_array_large ; Otherwise adjust
-
- ;; Deal with loading byte
- LOADI32_ECX &postfix_expr_array_string_1 ; ASSIGN = "LOAD_BYTE\n"
- JMP32 %postfix_expr_array_common ; Do the next bit
-
-:postfix_expr_array_large
- ;; deal with arrays made of things other than chars
- LOADI32_EAX &postfix_expr_array_string_2 ; Using "SAL_eax_Immediate8 !"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax ¤t_target ; Using current_target
- LOAD32_EAX_from_EAX_Immediate8 !12 ; current_target->INDIRECT
- LOAD32_EAX_from_EAX_Immediate8 !4 ; current_target->INDIRECT->SIZE
- CALL32 %ceil_log2 ; ceil_log2(current_target->indirect->size)
- CALL32 %numerate_number ; numerate_number(ceil_log2(current_target->indirect->size))
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &postfix_expr_array_string_3 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
-:postfix_expr_array_common
- LOADI32_EAX &postfix_expr_array_string_4 ; Using "ADD_ebx_to_eax\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &postfix_expr_array_string_5 ; Using "ERROR in postfix_expr\nMissing ]\n"
- LOADI32_EBX &close_bracket ; Using "]"
- CALL32 %require_match ; Make sure we have it
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; Using "="
- CALL32 %match ; IF global_token->S == "="
- CMPI8_EAX !0 ; We need to preserve address
- JNE32 %postfix_expr_array_done ; Otherwise be done
-
- ;; Clearing out assign
- LOADI32_ECX &postfix_expr_array_string_6 ; ASSIGN = ""
-
-:postfix_expr_array_done
- COPY_ECX_to_EAX ; Using ASSIGN
- CALL32 %emit_out ; Emit it
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:postfix_expr_array_string_0 "LOAD_INTEGER
-"
-:postfix_expr_array_string_1 "LOAD_BYTE
-"
-:postfix_expr_array_string_2 "SAL_eax_Immediate8 !"
-:postfix_expr_array_string_3 "
-"
-:postfix_expr_array_string_4 "ADD_ebx_to_eax
-"
-:postfix_expr_array_string_5 "ERROR in postfix_expr
-Missing ]
-"
-:postfix_expr_array_string_6 ""
-
-
-;; ceil_log2 function
-;; Receives int a in EAX
-;; Performs log2 on A and
-;; Returns result in EAX
-;; Uses EBX for INT A and ECX for INT RESULT
-:ceil_log2
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOADI32_ECX %0 ; RESULT = 0
-
- COPY_EAX_to_EBX ; put A in right place
- SUBI8_EAX !1 ; (A - 1)
- AND_EAX_EBX ; A & (A - 1)
- CMPI8_EAX !0 ; IF 0 == (A & (A - 1))
- JNE32 %ceil_log2_iter ; Starting from -1
-
- LOADI32_ECX %-1 ; RESULT = -1
-
-:ceil_log2_iter
- CMPI8_EBX !0 ; IF A > 0
- JLE32 %ceil_log2_done ; Otherwise be done
-
- ADDI8_ECX !1 ; RESULT = RESULT + 1
- SHRI8_EBX !1 ; A = A >> 1
- JMP32 %ceil_log2_iter ; Keep looping
-
-:ceil_log2_done
- COPY_ECX_to_EAX ; Return RESULT
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; postfix_expr_arrow function
-;; Receives nothing
-;; Returns nothing
-;; Emits a bunch and updates current_target
-;; Uses EBX for struct type* I
-:postfix_expr_arrow
- PUSH_EBX ; Protect EBX
- LOADI32_EAX &postfix_expr_arrow_string_0 ; Using "# looking up offset\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOAD32_EBX_from_EAX_Immediate8 !8 ; Using global_token->S
- LOAD32_Absolute32_eax ¤t_target ; Using current_target
- CALL32 %lookup_member ; lookup_member(current_target, global_token->s)
- COPY_EAX_to_EBX ; struct type* I = lookup_member(current_target, global_token->s)
-
- LOAD32_EAX_from_EAX_Immediate8 !20 ; I->TYPE
- STORE32_Absolute32_eax ¤t_target ; current_target = I->TYPE
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOAD32_EAX_from_EBX_Immediate8 !8 ; I->OFFSET
- CMPI8_EAX !0 ; IF 0 != I->OFFSET
- JE32 %postfix_expr_arrow_first ; Then we don't need to do an offset
-
- ;; Deal with needing an offset
- LOADI32_EAX &postfix_expr_arrow_string_1 ; Using "# -> offset calculation\nLOAD_IMMEDIATE_ebx %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_EAX_from_EBX_Immediate8 !8 ; I->OFFSET
- CALL32 %numerate_number ; Convert to string
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &postfix_expr_arrow_string_2 ; Using "\nADD_ebx_to_eax\n"
- CALL32 %emit_out ; Emit it
-
-:postfix_expr_arrow_first
- LOAD32_EAX_from_EBX_Immediate8 !4 ; I->SIZE
- CMPI8_EAX !4 ; IF I->SIZE >= 4
- JL32 %postfix_expr_arrow_done ; Otherwise be done
-
- ;; Last chance for load
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; Using "="
- CALL32 %match ; IF global_token->S == "="
- CMPI8_EAX !0 ; Then we have assignment and should not load
- JE32 %postfix_expr_arrow_done ; Be done
-
- ;; Deal with load case
- LOADI32_EAX &postfix_expr_arrow_string_3 ; Using "LOAD_INTEGER\n"
- CALL32 %emit_out ; Emit it
-
-:postfix_expr_arrow_done
- POP_EBX ; Restore EBX
- RETURN
-
-:postfix_expr_arrow_string_0 "# looking up offset
-"
-:postfix_expr_arrow_string_1 "# -> offset calculation
-LOAD_IMMEDIATE_ebx %"
-:postfix_expr_arrow_string_2 "
-ADD_ebx_to_eax
-"
-:postfix_expr_arrow_string_3 "LOAD_INTEGER
-"
-
-
-;; primary_expr function
-;; Receives nothing
-;; Returns nothing
-:primary_expr
- PUSH_EBX ; Protect EBX
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &sizeof_string ; Using "sizeof"
- CALL32 %match ; See if match
- CMPI8_EAX !0 ; IF match
- JNE32 %primary_expr_neg ; Otherwise try negatives
-
- ;; Deal with sizeof
- CALL32 %unary_expr_sizeof ; Lets do this
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_neg
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !45 ; IF global_token->S[0] == "-"
- JNE32 %primary_expr_not ; Otherwise try logical NOT
-
- ;; Deal with negative numbers
- LOADI32_EAX &primary_expr_string_0 ; Using "LOAD_IMMEDIATE_eax %0\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &postfix_expr ; Passing postfix_expr
- CALL32 %common_recursion ; Get what it is notting
-
- LOADI32_EAX &primary_expr_string_1 ; Using "SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n"
- CALL32 %emit_out ; Emit it
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_not
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !33 ; IF global_token->S[0] == "!"
- JNE32 %primary_expr_bin ; Otherwise try '~'
-
- ;; Deal with logical not
- LOADI32_EAX &primary_expr_string_2 ; Using "LOAD_IMMEDIATE_eax %1\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &postfix_expr ; Passing postfix_expr
- CALL32 %common_recursion ; Get what it is notting
-
- LOADI32_EAX &primary_expr_string_3 ; Using "XOR_ebx_eax_into_eax\n"
- CALL32 %emit_out ; Emit it
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_bin
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !126 ; IF global_token->S[0] == "~"
- JNE32 %primary_expr_paren ; Otherwise try paren
-
- ;; Deal with binary NOT
- LOADI32_EAX &postfix_expr ; Passing postfix_expr
- CALL32 %common_recursion ; Get what it is notting
- LOADI32_EAX &primary_expr_string_4 ; Using "NOT_eax\n"
- CALL32 %emit_out ; Emit it
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_paren
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !40 ; IF global_token->S[0] == "("
- JNE32 %primary_expr_ch ; Otherwise try char
-
- ;; deal with nesting
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
- CALL32 %expression ; Lets recurse
- LOADI32_EAX &primary_expr_string_5 ; Using "Error in Primary expression\nDidn't get )\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_ch
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !39 ; Using "'"
- JNE32 %primary_expr_str ; Otherwise try string
-
- ;; Deal with chars
- CALL32 %primary_expr_char ; Handle that char
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_str
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !34 ; Using '\"'
- JNE32 %primary_expr_var ; Otherwise try a variable
-
- ;; Deal with strings
- CALL32 %primary_expr_string ; Handle that string
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_var
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- LOADI32_EBX &primary_expr_string_6 ; Using "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
- CALL32 %In_Set ; See if we have a match
- CMPI8_EAX !1 ; IF match
- JNE32 %primary_expr_num ; otherwise try number
-
- ;; Deal with variables
- CALL32 %primary_expr_variable ; Deal with variable
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_num
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- LOADI32_EBX &primary_expr_string_7 ; Using "0123456789"
- CALL32 %In_Set ; See if we have a match
- CMPI8_EAX !1 ; IF match
- JNE32 %primary_expr_fail ; otherwise we failed hard
-
- ;; Deal with numbers
- CALL32 %primary_expr_number ; Collect the number
- JMP32 %primary_expr_done ; Be done
-
-:primary_expr_fail
- ;; looks like we hit bad input
- ;; abort before it gets bad
- CALL32 %primary_expr_failure ; No match means failure
-:primary_expr_done
- POP_EBX ; Restore EBX
- RETURN
-
-:primary_expr_string_0 "LOAD_IMMEDIATE_eax %0
-"
-:primary_expr_string_1 "SUBTRACT_eax_from_ebx_into_ebx
-MOVE_ebx_to_eax
-"
-:primary_expr_string_2 "LOAD_IMMEDIATE_eax %1
-"
-:primary_expr_string_3 "XOR_ebx_eax_into_eax
-"
-:primary_expr_string_4 "NOT_eax
-"
-:primary_expr_string_5 "Error in Primary expression
-Didn't get )
-"
-:primary_expr_string_6 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
-:primary_expr_string_7 "0123456789"
-
-
-;; primary_expr_variable function
-;; Receives nothing
-;; Returns nothing
-;; Walks global and updates output
-;; Uses EAX for struct token_list* a and ECX for char* S
-:primary_expr_variable
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_ECX_from_EAX_Immediate8 !8 ; S = global_token->S
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- COPY_ECX_to_EAX ; Using S
- LOAD32_Absolute32_ebx &global_constant_list ; Using global_constant_list
- CALL32 %sym_lookup ; sym_lookup(s, global_constant_list)
- CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list)
- JE32 %primary_expr_variable_local ; Try locals next
-
- ;; Deal with constant load
- LOAD32_EBX_from_EAX_Immediate8 !16 ; a->ARGS
- LOADI32_EAX &primary_expr_variable_string_2 ; Using "LOAD_IMMEDIATE_eax %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_EAX_from_EBX_Immediate8 !8 ; a->ARGS->S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &primary_expr_variable_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
- JMP32 %primary_expr_variable_done ; Be done
-
-:primary_expr_variable_local
- COPY_ECX_to_EAX ; Using S
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EBX_from_EBX_Immediate8 !4 ; function->locals
- CALL32 %sym_lookup ; sym_lookup(s, function->locals)
- CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list)
- JE32 %primary_expr_variable_arguments ; try arguments next
-
- ;; Deal with local load
- CALL32 %variable_load ; Collect it
- JMP32 %primary_expr_variable_done ; Be done
-
-:primary_expr_variable_arguments
- COPY_ECX_to_EAX ; Using S
- LOAD32_Absolute32_ebx &function ; Using function
- LOAD32_EBX_from_EBX_Immediate8 !16 ; function->args
- CALL32 %sym_lookup ; sym_lookup(s, function->args)
- CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list)
- JE32 %primary_expr_variable_function ; try functions next
-
- ;; Deal with argument load
- CALL32 %variable_load ; Collect it
- JMP32 %primary_expr_variable_done ; Be done
-
-:primary_expr_variable_function
- COPY_ECX_to_EAX ; Using S
- LOAD32_Absolute32_ebx &global_function_list ; Using global_function_list
- CALL32 %sym_lookup ; sym_lookup(s, global_function_list)
- CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_function_list)
- JE32 %primary_expr_variable_global ; try globals next
-
- ;; Deal with functions
- CALL32 %function_load ; Deal with the function
- JMP32 %primary_expr_variable_done ; Be done
-
-:primary_expr_variable_global
- COPY_ECX_to_EAX ; Using S
- LOAD32_Absolute32_ebx &global_symbol_list ; Using global_symbol_list
- CALL32 %sym_lookup ; sym_lookup(s, global_symbol_list)
- CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_symbol_list)
- JE32 %primary_expr_variable_error ; Give up
-
- ;; Deal with globals
- CALL32 %global_load ; Collect that global
- JMP32 %primary_expr_variable_done ; Be done
-
-:primary_expr_variable_error
- LOADI32_EAX %2 ; Using standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
-; CALL32 %line_error ; Write useful debug info
- COPY_ECX_to_EAX ; put S in the right place
- CALL32 %File_Print ; print it
-
- LOADI32_EAX &primary_expr_variable_string_0 ; Ending string
- CALL32 %File_Print ; print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:primary_expr_variable_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:primary_expr_variable_string_0 " is not a defined symbol
-"
-:primary_expr_variable_string_1 "
-"
-:primary_expr_variable_string_2 "LOAD_IMMEDIATE_eax %"
-
-
-;; function_call function
-;; Receives char* S in EAX and int BOOL in EBX
-;; Builds stack frames before and tears them down after function calls
-;; Uses ECX for char* S, EDX for int BOOL, ESI for PASSED
-:function_call
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_ESI ; Protect ESI
- COPY_EAX_to_ECX ; Put S in place
- COPY_EBX_to_EDX ; Put BOOL in place
- LOADI32_ESI %0 ; PASSED = 0
-
- LOADI32_EAX &function_call_string_0 ; Using "ERROR in process_expression_list\nNo ( was found\n"
- LOADI32_EBX &open_paren ; Using "("
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_EAX &function_call_string_1 ; Using "PUSH_edi\t# Prevent overwriting in recursion\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_2 ; Using "PUSH_ebp\t# Protect the old base pointer\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_3 ; Using "COPY_esp_to_edi\t# Copy new base pointer\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !41 ; IF global_token->S[0] == ")"
- JE32 %function_call_gen_done ; Then no arguments to send
-
- ;; looks like we have arguments to collect
- CALL32 %expression ; Collect the argument
-
- LOADI32_EAX &function_call_string_4 ; Using "PUSH_eax\t#_process_expression1\n"
- CALL32 %emit_out ; Emit it
- LOADI32_ESI %1 ; PASSED = 1
-
-:function_call_gen_iter
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !44 ; IF global_token->S[0] == ","
- JNE32 %function_call_gen_done ; Otherwise we are done
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- CALL32 %expression ; Collect the argument
-
- LOADI32_EAX &function_call_string_5 ; Using "PUSH_eax\t#_process_expression2\n"
- CALL32 %emit_out ; Emit it
- ADDI8_ESI !1 ; PASSED = PASSED + 1
- JMP32 %function_call_gen_iter ; Keep trying
-
-:function_call_gen_done
- ;; All is collected
- LOADI32_EAX &function_call_string_6 ; Using "ERROR in process_expression_list\nNo ) was found\n"
- LOADI32_EBX &close_paren ; Using ")"
- CALL32 %require_match ; Make sure we have it
-
- CMPI8_EDX !0 ; IF(BOOL == TRUE)
- JNE32 %function_call_static ; Otherwise it is a static call
-
- ;; Deal with a passed function pointer
- LOADI32_EAX &function_call_string_7 ; Using "LOAD_BASE_ADDRESS_eax %"
- CALL32 %emit_out ; Emit it
-
- COPY_ECX_to_EAX ; Using S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_8 ; Using "\nLOAD_INTEGER\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_9 ; Using "COPY_edi_to_ebp\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_10 ; Using "CALL_eax\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_13 ; Using "POP_ebx\t# _process_expression_locals\n"
- JMP32 %function_call_cleanup ; Clean up
-
-:function_call_static
- ;; Deal with fixed function name
- LOADI32_EAX &function_call_string_9 ; Using "COPY_edi_to_ebp\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_11 ; Using "CALL_IMMEDIATE %FUNCTION_"
- CALL32 %emit_out ; Emit it
-
- COPY_ECX_to_EAX ; Using S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_12 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_13 ; Using "POP_ebx\t# _process_expression_locals\n"
-
-:function_call_cleanup
- CMPI8_ESI !0 ; IF PASSED > 0
- JLE32 %function_call_done ; Otherwise be done
-
- ;; The desired string is already in EAX
- CALL32 %emit_out ; Emit it
-
- SUBI8_ESI !1 ; PASSED = PASSED - 1
- JMP32 %function_call_cleanup ; Keep going
-
-:function_call_done
- LOADI32_EAX &function_call_string_14 ; Using "POP_ebp\t# Restore old base pointer\n"
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_call_string_15 ; Using "POP_edi\t# Prevent overwrite\n"
- CALL32 %emit_out ; Emit it
-
- POP_ESI ; Restore ESI
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:function_call_string_0 "ERROR in process_expression_list
-No ( was found
-"
-:function_call_string_1 "PUSH_edi # Prevent overwriting in recursion
-"
-:function_call_string_2 "PUSH_ebp # Protect the old base pointer
-"
-:function_call_string_3 "COPY_esp_to_edi # Copy new base pointer
-"
-:function_call_string_4 "PUSH_eax #_process_expression1
-"
-:function_call_string_5 "PUSH_eax #_process_expression2
-"
-:function_call_string_6 "ERROR in process_expression_list
-No ) was found
-"
-:function_call_string_7 "LOAD_BASE_ADDRESS_eax %"
-:function_call_string_8 "
-LOAD_INTEGER
-"
-:function_call_string_9 "COPY_edi_to_ebp
-"
-:function_call_string_10 "CALL_eax
-"
-:function_call_string_11 "CALL_IMMEDIATE %FUNCTION_"
-:function_call_string_12 "
-"
-:function_call_string_13 "POP_ebx # _process_expression_locals
-"
-:function_call_string_14 "POP_ebp # Restore old base pointer
-"
-:function_call_string_15 "POP_edi # Prevent overwrite
-"
-
-
-;; variable_load function
-;; Receives struct token_list* A in EAX
-;; Returns nothing
-;; Updates output and current_target
-;; Uses ECX for A
-:variable_load
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; Protect A
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_paren ; Using "("
- CALL32 %match ; IF global_token->S == "("
- CMPI8_EAX !0 ; Then it might be a function
- JNE32 %variable_load_regular ; Otherwise it is regular
-
- LOAD32_EBX_from_ECX_Immediate8 !12 ; A->TYPE
- LOAD32_EBX_from_EBX_Immediate8 !24 ; A->TYPE->NAME
- LOADI32_EAX &type_function_name ; Using "FUNCTION"
- CALL32 %match ; IF A->TYPE->NAME == "FUNCTION"
- CMPI8_EAX !0 ; Then it must be a function
- JNE32 %variable_load_regular ; otherwise just another regular
-
- ;; deal with function
- LOAD32_EAX_from_ECX_Immediate8 !16 ; A->DEPTH
- CALL32 %numerate_number ; Convert to string
- LOADI32_EBX %0 ; pass 0 for true
- CALL32 %function_call ; Create the function call
- JMP32 %variable_load_done ; Be done
-
-:variable_load_regular
- LOAD32_EAX_from_ECX_Immediate8 !12 ; A->TYPE
- STORE32_Absolute32_eax ¤t_target ; current_target = A->TYPE
-
- LOADI32_EAX &variable_load_string_0 ; Using "LOAD_BASE_ADDRESS_eax %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_EAX_from_ECX_Immediate8 !16 ; A->DEPTH
- CALL32 %numerate_number ; Convert to string
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &variable_load_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- ;; Check for special case of assignment
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; Using "="
- CALL32 %match ; IF global_token->S == "="
- CMPI8_EAX !0 ; Then we skip loading
- JE32 %variable_load_done ; And be done
-
- ;; Deal with common case
- LOADI32_EAX &variable_load_string_2 ; Using "LOAD_INTEGER\n"
- CALL32 %emit_out ; Emit it
-
-:variable_load_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:variable_load_string_0 "LOAD_BASE_ADDRESS_eax %"
-:variable_load_string_1 "
-"
-:variable_load_string_2 "LOAD_INTEGER
-"
-
-
-;; function_load function
-;; Receives struct token_list* a in EAX
-;; Returns nothing
-;; Uses ECX to hold A->S
-:function_load
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_EAX_from_EAX_Immediate8 !8 ; A->S
- COPY_EAX_to_ECX ; Protect A->S
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_paren ; Using "("
- CALL32 %match ; IF global_token->S == "("
- CMPI8_EAX !0 ; The we need to do a function call
- JNE32 %function_load_regular ; Otherwise just load it's address
-
- ;; Deal with function call
- COPY_ECX_to_EAX ; Using A->S
- LOADI32_EBX %1 ; Using FALSE
- CALL32 %function_call ; Deal with it
- JMP32 %function_load_done ; Be done
-
-:function_load_regular
- LOADI32_EAX &function_load_string_0 ; Using "LOAD_IMMEDIATE_eax &FUNCTION_"
- CALL32 %emit_out ; Emit it
-
- COPY_ECX_to_EAX ; Using A->S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &function_load_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
-:function_load_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:function_load_string_0 "LOAD_IMMEDIATE_eax &FUNCTION_"
-:function_load_string_1 "
-"
-
-
-;; global_load function
-;; Receives struct token_list* A in EAX
-;; Returns nothing
-;; Uses EBX to hold A->S
-:global_load
- PUSH_EBX ; Protect EBX
- COPY_EAX_to_EBX ; Set as A
- LOAD32_EBX_from_EBX_Immediate8 !8 ; Set as A->S
-
- LOAD32_EAX_from_EAX_Immediate8 !12 ; A->TYPE
- STORE32_Absolute32_eax ¤t_target ; current_target = A->TYPE
-
- LOADI32_EAX &global_load_string_0 ; Using "LOAD_IMMEDIATE_eax &GLOBAL_"
- CALL32 %emit_out ; Emit it
-
- COPY_EBX_to_EAX ; Using A->S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &global_load_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &equal ; "="
- CALL32 %match ; IF global_token->S == "="
- CMPI8_EAX !0 ; We need to skip for assignment
- JE32 %global_load_done ; and be done
-
- ;; Otherwise we are loading the contents
- LOADI32_EAX &global_load_string_2 ; Using "LOAD_INTEGER\n"
- CALL32 %emit_out ; Emit it
-
-:global_load_done
- POP_EBX ; Restore EBX
- RETURN
-
-:global_load_string_0 "LOAD_IMMEDIATE_eax &GLOBAL_"
-:global_load_string_1 "
-"
-:global_load_string_2 "LOAD_INTEGER
-"
-
-
-;; sym_lookup function
-;; Receives char* S in EAX and struct token_list* symbol_list in EBX
-;; Uses I->S in EAX, S in EBX and I in ECX
-;; Returns match or NULL
-:sym_lookup
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EBX_to_ECX ; I = symbol_list
- COPY_EAX_to_EBX ; Put S in the right place
-:sym_lookup_iter
- CMPI8_ECX !0 ; IF NULL == I
- JE32 %sym_lookup_done ; We failed to find match
-
- LOAD32_EAX_from_ECX_Immediate8 !8 ; Using I->S
- CALL32 %match ; IF I->S == S
- CMPI8_EAX !0 ; then be done
- JE32 %sym_lookup_done ; Failed
-
- LOAD32_ECX_from_ECX ; I = I->NEXT
- JMP32 %sym_lookup_iter ; otherwise keep looping
-
-:sym_lookup_done
- COPY_ECX_to_EAX ; Return I
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; primary_expr_number function
-;; Receives nothing
-;; Returns nothing
-;; Simply uses current global token to update output and then steps to next global_token
-:primary_expr_number
- LOADI32_EAX &primary_expr_number_string_0 ; Using "LOAD_IMMEDIATE_eax %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %emit_out ; Emit it
-
- LOADI32_EAX &primary_expr_number_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
- RETURN
-
-:primary_expr_number_string_0 "LOAD_IMMEDIATE_eax %"
-:primary_expr_number_string_1 "
-"
-
-
-;; primary_expr_string function
-;; receives nothing
-;; Returns nothing
-;; creates entries for string and calls to generate string output
-;; uses ECX for char* number_string
-:primary_expr_string
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_ebx ¤t_count ; Using current_count
- COPY_EBX_to_EAX ; And putting it in the right place
- CALL32 %numerate_number ; Get the string
- COPY_EAX_to_ECX ; protect number_string
-
- ADDI8_EBX !1 ; current_count + 1
- STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1
-
- LOADI32_EAX &primary_expr_string_string_0 ; Using "LOAD_IMMEDIATE_eax &STRING_"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- COPY_ECX_to_EBX ; Put number_string in the right place
- CALL32 %uniqueID_out ; Make it unique
-
- ;; Generate the target
- LOADI32_EAX &primary_expr_string_string_1 ; Using ":STRING_"
- LOAD32_Absolute32_ebx &strings_list ; Using strings_list
- CALL32 %emit ; Emit it
- COPY_EAX_to_EBX ; put new strings_list in place
-
- LOAD32_Absolute32_eax &function ; Using function
- LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S
- CALL32 %uniqueID ; Make it unique
- COPY_EAX_to_EBX ; put new strings_list in place
-
- ;; Parse the string
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %parse_string ; convert to useful form
- CALL32 %emit ; Emit it
- STORE32_Absolute32_eax &strings_list ; Update Strings _list
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:primary_expr_string_string_0 "LOAD_IMMEDIATE_eax &STRING_"
-:primary_expr_string_string_1 ":STRING_"
-
-
-;; primary_expr_char function
-;; Receives nothing
-;; Returns nothing
-;; Updates output_list using global_token
-:primary_expr_char
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOADI32_EAX &primary_expr_char_string_0 ; Using "LOAD_IMMEDIATE_eax %"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- ADDI8_EAX !1 ; global_token->S + 1
- CALL32 %escape_lookup ; Get the char
- CALL32 %numerate_number ; Convert to string
- CALL32 %emit_out ; emit it
-
- LOADI32_EAX &primary_expr_char_string_1 ; Using "\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:primary_expr_char_string_0 "LOAD_IMMEDIATE_eax %"
-:primary_expr_char_string_1 "
-"
-
-
-;; primary_expr_failure function
-;; Receives nothing
-;; Does not return but aborts hard
-;; Complains about the bad input
-:primary_expr_failure
-; CALL32 %line_error ; Get line of issue
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- LOADI32_EAX &primary_expr_failure_string_0 ; Using "Received "
- CALL32 %File_Print ; Print it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %File_Print ; Print it
-
- LOADI32_EAX &primary_expr_failure_string_1 ; Using " in primary_expr\n"
- CALL32 %File_Print ; Print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:primary_expr_failure_string_0 "Received "
-:primary_expr_failure_string_1 " in primary_expr
-"
-
-
-;; general_recursion function
-;; Receives FUNCTION F in EAX, char* S in EBX, char* name in ECX and FUNCTION iterate in EDX
-;; Returns nothing
-;; Uses ECX for char* S, EDX for FUNCTION iterate and EBP for FUNCTION F
-;; But generally recurses a shitload
-:general_recursion
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_EBP ; Protect EBP
- COPY_EAX_to_EBP ; Protect F
- COPY_ECX_to_EAX ; Put name in the right place
- COPY_EBX_to_ECX ; Protect S
-
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- CALL32 %match ; IF match(name, global_token->s)
- CMPI8_EAX !0 ; If true we do
- JNE32 %general_recursion_done ; Otherwise skip it
-
- ;; Deal with the recursion
- COPY_EBP_to_EAX ; Put F in the right place
- CALL32 %common_recursion ; Recurse
-
- COPY_ECX_to_EAX ; Put S in the right place
- CALL32 %emit_out ; Emit it
-
- COPY_EDX_to_EAX ; Put iterate in the right place
- CALL_EAX ; Down the rabbit hole
-
-:general_recursion_done
- POP_EBP ; Restore EBP
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; promote_type function
-;; Receives struct type* a in EAX and struct type* b in EBX
-;; Returns the most recent type in EAX
-;; Uses EAX for struct type* I, ECX for struct type* A and EDX for struct type* B
-:promote_type
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- CMPI8_EBX !0 ; IF NULL == A
- JE32 %promote_type_done ; Just return A
-
- COPY_EAX_to_ECX ; Put A in place
- COPY_EBX_to_EDX ; Put B in place
- COPY_EBX_to_EAX ; IF NULL == A
- CMPI8_ECX !0 ; Then we just return B
- JE32 %promote_type_done ; Be done
-
- ;; Looks like we need to walk the list
- LOAD32_ECX_from_ECX_Immediate8 !24 ; A->NAME
- LOAD32_EDX_from_EDX_Immediate8 !24 ; B->NAME
- LOAD32_Absolute32_eax &global_types ; I = global_types
-:promote_type_iter
- CMPI8_EAX !0 ; IF NULL == I
- JE32 %promote_type_done ; Just be done
-
- LOAD32_EBX_from_EAX_Immediate8 !24 ; I->NAME
- CMP_ECX_EBX ; IF(A->NAME == I->NAME)
- JE32 %promote_type_done ; Be done
-
- CMP_EBX_EDX ; IF(B->NAME == I->NAME)
- JE32 %promote_type_done ; Be done
-
- LOAD32_EBX_from_EAX_Immediate8 !12 ; I->INDIRECT
- LOAD32_EBX_from_EBX_Immediate8 !24 ; I->INDIRECT->NAME
-
- CMP_ECX_EBX ; IF(A->NAME == I->INDIRECT->NAME)
- JE32 %promote_type_done ; Be done
-
- CMP_EBX_EDX ; IF(B->NAME == I->INDIRECT->NAME)
- JE32 %promote_type_done ; Be done
-
- LOAD32_EAX_from_EAX ; I = I->NEXT
- JMP32 %promote_type_iter ; Keep going
-
-:promote_type_done
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; common_recursion function
-;; Receives FUNCTION F in EAX
-;; Returns Nothing
-;; Walks global_token list and update output_list
-;; Updates current_target
-;; Uses EBX to hold FUNCTION F and struct type* last_type
-:common_recursion
- PUSH_EBX ; Protect EBX
- COPY_EAX_to_EBX ; Put FUNCTION F safely out of the way
- LOADI32_EAX &common_recursion_string_0 ; Using "PUSH_eax\t#_common_recursion\n"
- CALL32 %emit_out ; Emit it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- COPY_EBX_to_EAX ; Prepare for function call
- LOAD32_Absolute32_ebx ¤t_target ; Get last type
- CALL_EAX ; F();
- LOAD32_Absolute32_eax ¤t_target ; Get current_target
- CALL32 %promote_type ; get the right type
- STORE32_Absolute32_eax ¤t_target ; Set new current_target
-
- LOADI32_EAX &common_recursion_string_1 ; Using "POP_ebx\t# _common_recursion\n"
- CALL32 %emit_out ; Emit it
- POP_EBX ; Restore EBX
- RETURN
-
-:common_recursion_string_0 "PUSH_eax #_common_recursion
-"
-:common_recursion_string_1 "POP_ebx # _common_recursion
-"
-
-
-;; require_match function
-;; Receives char* message in EAX and char* required in EBX
-;; Returns nothing
-;; Uses ECX to hold message and updates global_token
-:require_match
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; put the message somewhere safe
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %match ; IF required == global_token->S
- CMPI8_EAX !0 ; we are fine
- JE32 %require_match_good ; otherwise pain
-
- ;; Deal will bad times
-; CALL32 %line_error ; Tell user what went wrong
- LOADI32_EAX %2 ; Using standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- COPY_ECX_to_EAX ; using our message
- CALL32 %File_Print ; Print it
- JMP32 %Exit_Failure ; Abort HARD
-
-:require_match_good
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->next
- STORE32_Absolute32_eax &global_token ; global_token = global_token->next
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; uniqueID Function
-;; Receives char*S in EAX, struct token_list* l in EBX snd char* num in ECX
-;; Returns updated struct token_list* L in EAX
-:uniqueID
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- CALL32 %emit ; emit(s, l)
- COPY_EAX_to_EBX ; Put L in correct place
- LOADI32_EAX &underline ; Usinf "_"
- CALL32 %emit ; emit("_", l)
- COPY_EAX_to_EBX ; Put L in correct place
- COPY_ECX_to_EAX ; Put num in correct place
- CALL32 %emit ; emit(num, l)
- COPY_EAX_to_EBX ; Put L in correct place
- LOADI32_EAX &uniqueID_string_0 ; Using "\n"
- CALL32 %emit ; emit("\n", l)
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:uniqueID_string_0 "
-"
-
-
-;; uniqueID_out function
-;; Receives char* S in EAX and char* num in EBX
-;; Returns nothing
-:uniqueID_out
- PUSH_EAX ; Protect EAX
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EBX_to_ECX ; Put num in right spot
- LOAD32_Absolute32_ebx &output_list ; Using output_list
- CALL32 %uniqueID ; Get updated list
- STORE32_Absolute32_eax &output_list ; output_list = uniqueID(s, output_list, num)
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- POP_EAX ; Restore EAX
- RETURN
-
-
-;; emit_out function
-;; Receives char* S in EAX
-;; Returns nothing
-;; Updates output_list
-;; MUST NOT ALTER REGISTERS
-:emit_out
- PUSH_EAX ; Protect EAX
- PUSH_EBX ; Protect EBX
- LOAD32_Absolute32_ebx &output_list ; Using output_list
- CALL32 %emit ; emit it
- STORE32_Absolute32_eax &output_list ; update it
- POP_EBX ; Restore EBX
- POP_EAX ; Restore EAX
- RETURN
-
-
-;; emit function
-;; Receives char *s in EAX and struct token_list* head in EBX
-;; Returns struct token_list* T in EAX
-:emit
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; put S out of the way
- LOADI32_EAX %20 ; sizeof(struct token_list)
- CALL32 %malloc ; get T
- STORE32_EBX_into_EAX ; t->next = head;
- STORE32_ECX_into_EAX_Immediate8 !8 ; t->s = s;
- POP_ECX ; Restore ECX
- RETURN
-
-
-;; escape_lookup function
-;; Receives char* c in EAX
-;; Returns integer value of char in EAX
-;; Aborts hard if unknown escape is received
-;; Uses ECX to hold char* C
-:escape_lookup
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; Put char* C in safe place
- LOAD8_al_from_ECX ; Load c[0]
- MOVZX_al ; make it useful
- CMPI8_EAX !92 ; If '\\' != c[0]
- JNE32 %escape_lookup_done ; Be done
-
- COPY_ECX_to_EBX ; Prepare for walk
- ADDI8_EBX !1 ; increment
- LOAD8_bl_from_EBX ; load c[1]
- MOVZX_bl ; make it useful
-
- CMPI8_EBX !120 ; Check if \x??
- JE32 %escape_lookup_hex ; Deal with hex
-
- ;; Deal with \? escapes
- LOADI32_EAX %10 ; Guess "\n"
- CMPI8_EBX !110 ; If n
- JE32 %escape_lookup_done ; Be done
-
- LOADI32_EAX %9 ; Guess "\t"
- CMPI8_EBX !116 ; If t
- JE32 %escape_lookup_done ; Be done
-
- COPY_EBX_to_EAX ; "\\", "'" and '\"' all encode as themselves
- CMPI8_EBX !92 ; If "\\"
- JE32 %escape_lookup_done ; Be done
- CMPI8_EBX !39 ; IF "'"
- JE32 %escape_lookup_done ; Be done
- CMPI8_EBX !34 ; IF '\"'
- JE32 %escape_lookup_done ; Be done
-
- LOADI32_EAX %13 ; Guess "\r"
- CMPI8_EBX !114 ; IF r
- JE32 %escape_lookup_done ; Be done
-
- ;; Looks like we have no clue what we are doing
- ;; Aborting hard
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- LOADI32_EAX &escape_lookup_string_0 ; Using "Unknown escape received: "
- CALL32 %File_Print ; Print it
- COPY_ECX_to_EAX ; Using C
- CALL32 %File_Print ; Print it
- LOADI32_EAX &escape_lookup_string_1 ; Using " Unable to process\n"
- CALL32 %File_Print ; Print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:escape_lookup_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:escape_lookup_hex
- ;; Give up on C and just assume they know what they are doing
- ADDI8_ECX !2 ; increment
- LOAD8_al_from_ECX ; c[2]
- MOVZX_al ; make it useful
- ADDI8_ECX !1 ; increment
- CALL32 %char2hex ; Get the hex value
- SALI8_EAX !4 ; c << 4
- LOAD8_bl_from_ECX ; c[3]
- MOVZX_bl ; make it useful
- SWAP_EAX_EBX ; protect c << 4
- CALL32 %char2hex ; Get the hex value
- ADD_ebx_into_eax ; hex(c[2]) << 4 + hex(c[3])
- JMP32 %escape_lookup_done ; Be done
-
-:escape_lookup_string_0 "Unknown escape received: "
-:escape_lookup_string_1 " Unable to process
-"
-
-
-;; char2hex function
-;; Receives char in EAX
-;; Returns hex or aborts hard
-:char2hex
- SUBI8_EAX !48 ; Try 0-9
- CMPI8_EAX !10 ; Otherwise fun times
- JL32 %char2hex_done ; Be done
-
- ;; Deal with A-F
- ANDI32_EAX %0xDF ; Unset High bit turning a-f into A-F
- SUBI8_EAX !7 ; Shift down into position
- CMPI8_EAX !10 ; Everything below A is bad
- JL32 %char2hex_fail ; And should fail
- CMPI8_EAX !16 ; Make sure we are below F
- JL32 %char2hex_done ; If so be done
-
-:char2hex_fail
- ;; Time to fail hard
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- LOADI32_EAX &char2hex_string_0 ; Using "Tried to print non-hex number\n"
- CALL32 %File_Print ; Print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:char2hex_done
- RETURN
-
-:char2hex_string_0 "Tried to print non-hex number
-"
-
-
-;; parse_string function
-;; Receives char* string in EAX
-;; Returns cleaned up string
-;; Protects char* string in EBX
-:parse_string
- PUSH_EBX ; Protect EBX
- COPY_EAX_to_EBX ; Protect char* string
- CALL32 %weird ; Determine if we have a weird string
- CMPI8_EAX !0 ; If weird
- JE32 %parse_string_weird ; Deal with it
-
- ;; Dealing with regular string
- COPY_EBX_to_EAX ; Passing Char* string
- CALL32 %collect_regular_string ; Collect it
- JMP32 %parse_string_done ; Be done
-
-:parse_string_weird
- COPY_EBX_to_EAX ; Passing Char* string
- CALL32 %collect_weird_string ; Collect it
-
-:parse_string_done
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; weird function
-;; Receives char* string in EAX
-;; Returns true(0) or false(1) in EAX
-;; Uses ECX to hold char* string
-:weird
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EAX_to_ECX ; Place string in safe place
- ADDI8_ECX !1 ; increment past the '\"'
-:weird_reset
- LOAD8_al_from_ECX ; Load a char
- MOVZX_al ; Make it useful
- CMPI8_EAX !0 ; IF NULL == C
- JE32 %weird_false ; Nothing weird found
-
- CMPI8_EAX !92 ; IF '\\'
- JNE32 %weird_escaped ; Deal with escaping
-
- ;; Deal with escape
- COPY_ECX_to_EAX ; We are passing the string
- CALL32 %escape_lookup ; to look it up
-
- ADDI8_ECX !1 ; string = string + 1
- LOAD8_bl_from_ECX ; get string[1]
- MOVZX_bl ; make it useful
- CMPI8_EBX !120 ; IF 'x' == string[1]
- JNE32 %weird_escaped ; otherwise skip the gap
-
- ADDI8_ECX !2 ; string = string + 2
-
-:weird_escaped
- PUSH_EAX ; Protect C in case we need it
- LOADI32_EBX &weird_string_0 ; Use "\t\n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
- CALL32 %In_Set ; To find if weird
- CMPI8_EAX !1 ; IF TRUE
- POP_EAX ; Restore C
- JNE32 %weird_true ; Then not weird
-
- ADDI8_ECX !1 ; string = string + 1
-
- ;; Last chance for weird
- LOADI32_EBX &weird_string_1 ; Use "\t\n\r "
- CALL32 %In_Set ; Check for special case
- CMPI8_EAX !1 ; IF TRUE
- JNE32 %weird_reset ; Otherwise not in the special case
-
- ;; Deal with possible special case
- LOAD8_al_from_ECX ; Load string[1]
- MOVZX_al ; Make it useful
- CMPI8_EAX !58 ; IF string[1] == ":"
- JE32 %weird_true ; Then we hit the special case
- JMP32 %weird_reset ; Keep trying
-
-:weird_done
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:weird_true
- LOADI32_EAX %0 ; Return true
- JMP32 %weird_done ; Be done
-
-:weird_false
- LOADI32_EAX %1 ; Return false
- JMP32 %weird_done ; Be done
-
-:weird_string_0 "
- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
-:weird_string_1 '09 0A 0D 20' ; "\t\n\r "
-
-
-;; collect_regular_string function
-;; Receives char* string in EAX
-;; Malloc and creates new string to return in EAX
-;; Uses ECX for return string and EDX for passed string
-:collect_regular_string
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_EDX ; Protect our passed string
- LOADI32_EAX %256 ; We need 256bytes of storage
- CALL32 %malloc ; Get our new pointer
- COPY_EAX_to_ECX ; put it in place
- PUSH_EAX ; protect until done
-:collect_regular_string_reset
- LOAD8_al_from_EDX ; string[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !0 ; See if we hit the end
- JE32 %collect_regular_string_done ; And be done
-
- CMPI8_EAX !92 ; IF string[0] == '\\'
- JE32 %collect_regular_string_escaped ; Deal with that mess
-
- ;; deal with boring char
- STORE8_al_into_Address_ECX ; hold_string[index] = string[0]
- ADDI8_ECX !1 ; Increment it
- ADDI8_EDX !1 ; Increment it
- JMP32 %collect_regular_string_reset ; And keep going
-
-:collect_regular_string_escaped
- COPY_EDX_to_EAX ; Using string
- CALL32 %escape_lookup ; Get the char
- STORE8_al_into_Address_ECX ; hold_string[index] = escape_lookup(string)
- ADDI8_EDX !1 ; Increment it
- ADDI8_ECX !1 ; Increment it
- LOAD8_al_from_EDX ; string[0]
- MOVZX_al ; Make it useful
- ADDI8_EDX !1 ; Increment it
- CMPI8_EAX !120 ; IF 'x' == string[1]
- JNE32 %collect_regular_string_reset ; Otherwise keep going
-
- ADDI8_EDX !2 ; Increment it
- JMP32 %collect_regular_string_reset ; Keep going
-
-:collect_regular_string_done
- LOADI32_EAX %34 ; Using '\"'
- STORE8_al_into_Address_ECX ; hold_string[index] = '\"'
- ADDI8_ECX !1 ; Increment it
- LOADI32_EAX %10 ; Using "\n"
- STORE8_al_into_Address_ECX ; hold_string[index] = '\n'
- POP_EAX ; Return our new string
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; collect_weird_string function
-;; Receives char* string in EAX
-;; Mallocs and returns char* hold in EAX
-;; Uses ECX for char* hold and EDX for char* string
-:collect_weird_string
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_EDX ; Protect our passed string
- LOADI32_EAX %512 ; We need 512bytes of storage
- CALL32 %malloc ; Get our new pointer
- COPY_EAX_to_ECX ; put it in place
- PUSH_EAX ; protect until done
-
- LOADI32_EAX %39 ; Using "'"
- STORE8_al_into_Address_ECX ; hold_string[index] = "'"
- ADDI8_ECX !1 ; Increment it
- ADDI8_EDX !1 ; Increment it
-:collect_weird_string_reset
- LOAD8_al_from_EDX ; Read a byte
- MOVZX_al ; Make it useful
- CMPI8_EAX !0 ; IF NULL == string[0]
- JE32 %collect_weird_string_done ; Be done
-
- LOADI32_EAX %32 ; Using ' '
- STORE8_al_into_Address_ECX ; hold_string[index] = ' '
- ADDI8_ECX !1 ; Increment it
-
- COPY_EDX_to_EAX ; Using string
- CALL32 %escape_lookup ; Get the char
- CALL32 %hex8 ; Update ECX
-
- LOAD8_al_from_EDX ; Read a byte
- MOVZX_al ; Make it useful
- ADDI8_EDX !1 ; Increment it
- CMPI8_EAX !92 ; IF string[0] == '\\'
- JNE32 %collect_weird_string_reset ; Otherwise keep going
-
- LOAD8_al_from_EDX ; Read a byte
- MOVZX_al ; Make it useful
- ADDI8_EDX !1 ; Increment it
- CMPI8_EAX !120 ; IF 'x' == string[1]
- JNE32 %collect_weird_string_reset ; Otherwise keep going
-
- ADDI8_EDX !2 ; Increment it
- JMP32 %collect_weird_string_reset ; Keep going
-
-:collect_weird_string_done
- LOADI32_EAX %32 ; Using ' '
- STORE8_al_into_Address_ECX ; hold_string[index] = ' '
- ADDI8_ECX !1 ; Increment it
- LOADI32_EAX %48 ; Using '0'
- STORE8_al_into_Address_ECX ; hold_string[index] = '0'
- ADDI8_ECX !1 ; Increment it
- STORE8_al_into_Address_ECX ; hold_string[index] = '0'
- ADDI8_ECX !1 ; Increment it
- LOADI32_EAX %39 ; Using "'"
- STORE8_al_into_Address_ECX ; hold_string[index] = "'"
- ADDI8_ECX !1 ; Increment it
- LOADI32_EAX %10 ; Using "\n"
- STORE8_al_into_Address_ECX ; hold_string[index] = '\n'
- POP_EAX ; Return our new string
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; HEX to ascii routine
-;; Receives INT in EAX and CHAR* in ECX
-;; Stores ascii of INT in CHAR*
-;; Returns only modifying EAX and ECX
-:hex8
- PUSH_EAX ; Protect bottom nibble
- SHRI8_EAX !4 ; do high nibble first
- CALL32 %hex4 ; Store it
- POP_EAX ; do low nibble
-:hex4
- ANDI32_EAX %0xF ; isolate nibble
- ADDI8_EAX !48 ; convert to ascii
- CMPI8_EAX !57 ; valid digit?
- JBE8 !hex1 ; yes
- ADDI8_EAX !7 ; use alpha range
-:hex1
- STORE8_al_into_Address_ECX ; store result
- ADDI8_ECX !1 ; next position
- RETURN
-
-
-;; type_name function
-;; Receives nothing
-;; Returns type_size in EAX
-;; Uses ECX for STRUCT TYPE* RET
-:type_name
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &struct ; Using "struct"
- CALL32 %match ; IF global_token->S == "struct"
- COPY_EAX_to_ECX ; Protect structure
- CMPI8_EAX !0 ; need to skip over "struct"
- JNE32 %type_name_native ; otherwise keep going
-
- ;; Deal with possible STRUCTs
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX ; global_token->next
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->next
- LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S
- LOAD32_Absolute32_ebx &global_types ; get all known types
- CALL32 %lookup_type ; Find type if possible
- COPY_EAX_to_ECX ; Set ret
-
- CMPI8_EAX !0 ; IF NULL == ret
- JNE32 %type_name_common ; We have to create struct
-
- ;; Create a struct
- CALL32 %create_struct ; Create a new struct
- LOADI32_ECX %0 ; We wish to return NULL
- JMP32 %type_name_done ; be done
-
-:type_name_native
- ;; Deal only with native types
- COPY_EBX_to_EAX ; Put global_token->S in the right place
- LOAD32_Absolute32_ebx &global_types ; get all known types
- CALL32 %lookup_type ; Find the type if possible
- COPY_EAX_to_ECX ; Set ret
-
- CMPI8_EAX !0 ; IF NULL == ret
- JNE32 %type_name_common ; We need to abort hard
-
- ;; Aborting hard
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- LOADI32_EAX &type_name_string_0 ; Print header
- CALL32 %File_Print ; Print it
-
- LOAD32_Absolute32_eax &global_token ; Using global token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %File_Print ; Print it
-
- LOADI32_EAX &type_name_string_1 ; Print footer
- CALL32 %File_Print ; Print it
-
-; CALL32 %line_error ; Give details
- JMP32 %Exit_Failure ; Abort
-
-:type_name_common
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX ; global_token->next
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->next
-
-:type_name_iter
- LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; make it useful
- CMPI8_EAX !42 ; IF global_token->S[0] == '*'
- JNE32 %type_name_done ; recurse
-
- ;; Deal with char**
- LOAD32_ECX_from_ECX_Immediate8 !12 ; ret = ret->indirect
- LOAD32_Absolute32_ebx &global_token ; Using global_token
- LOAD32_EBX_from_EBX ; global_token->next
- STORE32_Absolute32_ebx &global_token ; global_token = global_token->next
- JMP32 %type_name_iter ; keep looping
-
-:type_name_done
- COPY_ECX_to_EAX ; put ret in the right place
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:type_name_string_0 "Unknown type "
-:type_name_string_1 "
-"
-
-
-;; lookup_type function
-;; Receives char* s in EAX and struct type* start in EBX
-;; Returns struct type* in EAX
-;; Uses EBX for S and ECX for I
-:lookup_type
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- COPY_EBX_to_ECX ; I = Start
- COPY_EAX_to_EBX ; Put S in place
-:lookup_type_iter
- CMPI8_ECX !0 ; Check if I == NULL
- JE32 %lookup_type_done ; return NULL
-
- LOAD32_EAX_from_ECX_Immediate8 !24 ; I->NAME
- CALL32 %match ; Check if matching
- CMPI8_EAX !0 ; IF I->NAME == S
- JE32 %lookup_type_done ; return it
-
- LOAD32_ECX_from_ECX ; Otherwise I = I->NEXT
- JMP32 %lookup_type_iter ; And keep looping
-
-:lookup_type_done
- COPY_ECX_to_EAX ; return either I or NULL
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; create_struct function
-;; Receives nothing
-;; Returns nothing
-;; Uses global_token to malloc a struct's definition
-;; Uses ECX for int OFFSET, EDX for struct type* head, EBP for struct type* I,
-;; EDI for member_size (Which is passed) and ESI for LAST
-;; EAX and EBX are used for scratch
-:create_struct
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_EBP ; Protect EBP
- PUSH_EDI ; Protect EDI
- PUSH_ESI ; Protect ESI
- LOADI32_ECX %0 ; OFFSET = 0
- LOADI32_EDI %0 ; member_size = 0
-
- LOADI32_EAX %28 ; sizeof(struct type)
- CALL32 %malloc ; malloc(sizeof(struct type))
- COPY_EAX_to_EDX ; Set HEAD
-
- LOADI32_EAX %28 ; sizeof(struct type)
- CALL32 %malloc ; malloc(sizeof(struct type))
- COPY_EAX_to_EBP ; Set I
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- STORE32_EAX_into_EDX_Immediate8 !24 ; HEAD->NAME = global_token->S
- STORE32_EAX_into_EBP_Immediate8 !24 ; I->NAME = global_token->S
-
- STORE32_EBP_into_EDX_Immediate8 !12 ; HEAD->INDIRECT = I
- STORE32_EDX_into_EBP_Immediate8 !12 ; I->INDIRECT = HEAD
-
- LOAD32_Absolute32_eax &global_types ; Using global_types
- STORE32_EAX_into_EDX ; HEAD->NEXT = global_types
- STORE32_Absolute32_edx &global_types ; global_types = HEAD
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX %4 ; Using register size
- STORE32_EAX_into_EBP_Immediate8 !4 ; I->SIZE = register size
-
- LOADI32_EAX &create_struct_string_0 ; Using "ERROR in create_struct\n Missing {\n"
- LOADI32_EBX &open_curly_brace ; Using "{"
- CALL32 %require_match ; Make sure we have it
-
- LOADI32_ESI %0 ; LAST = NULL
-
-:create_struct_iter
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; Make it useful
- CMPI8_EAX !125 ; IF global_token->S[0] == "}"
- JE32 %create_struct_done ; be done
-
- ;; Looks like we are adding members
- ;; Lets see if it is a union
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EBX &union ; Using "union"
- CALL32 %match ; IF match(global_token->s, "union")
- CMPI8_EAX !0 ; Deal with union
- JNE32 %create_struct_single ; Otherwise deal with singles
-
- ;; Deal with union
- COPY_ESI_to_EAX ; Put last in right place
- COPY_ECX_to_EBX ; put offset in right place
- CALL32 %build_union ; ASSEMBLE
- COPY_EAX_to_ESI ; last = build_union(last, offset)
- ADD_edi_into_ecx ; offset = offset + member_size
-
- LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
- JMP32 %create_struct_iter ; keep going
-
-:create_struct_single
- ;; deal with singles
- COPY_ESI_to_EAX ; Put last in right place
- COPY_ECX_to_EBX ; put offset in right place
- CALL32 %build_member ; ASSEMBLE
- COPY_EAX_to_ESI ; last = build_union(last, offset)
- ADD_edi_into_ecx ; offset = offset + member_size
-
- LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
- JMP32 %create_struct_iter ; keep going
-
-:create_struct_done
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
-
- STORE32_ECX_into_EDX_Immediate8 !4 ; HEAD->SIZE = OFFSET
- STORE32_ESI_into_EDX_Immedate8 !16 ; HEAD->MEMBERS = LAST
- STORE32_ESI_into_EBP_Immedate8 !16 ; I->MEMBERS = LAST
-
- POP_ESI ; Restore ESI
- POP_EDI ; Restore EDI
- POP_EBP ; Restore EBP
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:create_struct_string_0 "ERROR in create_struct
- Missing {
-"
-:create_struct_string_1 "ERROR in create_struct
- Missing ;
-"
-
-
-;; lookup_member function
-;; Receives struct type* parent in EAX and char* name in EBX
-;; Returns struct type* I in EAX
-;; Uses char* NAME in EBX, ECX for struct type* I and EDX to hold parent for errors
-;; Aborts hard if not found
-:lookup_member
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_EDX ; Protect Parent
- LOAD32_ECX_from_EAX_Immediate8 !16 ; struct type* I = parent->MEMBERS
-:lookup_member_iter
- CMPI8_ECX !0 ; IF I == NULL
- JE32 %lookup_member_fail ; Abort HARD
-
- LOAD32_EAX_from_ECX_Immediate8 !24 ; Using I->NAME
- CALL32 %match ; IF I->NAME == NAME
- CMPI8_EAX !0 ; Then we have found the member
- COPY_ECX_to_EAX ; Prepare for return
- LOAD32_ECX_from_ECX_Immediate8 !16 ; Prepare for loop I = I->MEMBERS
- JNE32 %lookup_member_iter ; Looks like we are looping
-
- ;; I is already in EAX
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:lookup_member_fail
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
- LOADI32_EAX &lookup_member_string_0 ; Using "ERROR in lookup_member "
- CALL32 %File_Print ; print it
-
- LOAD32_EAX_from_EDX_Immediate8 !24 ; PARENT->NAME
- CALL32 %File_Print ; print it
-
- LOADI32_EAX &arrow_string ; Using "->"
- CALL32 %File_Print ; print it
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %File_Print ; print it
-
- LOADI32_EAX &lookup_member_string_1 ; Using " does not exist\n"
- CALL32 %File_Print ; print it
-
-; CALL32 %line_error ; Write useful debug info
-
- LOADI32_EAX &lookup_member_string_2 ; Using "\n"
- CALL32 %File_Print ; print it
- JMP32 %Exit_Failure ; Abort Hard
-
-:lookup_member_string_0 "ERROR in lookup_member "
-:lookup_member_string_1 " does not exist
-"
-:lookup_member_string_2 "
-"
-
-
-;; build_member function
-;; Receives struct type* last in EAX, int offset in EBX and global member_size in EDI
-;; Updates member_size in EDI and returns struct type* I in EAX
-;; Uses ECX for struct type* member_type and EDX for struct type* I
-:build_member
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_EDX ; Put last out of the way
- LOADI32_EAX %28 ; Allocate type
- CALL32 %malloc ; Get I
- STORE32_EDX_into_EAX_Immediate8 !16 ; I->MEMBERS = LAST
- STORE32_EBX_into_EAX_Immediate8 !8 ; I->OFFSET = OFFSET
- COPY_EAX_to_EDX ; Put I in place
-
- CALL32 %type_name ; Get member_type
- COPY_EAX_to_ECX ; Put in place
- STORE32_ECX_into_EDX_Immediate8 !20 ; I->TYPE = MEMBER_TYPE
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S
- STORE32_EBX_into_EDX_Immediate8 !24 ; I->NAME = global_token->S
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- ;; Check if we have an array
- LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S
- LOADI32_EAX &open_bracket ; Using "["
- CALL32 %match ; IF global_token->S == "["
- CMPI8_EAX !0 ; Then we have to deal with arrays in our structs
- JE32 %build_member_array ; So deal with that pain
-
- ;; Deal with non-array case
- LOAD32_EAX_from_ECX_Immediate8 !4 ; member_type->SIZE
- STORE32_EAX_into_EDX_Immediate8 !4 ; I->SIZE = member_type->SIZE
- JMP32 %build_member_done ; Be done
-
-:build_member_array
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- CALL32 %numerate_string ; convert number
- LOAD32_EBX_from_ECX_Immediate8 !20 ; member_type->TYPE
- LOAD32_EBX_from_EBX_Immediate8 !4 ; member_type->TYPE->SIZE
- IMUL_EAX_by_EBX ; member_type->type->size * numerate_string(global_token->s)
- STORE32_EAX_into_EDX_Immediate8 !4 ; I->SIZE = member_type->type->size * numerate_string(global_token->s)
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &build_member_string_0 ; Using "Struct only supports [num] form\n"
- LOADI32_EBX &close_bracket ; Using "]"
- CALL32 %require_match ; Make sure we have it
-
-:build_member_done
- LOAD32_EDI_from_EDX_Immediate8 !4 ; MEMBER_SIZE = I->SIZE
- STORE32_ECX_into_EDX_Immediate8 !20 ; I->TYPE = MEMBER_TYPE
- COPY_EDX_to_EAX ; Return I
-
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:build_member_string_0 "Struct only supports [num] form
-"
-
-
-;; build_union function
-;; Receives struct type* last in EAX, int offset in EBX and global member_size in EDI
-;; Updates member_size in EDI and returns struct type* LAST in EAX
-;; Uses ECX for struct type* last, EDX for int offset, ESI for int size and EDI for int member_size
-:build_union
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_ESI ; Protect ESI
- COPY_EAX_to_ECX ; Put LAST in right spot
- COPY_EBX_to_EDX ; Put OFFSET in right spot
- LOADI32_ESI %0 ; SIZE = 0
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- LOADI32_EAX &build_union_string_0 ; Using "ERROR in build_union\nMissing {\n"
- LOADI32_EBX &open_curly_brace ; Using "{"
- CALL32 %require_match ; Make sure we have it
-
-:build_union_iter
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S
- LOAD8_al_from_EAX ; global_token->S[0]
- MOVZX_al ; make it useful
- CMPI8_EAX !125 ; IF global_token->S[0] == "}"
- JE32 %build_union_done ; Be done
-
- ;; Collect union member
- COPY_ECX_to_EAX ; Passing LAST
- COPY_EDX_to_EBX ; Passing offset
- CALL32 %build_member ; build_member(last, offset)
- COPY_EAX_to_ECX ; last = build_member(last, offset)
-
- CMP_EDI_ESI ; IF member_size > size
- JG32 %build_union_size ; Then update size
-
- ;; deal with member_size > size
- COPY_EDI_to_ESI ; SIZE = MEMBER_SIZE
-
-:build_union_size
- LOADI32_EAX &build_union_string_1 ; Using "ERROR in build_union\nMissing ;\n"
- LOADI32_EBX &semicolon ; Using ";"
- CALL32 %require_match ; Make sure we have it
- JMP32 %build_union_iter ; Keep going
-
-:build_union_done
- COPY_ESI_to_EDI ; MEMBER_SIZE = SIZE
-
- LOAD32_Absolute32_eax &global_token ; Using global_token
- LOAD32_EAX_from_EAX ; global_token->NEXT
- STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT
-
- COPY_ECX_to_EAX ; Return last
-
- POP_ESI ; Restore ESI
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:build_union_string_0 "ERROR in build_union
-Missing {
-"
-:build_union_string_1 "ERROR in build_union
-Missing ;
-"
-
-
-;; sym_declare function
-;; Receives char *s in EAX, struct type* t in EBX, and struct token_list* list in ECX
-;; Returns struct token_list* in EAX
-;; Uses EAX for A
-:sym_declare
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_EDX ; Get char *S safely out of the way
- LOADI32_EAX %20 ; Using sizeof(struct token_list)
- CALL32 %malloc ; Get pointer to A
- STORE32_ECX_into_EAX ; A->NEXT = LIST
- STORE32_EDX_into_EAX_Immediate8 !8 ; A->S = S
- STORE32_EBX_into_EAX_Immediate8 !12 ; A->TYPE = T
- POP_EDX ; Restore EDX
- RETURN
-
-
-;; match function
-;; Receives CHAR* in EAX and CHAR* in EBX
-;; Returns 0 (TRUE) or 1 (FALSE) in EAX
-:match
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- COPY_EAX_to_ECX ; S1 in place
- COPY_EBX_to_EDX ; S2 in place
-:match_Loop
- LOAD8_al_from_ECX ; S1[0]
- MOVZX_al ; Make it useful
- LOAD8_bl_from_EDX ; S2[0]
- MOVZX_bl ; Make it useful
- CMP_EAX_EBX ; See if they match
- JNE32 %match_False ; If not
-
- ADDI8_ECX !1 ; S1 = S1 + 1
- ADDI8_EDX !1 ; S2 = S2 + 1
- CMPI8_EAX !0 ; If reached end of string
- JE32 %match_Done ; Perfect match
- JMP32 %match_Loop ; Otherwise keep looping
-
-:match_False
- LOADI32_EAX %1 ; Return false
-:match_Done
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; numerate_number function
-;; Receives an INT A in EAX
-;; Returns char* result in EAX
-;; Allocates 16 bytes of memory
-;; Behaves badly when given a negative number too large
-;; Uses EAX for temp, EBX for DIVISOR, EDX for mod/0, ESI for result[i] and EBP for A
-:numerate_number
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_ESI ; Protect ESI
- PUSH_EBP ; Protect EBP
- COPY_EAX_to_EBP ; Protect A
-
- LOADI32_EAX %16 ; 16bytes
- CALL32 %malloc ; Get our pointer
- PUSH_EAX ; Protect our pointer
- COPY_EAX_to_ESI ; put pointer in right place
- LOADI32_EBX %0x3B9ACA00 ; Set divisor to largest positive number that fits in 32bits
-
- CMPI8_EBP !0 ; Deal with 0 case
- JE32 %numerate_number_ZERO ; If it is
- JG32 %numerate_number_positive ; If it is positive
-
- ;; Deal with negative case
- LOADI32_EAX %45 ; Using "-"
- STORE8_al_into_Address_ESI ; Write it
- ADDI8_ESI !1 ; increment
- IMULI8_EBP !-1 ; A = A * -1
-
-:numerate_number_positive
- LOADI32_EDX %0 ; Set top to 0
- COPY_EBP_to_EAX ; Using A as bottom
- IDIV_EBX ; edx:eax % ebx -> edx + edx:eax / ebx -> eax [Even if we don't want it]
- CMPI8_EAX !0 ; IF 0 == (a / divisor)
- JNE32 %numerate_number_iter ; Clean up those leading Zeros
-
- LOADI32_EDX %0 ; Set top to 0
- COPY_EBX_to_EAX ; Using Divisor for bottom
- LOADI32_EBX %10 ; Make this shit work because idiv 10 doesn't work
- IDIV_EBX ; edx:eax % 10 -> edx + edx:eax / 10 -> eax [Even if we don't want it]
- COPY_EAX_to_EBX ; Update divisor
- JMP32 %numerate_number_positive ; Keep collecting
-
-:numerate_number_iter
- CMPI8_EBX !0 ; IF DIVISOR < 0
- JLE32 %numerate_number_done ; Be done
-
- LOADI32_EDX %0 ; Set top to 0
- COPY_EBP_to_EAX ; Using A as bottom
- IDIV_EBX ; edx:eax % ebx -> edx + edx:eax / ebx -> eax [Even if we don't want it]
- ADDI8_EAX !48 ; ((a / divisor) + 48)
- STORE8_al_into_Address_ESI ; Write it
- COPY_EDX_to_EBP ; a = a % divisor
-
- LOADI32_EDX %0 ; Set top to 0
- COPY_EBX_to_EAX ; Using Divisor for bottom
- LOADI32_EBX %10 ; Make this shit work because idiv 10 doesn't work
- IDIV_EBX ; edx:eax % 10 -> edx + edx:eax / 10 -> eax [Even if we don't want it]
- COPY_EAX_to_EBX ; Update divisor
-
- ADDI8_ESI !1 ; increment
- JMP32 %numerate_number_iter ; Keep going
-
-:numerate_number_done
- POP_EAX ; Restore our result
- POP_EBP ; Restore EBP
- POP_ESI ; Restore ESI
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-:numerate_number_ZERO
- LOADI32_EAX %48 ; Using '0'
- STORE8_al_into_Address_ESI ; Write it
- ADDI8_ESI !1 ; increment
- JMP32 %numerate_number_done ; Be done
-
-
-;; numerate_string function
-;; Receives CHAR* in EAX
-;; Returns value of CHAR* in EAX
-;; Uses EAX for VALUE, EBX for S, ECX for CH and ESI for NEGATIVE?
-:numerate_string
- PUSH_EBX ; Protect EBX
- PUSH_ECX ; Protect ECX
- PUSH_EDX ; Protect EDX
- PUSH_ESI ; Protect ESI
- COPY_EAX_to_EBX ; put S in correct place
- LOADI32_EAX %0 ; Initialize to Zero
-:numerate_string_loop
- LOAD8_cl_from_EBX_Immediate8 !1 ; S[1]
- MOVZX_cl ; make it useful
- CMPI8_ECX !120 ; IF 'x' == S[1]
- JE32 %numerate_hex ; Deal with hex input
-
- ;; Assume decimal input
- LOADI32_ESI %0 ; Assume no negation
- LOAD8_cl_from_EBX ; S[0]
- MOVZX_cl ; make it useful
- CMPI8_ECX !45 ; IF '-' == S[0]
- JNE32 %numerate_decimal ; Skip negation
-
- LOADI32_ESI %1 ; Set FLAG
- ADDI8_EBX !1 ; S = S + 1
-
-:numerate_decimal
- LOAD8_cl_from_EBX ; S[0]
- MOVZX_cl ; make it useful
- CMPI8_ECX !0 ; IF NULL == S[0]
- JE32 %numerate_decimal_done ; We are done
-
- IMULI8_EAX !10 ; VALUE = VALUE * 10
- SUBI8_ECX !48 ; CH = CH - '0'
- CMPI8_ECX !9 ; Check for illegal
- JG32 %numerate_string_fail ; If CH > '9'
- CMPI8_ECX !0 ; Check for illegal
- JL32 %numerate_string_fail ; IF CH < 0
- ADD_ecx_into_eax ; VALUE = VALUE + CH
- ADDI8_EBX !1 ; S = S + 1
- JMP32 %numerate_decimal ; Keep looping
-
-:numerate_decimal_done
- CMPI8_ESI !1 ; Check if need to negate
- JNE32 %numerate_string_done ; Nope
-
- IMULI8_EAX !-1 ; VALUE = VALUE * -1
- JMP32 %numerate_string_done ; Done
-
-:numerate_hex
- ADDI8_EBX !2 ; S = S + 2
-:numerate_hex_loop
- LOAD8_cl_from_EBX ; S[0]
- MOVZX_cl ; make it useful
- CMPI8_ECX !0 ; IF NULL == S[0]
- JE32 %numerate_string_done ; We are done
-
- SALI8_EAX !4 ; VALUE = VALUE << 4
- SUBI8_ECX !48 ; CH = CH - '0'
- CMPI8_ECX !10 ; IF 10 >= CH
- JL32 %numerate_hex_digit ; NO
- SUBI8_ECX !7 ; Push A-F into range
-:numerate_hex_digit
- CMPI8_ECX !15 ; Check for illegal
- JG32 %numerate_string_fail ; If CH > 'F'
- CMPI8_ECX !0 ; Check for illegal
- JL32 %numerate_string_fail ; IF CH < 0
- ADD_ecx_into_eax ; VALUE = VALUE + CH
- ADDI8_EBX !1 ; S = S + 1
- JMP32 %numerate_hex_loop ; Keep looping
-
-:numerate_string_fail
- LOADI32_EAX %0 ; return ZERO
-
-:numerate_string_done
- POP_ESI ; Restore ESI
- POP_EDX ; Restore EDX
- POP_ECX ; Restore ECX
- POP_EBX ; Restore EBX
- RETURN
-
-
-;; Exit_Failure function
-;; Receives nothing
-;; And aborts hard
-;; Does NOT return
-:Exit_Failure
- LOADI32_EBX %1 ; All is wrong
- LOADI32_EAX %1 ; put the exit syscall number in eax
- INT_80 ; Call it a bad day
-
-;; 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 "]"
-:comma ","
-:semicolon ";"
-:equal "="
-:percent "%"
-:newline "\n"
-:underline "_"
-
-
-:prim_types
-:type_void
- &type_int ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_void ; INDIRECT
- %0 ; MEMBERS
- &type_void ; TYPE
- &type_void_name ; NAME
-:type_void_name "void"
-
-:type_int
- &type_char ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_int ; INDIRECT
- %0 ; MEMBERS
- &type_int ; TYPE
- &type_int_name ; NAME
-:type_int_name "int"
-
-:type_char
- &type_file ; NEXT
- %1 ; SIZE
- %0 ; OFFSET
- &type_char_indirect ; INDIRECT
- %0 ; MEMBERS
- &type_char ; TYPE
- &type_char_name ; NAME
-:type_char_name "char"
-
-:type_char_indirect
- &type_file ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_char_double_indirect ; INDIRECT
- %0 ; MEMBERS
- &type_char_indirect ; TYPE
- &type_char_indirect_name ; NAME
-:type_char_indirect_name "char*"
-
-:type_char_double_indirect
- &type_file ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_char_double_indirect ; INDIRECT
- %0 ; MEMBERS
- &type_char_indirect ; TYPE
- &type_char_double_indirect_name ; NAME
-:type_char_double_indirect_name "char**"
-
-:type_file
- &type_function ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_file ; INDIRECT
- %0 ; MEMBERS
- &type_file ; TYPE
- &type_file_name ; NAME
-:type_file_name "FILE"
-
-:type_function
- &type_unsigned ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_function ; INDIRECT
- %0 ; MEMBERS
- &type_function ; TYPE
- &type_function_name ; NAME
-:type_function_name "FUNCTION"
-
-:type_unsigned
- %0 ; NEXT
- %4 ; SIZE
- %0 ; OFFSET
- &type_unsigned ; INDIRECT
- %0 ; MEMBERS
- &type_unsigned ; TYPE
- &type_unsigned_name ; NAME
-:type_unsigned_name "unsigned"
-
-
-;; debug_list function
-;; Receives struct token_list* in EAX
-;; Prints contents of list and exits
-;; Does NOT return
-:debug_list
- COPY_EAX_to_EBP ; Protect the list pointer
- LOADI32_EAX %2 ; Using Standard error
- STORE32_Absolute32_eax &Output_file ; write to standard error
-
-:debug_list_iter
- ;; Header
- LOADI32_EAX &debug_list_string0 ; Using our first string
- CALL32 %File_Print ; Print it
- COPY_EBP_to_EAX ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- ;; NEXT
- LOADI32_EAX &debug_list_string1 ; Using our second string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !0 ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- ;; PREV
- LOADI32_EAX &debug_list_string2 ; Using our third string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !4 ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- ;; S
- LOADI32_EAX &debug_list_string3 ; Using our fourth string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !8 ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- ;; S Contents
- LOADI32_EAX &debug_list_string4 ; Using our fifth string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !8 ; Use address of string
- CMPI8_EAX !0 ; IF NULL Pointer
- JNE32 %debug_list_null ; otherwise display
- LOADI32_EAX &debug_list_string_null ; Give meaningful message instead
-:debug_list_null
- CALL32 %File_Print ; Print it
-
- ;; TYPE
- LOADI32_EAX &debug_list_string5 ; Using our sixth string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !12 ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- ;; ARGS/DEPTH
- LOADI32_EAX &debug_list_string6 ; Using our third string
- CALL32 %File_Print ; Print it
- LOAD32_EAX_from_EBP_Immediate8 !16 ; Use address of pointer
- CALL32 %numerate_number ; Convert it into string
- CALL32 %File_Print ; Print it
-
- LOADI32_EAX %10 ; Add "\n"
- CALL32 %fputc ; print it
- CALL32 %fputc ; print it
-
- LOAD32_EBP_from_EBP ; TOKEN = TOKEN->NEXT
- CMPI8_EBP !0 ; Check if NULL
- JNE32 %debug_list_iter ; iterate otherwise
-
- LOADI32_EBX %666 ; All is HELL
- LOADI32_EAX %1 ; put the exit syscall number in eax
- INT_80 ; Call it a bad day
-
-: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 ">::::<"
-
-
-:Address_of
- NULL
-:C
- NULL
-:Input_file
- NULL
-:MALLOC
- NULL
-:Output_file
- NULL
-:Token
- NULL
-:break_frame
- NULL
-:break_target_func
- NULL
-:break_target_head
- NULL
-:break_target_num
- NULL
-:current_count
- NULL
-:current_target
- NULL
-:function
- NULL
-:global_constant_list
- NULL
-:global_function_list
- NULL
-:global_symbol_list
- NULL
-:global_token
- NULL
-:global_types
- &prim_types
-:globals_list
- NULL
-:output_list
- NULL
-:string_index
- NULL
-:strings_list
- NULL
-
-:ELF_end
diff --git a/cc.h b/cc.h
index 685f967..c7a1696 100644
--- a/cc.h
+++ b/cc.h
@@ -49,6 +49,7 @@ struct type
struct type* next;
int size;
int offset;
+ int SIGNED;
struct type* indirect;
struct type* members;
struct type* type;
diff --git a/cc_types.c b/cc_types.c
index 8860db0..d938e4f 100644
--- a/cc_types.c
+++ b/cc_types.c
@@ -29,84 +29,100 @@ void initialize_types()
/* Define void */
global_types = calloc(1, sizeof(struct type));
global_types->name = "void";
+ global_types->SIGNED = FALSE;
global_types->size = register_size;
global_types->type = global_types;
/* void* has the same properties as void */
global_types->indirect = global_types;
- /* Define int */
+ /* Define UNSIGNED LONG */
struct type* a = calloc(1, sizeof(struct type));
- a->name = "int";
+ a->name = "SCM";
+ a->SIGNED = FALSE;
a->size = register_size;
- /* int* has the same properties as int */
a->indirect = a;
a->type = a;
- /* Define char* */
+ /* Define LONG */
struct type* b = calloc(1, sizeof(struct type));
- b->name = "char*";
+ b->name = "long";
+ b->SIGNED = TRUE;
b->size = register_size;
+ b->indirect = b;
b->type = b;
- /* Define char */
+ /* Define UNSIGNED */
struct type* c = calloc(1, sizeof(struct type));
- c->name = "char";
- c->size = 1;
+ c->name = "unsigned";
+ c->SIGNED = FALSE;
+ c->size = register_size;
c->type = c;
+ /* unsigned* has the same properties as unsigned */
+ c->indirect = c;
- /* Define char** */
+ /* Define int */
struct type* d = calloc(1, sizeof(struct type));
- d->name = "char**";
+ d->name = "int";
+ d->SIGNED = TRUE;
d->size = register_size;
- d->type = b;
+ /* int* has the same properties as int */
d->indirect = d;
+ d->type = d;
- /*fix up indrects for chars */
- c->indirect = b;
- b->indirect = d;
-
- /* Define FILE */
+ /* Define char* */
struct type* e = calloc(1, sizeof(struct type));
- e->name = "FILE";
+ e->name = "char*";
+ e->SIGNED = FALSE;
e->size = register_size;
e->type = e;
- /* FILE* has the same properties as FILE */
- e->indirect = e;
- /* Define FUNCTION */
+ /* Define char */
struct type* f = calloc(1, sizeof(struct type));
- f->name = "FUNCTION";
- f->size = register_size;
+ f->name = "char";
+ f->SIGNED = FALSE;
+ f->size = 1;
f->type = f;
- /* FUNCTION* has the same properties as FUNCTION */
- f->indirect = f;
- /* Define UNSIGNED */
+ /* Define char** */
struct type* g = calloc(1, sizeof(struct type));
- g->name = "unsigned";
+ g->name = "char**";
+ g->SIGNED = FALSE;
g->size = register_size;
- g->type = g;
- /* unsigned* has the same properties as unsigned */
+ g->type = e;
g->indirect = g;
- /* Custom type for mescc*/
+ /*fix up indrects for chars */
+ f->indirect = e;
+ e->indirect = g;
+
+ /* Define FILE */
struct type* h = calloc(1, sizeof(struct type));
- h->name = "SCM";
+ h->name = "FILE";
+ h->SIGNED = FALSE;
h->size = register_size;
+ h->type = h;
+ /* FILE* has the same properties as FILE */
h->indirect = h;
+ /* Define FUNCTION */
struct type* i = calloc(1, sizeof(struct type));
- i->name = "long";
+ i->name = "FUNCTION";
+ i->SIGNED = FALSE;
i->size = register_size;
+ i->type = i;
+ /* FUNCTION* has the same properties as FUNCTION */
i->indirect = i;
+ /* Primitives mes.c wanted */
struct type* j = calloc(1, sizeof(struct type));
j->name = "size_t";
+ j->SIGNED = FALSE;
j->size = register_size;
j->indirect = j;
struct type* k = calloc(1, sizeof(struct type));
k->name = "ssize_t";
+ k->SIGNED = FALSE;
k->size = register_size;
k->indirect = k;
@@ -116,10 +132,10 @@ void initialize_types()
h->next = i;
g->next = h;
f->next = g;
- e->next = f;
- d->next = e;
- c->next = e;
- a->next = c;
+ d->next = f;
+ c->next = d;
+ b->next = c;
+ a->next = b;
global_types->next = a;
prim_types = global_types;
}
diff --git a/test/test.answers b/test/test.answers
index d55ac24..4f5794f 100644
--- a/test/test.answers
+++ b/test/test.answers
@@ -53,10 +53,10 @@ a9cf4422e05075395ad75bbfe4b2659aec4541edd46d8c6b5064d3496b06a0b6 test/results/t
1154f39f25dcd6d914e9a542306f95280926baf985d011b2152c7ea0b87ab42d test/results/test10-knight-native-binary
c1b5a2a3cd46c5e95e5540e871c2a916e028684ca80f51c001ef489342e27625 test/results/test10-knight-posix-binary
b3e13d54aab689137628fb9c4487bfd8288f9bd18bef8fe756577c8d2dce1f1f test/results/test10-x86-binary
-67fe5708ecb58ff63262d002c81e007177395613166649c23119c154cd347254 test/results/test100-amd64-binary
-057cbf1a026f80c6f377af1eeeba6e38007697e8c12546ec853a4ca68f7869ce test/results/test100-armv7l-binary
-0c563f8028cc93be2091992ef1210cd1a25e006680ec3b1bac5ecc61370c9258 test/results/test100-knight-posix-binary
-84db585b6a8f51151c658ecbbcbd97a411d88d7379d5e416841ca616cf723374 test/results/test100-x86-binary
+4d41cd9cc1ac08bda0372a1e7be17965b7a6f3bc77f87ca024bc4cc7948aedf5 test/results/test100-amd64-binary
+a157f35aa2acf791464b242fe36f69816e1b91dd5559bca6a5bab1ad8ddcfbac test/results/test100-armv7l-binary
+1ce45071c156ce9f012b9cc8b179205c3948405b252c29db1f036c097f22947f test/results/test100-knight-posix-binary
+5e9e50ee0ca2c0cd290c4c764dfd1329baa563e078247b93754500543cb24c2e test/results/test100-x86-binary
34e6d535e30ef8826a4ad1a4d08b76cfa370c54595599ad3be784b64c9cd8ec5 test/results/test11-amd64-binary
d9d465340abbce2d5964a6bc58e6cdd0ef93fb3d0199eaa823c86ec6abd0452a test/results/test11-armv7l-binary
955b564d2c89abf2cfc6c80d766cd11479d146b828dec69e654b0958a62d5e6e test/results/test11-knight-native-binary
diff --git a/test/test100/proof.answer b/test/test100/proof.answer
index bc33ff4..93bc1b0 100644
--- a/test/test100/proof.answer
+++ b/test/test100/proof.answer
@@ -1 +1 @@
-d37c7ede25b79a5ba457fd80aec9f4a21df5a8c3d467e52c4f1d7146d83d2d64 test/test100/proof
+857519b111433c1cc3fd2f9fa60e86222e4227e9fce1601d08ceec6dfd7160e9 test/test100/proof