Specification for implementing a VM The stack VM works with two stacks, a base stack and a return stack. Memory layout 0x0000 - SYSTEM 00 - PC - The program counter 01 - SP - The stack pointer. The stack is used to run operators on data. 02 - RSP - The return stack pointer. The return stack is used to store memory addresses. 03 - JUMP_OFFSET 04-10 - CLI ARGS - Write arguments from the command line to these values to use them in a program 0x0010 - IO 10 - INPUT_LENGTH - This stores the length of input written in. 11 - INPUT - Memory after this holds the most recent stdin. 0c0030 - file device 0x00 - REQUEST FS 0x01 - PATH ADDR 0x02 - PATH LEN 0x03 - IN ADDR FORMAT file/path.ext;1024;type;created;modified 0x04 - FORMAT OPTIONS - 0b0000111100001111 1 - local path 2 - r 3 - w 4 - execute 5 - list 6 - size 7 - type 8 - creation date 9 - modified date 0x05 - IN LEN ... This memory is reserved for future functionality 0x0100 - ROM - Load the program here 0x0600 - STACK - The stack is here in memory 0x0700 - R_STACK - The return stack is here in memory ... This memory can be used to store variables and data. 0xFFFF - END OF MEMORY OPERATORS All operators (except LIT) use postfix notation meaning the operands must be on the stack before the operator. For example to add `1` and `2` the syntax is `1 2 ADD`. The below operators are defined with `(OPERAND1 OPERAND2 OPERAND3) OPERATOR_NAME OPERATOR_BYTECODE -> (STACK STATE AFTER OPERATOR) -> ACTION` . The parenthesis should not be included in real code. #define LFR 227 //LOAD FROM RETURN STACK #define PRS 228 //RETURN STACK PUSH (ADDRESS) JMR 229 -> () -> JUMP TO X. USE THE RETURN STACK (VALUE1 VALUE2 ADDRESS) JER 230 -> () -> JUMP TO X IF X-1 EQUAL TO X-2. USE THE RETURN STACK (VALUE1 VALUE2 ADDRESS) JNR 231 -> () -> JUMP TO X IF X-1 NOT EQUAL TO X-2. USE THE RETURN STACK NFH 232 -> (X) -> NEXT FREE HEAP (X MODE) CMP 233 -> (X MODE Y) -> PERFORM A COMPARISON BASED ON THE MODE = < > <= >= != IS NEG IS POS () RIN 234 -> () -> READ IN FROM STDIN (X) LSL 235 -> (X*) -> LOGICAL SHIFT LEFT (X Y) AND 236 -> (X&Y) -> LOGICAL AND (X Y) LOR 237 -> (X|Y) -> LOGICAL OR (...DATA... ADDRESS LENGTH) STV 238 -> () -> STORE VARIABLE DATA AT ADDRESS X-1 OF LENGTH X () END 239 -> () -> End the program exiting the emulator. () JCC 240 -> () -> Looks at the topmost value of the return stack and jumps to that address (VALUE_TO_COPY) DUP 241 -> (VALUE_TO_COPY COPIED_VALUE) -> Copies VALUE_TO_COPY to the top of the stack () LIT 242 -> (NEXT_VALUE_IN_CODE) -> Declares that the next stack value is not an operator and places i t onto the stack skipping execution. All non-operator operands will be prefixed with this. (VALUE_TO_REMOVE) POP 243 -> () -> Removes the top value from the stack, does not error on an empty stac k. (VALUE_TO_STORE ADDRESS) STA 244 -> () -> Put VALUE_TO_STORE at ADDRESS (ADDRESS) LFA 245 -> (VALUE_AT_ADDRESS) -> Put the value at ADDRESS on top of the stack (ADDRESS) JMP 246 -> () -> Jump to ADDRESS. (Does not modify the return stack) (VALUE1 VALUE2 ADDRESS) JNE 247 -> () -> Jump to ADDRESS if VALUE1 != VALUE2. Put the address of the nex t value on the return stack (VALUE1 VALUE2 ADDRESS) JEQ 248 -> () -> Jump to ADDRESS if VALUE1 == VALUE2. Put the address of the nex t value on the return stack (VALUE1 VALUE2) SWP 249 -> (VALUE2 VALUE1) -> Swaps the positions of VALUE1 and VALUE2 on the stack (VALUE_TO_COPY ANYTHING) OVR 250 -> (VALUE_TO_COPY ANYTHING COPIED_VALUE) -> Copies VALUE_TO_COPY to the top of the stack (X Y) DIV 251 -> (X_DIVIDED_BY_Y) -> Does an integer divide of X by Y (X Y) MUL 252 -> (X_DIVIDED_BY_Y) -> Put X*Y on top of the stack (X Y) SUB 253 -> (X_DIVIDED_BY_Y) -> Put X-Y on top of the stack (X Y) ADD 254 -> (X_DIVIDED_BY_Y) -> Put X+Y on top of the stack (ADDRESS DATA_LENGTH DATA_FORMAT) OUT 255 -> () Output x values starting at ADDRESS to stdout where X eq uals DATA_LENGTH. The output use DATA_FORMAT to determine how to format the data the int value of 'C' outputs as a charact er the int value of 'I' outputs as an integer. Specification for implementing a compiler DEFINE RULES ;A 1 1 A = [1,1] ;B 1 1 ;C B = 1, C = 2 ;D 1 D = 1 ;;GLOBAL_DEFINE ;LOCAL_DEFINE :DEFINE_AND_INIT_ON_RETURN_STACK VALUE @LABEL_MARK #LABEL_REFERECE Functions Definitions @{}NAME BODY JCC Calling { ARGS }#NAME ARGS NAME If Statements ?@IF_LABEL {}#load_input DUP 0 > OVR 10 < ? POP |@ELSEIF_LABEL {}#load_input DUP 10 > OVR 20 < ? POP |@ELSE_LABEL 1 ? POP ?? Imports $path/to/import.ual Strings 'STRING\n' Strings auto include null "terminators".