mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
33
.notes/disassembly.txt
Normal file
33
.notes/disassembly.txt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
//source
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
print "1";
|
||||||
|
break;
|
||||||
|
print "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "3";
|
||||||
|
|
||||||
|
//asm
|
||||||
|
|
||||||
|
0 TOY_OPCODE_READ [TOY_VALUE_BOOLEAN, true, -]
|
||||||
|
4 TOY_OPCODE_JUMP [TOY_OP_PARAM_JUMP_RELATIVE, TOY_OP_PARAM_JUMP_IF_FALSE, -]
|
||||||
|
8 52 (jumps to end '64' after this JUMP instruction)
|
||||||
|
12 TOY_OPCODE_SCOPE_PUSH
|
||||||
|
16 TOY_OPCODE_READ [TOY_VALUE_STRING, TOY_STRING_LEAF, 0]
|
||||||
|
20 0 (string "1")
|
||||||
|
24 TOY_OPCODE_PRINT
|
||||||
|
28 TOY_OPCODE_ESCAPE
|
||||||
|
32 0? (addr)
|
||||||
|
36 0? (diff)
|
||||||
|
40 TOY_OPCODE_READ [TOY_VALUE_STRING, TOY_STRING_LEAF, 0]
|
||||||
|
44 4 (string "2")
|
||||||
|
48 TOY_OPCODE_PRINT
|
||||||
|
52 TOY_OPCODE_SCOPE_POP
|
||||||
|
56 TOY_OPCODE_JUMP [TOY_OP_PARAM_JUMP_RELATIVE, TOY_OP_PARAM_JUMP_ALWAYS, -]
|
||||||
|
60 -64 (jumps to start '0' after this JUMP instruction)
|
||||||
|
64 TOY_OPCODE_READ [TOY_VALUE_STRING, TOY_STRING_LEAF, 0]
|
||||||
|
68 8 (string "3")
|
||||||
|
72 TOY_OPCODE_PRINT
|
||||||
|
76 TOY_OPCODE_RETURN
|
||||||
48
scripts/breakdancing.toy
Normal file
48
scripts/breakdancing.toy
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
while (true) {
|
||||||
|
print "1";
|
||||||
|
break;
|
||||||
|
print "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "3";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
print 1;
|
||||||
|
while (true) {
|
||||||
|
print 2;
|
||||||
|
if (true) {
|
||||||
|
print 3;
|
||||||
|
while (true) {
|
||||||
|
print 4;
|
||||||
|
break;
|
||||||
|
print 5;
|
||||||
|
}
|
||||||
|
print 6;
|
||||||
|
}
|
||||||
|
print 7;
|
||||||
|
}
|
||||||
|
print 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
print 9;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
print 1;
|
||||||
|
while (true) {
|
||||||
|
print 2;
|
||||||
|
if (true) {
|
||||||
|
print 3;
|
||||||
|
break;
|
||||||
|
print 6;
|
||||||
|
}
|
||||||
|
print 7;
|
||||||
|
}
|
||||||
|
print 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
print 9;
|
||||||
@@ -36,7 +36,8 @@ typedef enum Toy_OpcodeType {
|
|||||||
|
|
||||||
//control instructions
|
//control instructions
|
||||||
TOY_OPCODE_RETURN,
|
TOY_OPCODE_RETURN,
|
||||||
TOY_OPCODE_JUMP,
|
TOY_OPCODE_JUMP, //JUMP, ADDR
|
||||||
|
TOY_OPCODE_ESCAPE, //JUMP, ADDR, UNWIND
|
||||||
|
|
||||||
TOY_OPCODE_SCOPE_PUSH,
|
TOY_OPCODE_SCOPE_PUSH,
|
||||||
TOY_OPCODE_SCOPE_POP,
|
TOY_OPCODE_SCOPE_POP,
|
||||||
@@ -57,7 +58,7 @@ typedef enum Toy_OpcodeType {
|
|||||||
typedef enum Toy_OpParamJumpType {
|
typedef enum Toy_OpParamJumpType {
|
||||||
TOY_OP_PARAM_JUMP_ABSOLUTE = 0, //from the start of the routine's code section
|
TOY_OP_PARAM_JUMP_ABSOLUTE = 0, //from the start of the routine's code section
|
||||||
TOY_OP_PARAM_JUMP_RELATIVE = 1,
|
TOY_OP_PARAM_JUMP_RELATIVE = 1,
|
||||||
} Toy_OpJumpType;
|
} Toy_OpParamJumpType;
|
||||||
|
|
||||||
typedef enum Toy_OpParamJumpConditional {
|
typedef enum Toy_OpParamJumpConditional {
|
||||||
TOY_OP_PARAM_JUMP_ALWAYS = 0,
|
TOY_OP_PARAM_JUMP_ALWAYS = 0,
|
||||||
|
|||||||
@@ -9,6 +9,30 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//escapes
|
||||||
|
void* Toy_private_resizeEscapeArray(Toy_private_EscapeArray* ptr, unsigned int capacity) {
|
||||||
|
//if you're freeing everything, just return
|
||||||
|
if (capacity == 0) {
|
||||||
|
free(ptr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int originalCapacity = ptr == NULL ? 0 : ptr->capacity;
|
||||||
|
unsigned int orignalCount = ptr == NULL ? 0 : ptr->count;
|
||||||
|
|
||||||
|
ptr = (Toy_private_EscapeArray*)realloc(ptr, capacity * sizeof(Toy_private_EscapeEntry_t) + sizeof(Toy_private_EscapeArray));
|
||||||
|
|
||||||
|
if (ptr == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to resize an escape array within 'Toy_Routine' from %d to %d capacity\n" TOY_CC_RESET, (int)originalCapacity, (int)capacity);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->capacity = capacity;
|
||||||
|
ptr->count = orignalCount;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
static void expand(unsigned char** handle, unsigned int* capacity, unsigned int* count, unsigned int amount) {
|
static void expand(unsigned char** handle, unsigned int* capacity, unsigned int* count, unsigned int amount) {
|
||||||
if ((*count) + amount > (*capacity)) {
|
if ((*count) + amount > (*capacity)) {
|
||||||
@@ -240,7 +264,7 @@ static unsigned int writeInstructionBinaryShortCircuit(Toy_Routine** rt, Toy_Ast
|
|||||||
}
|
}
|
||||||
|
|
||||||
//parameter address
|
//parameter address
|
||||||
unsigned int endAddr = SKIP_INT(rt, code); //parameter to be written later
|
unsigned int paramAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
//if the lhs value isn't needed, pop it
|
//if the lhs value isn't needed, pop it
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ELIMINATE);
|
EMIT_BYTE(rt, code,TOY_OPCODE_ELIMINATE);
|
||||||
@@ -252,7 +276,7 @@ static unsigned int writeInstructionBinaryShortCircuit(Toy_Routine** rt, Toy_Ast
|
|||||||
writeRoutineCode(rt, ast.right);
|
writeRoutineCode(rt, ast.right);
|
||||||
|
|
||||||
//set the parameter
|
//set the parameter
|
||||||
OVERWRITE_INT(rt, code, endAddr, CURRENT_ADDRESS(rt, code) - (endAddr + 4));
|
OVERWRITE_INT(rt, code, paramAddr, CURRENT_ADDRESS(rt, code) - (paramAddr + 4));
|
||||||
|
|
||||||
return 1; //leaves only 1 value on the stack
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
@@ -401,7 +425,7 @@ static unsigned int writeInstructionIfThenElse(Toy_Routine** rt, Toy_AstIfThenEl
|
|||||||
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_IF_FALSE);
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_IF_FALSE);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
unsigned int thenEndAddr = SKIP_INT(rt, code); //parameter to be written later
|
unsigned int thenParamAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
//emit then-branch
|
//emit then-branch
|
||||||
writeRoutineCode(rt, ast.thenBranch);
|
writeRoutineCode(rt, ast.thenBranch);
|
||||||
@@ -413,21 +437,21 @@ static unsigned int writeInstructionIfThenElse(Toy_Routine** rt, Toy_AstIfThenEl
|
|||||||
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_ALWAYS);
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_ALWAYS);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
unsigned int elseEndAddr = SKIP_INT(rt, code); //parameter to be written later
|
unsigned int elseParamAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
//specify the starting position for the else branch
|
//specify the starting position for the else branch
|
||||||
OVERWRITE_INT(rt, code, thenEndAddr, CURRENT_ADDRESS(rt, code) - (thenEndAddr + 4));
|
OVERWRITE_INT(rt, code, thenParamAddr, CURRENT_ADDRESS(rt, code) - (thenParamAddr + 4));
|
||||||
|
|
||||||
//emit the else branch
|
//emit the else branch
|
||||||
writeRoutineCode(rt, ast.elseBranch);
|
writeRoutineCode(rt, ast.elseBranch);
|
||||||
|
|
||||||
//specify the ending position for the else branch
|
//specify the ending position for the else branch
|
||||||
OVERWRITE_INT(rt, code, elseEndAddr, CURRENT_ADDRESS(rt, code) - (elseEndAddr + 4));
|
OVERWRITE_INT(rt, code, elseParamAddr, CURRENT_ADDRESS(rt, code) - (elseParamAddr + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
//without an else branch, set the jump destination and move on
|
//without an else branch, set the jump destination and move on
|
||||||
OVERWRITE_INT(rt, code, thenEndAddr, CURRENT_ADDRESS(rt, code) - (thenEndAddr + 4));
|
OVERWRITE_INT(rt, code, thenParamAddr, CURRENT_ADDRESS(rt, code) - (thenParamAddr + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -446,7 +470,7 @@ static unsigned int writeInstructionWhileThen(Toy_Routine** rt, Toy_AstWhileThen
|
|||||||
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_IF_FALSE);
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_IF_FALSE);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
unsigned int endAddr = SKIP_INT(rt, code); //parameter to be written later
|
unsigned int paramAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
//emit then-branch
|
//emit then-branch
|
||||||
writeRoutineCode(rt, ast.thenBranch);
|
writeRoutineCode(rt, ast.thenBranch);
|
||||||
@@ -459,25 +483,85 @@ static unsigned int writeInstructionWhileThen(Toy_Routine** rt, Toy_AstWhileThen
|
|||||||
|
|
||||||
EMIT_INT(rt, code, beginAddr - (CURRENT_ADDRESS(rt, code) + 4)); //this sets a negative value
|
EMIT_INT(rt, code, beginAddr - (CURRENT_ADDRESS(rt, code) + 4)); //this sets a negative value
|
||||||
|
|
||||||
OVERWRITE_INT(rt, code, endAddr, CURRENT_ADDRESS(rt, code) - (endAddr + 4));
|
//set the exit parameter for the cond
|
||||||
|
OVERWRITE_INT(rt, code, paramAddr, CURRENT_ADDRESS(rt, code) - (paramAddr + 4));
|
||||||
|
|
||||||
|
//set the break & continue data
|
||||||
|
while ((*rt)->breakEscapes->count > 0) {
|
||||||
|
//extract
|
||||||
|
unsigned int addr = (*rt)->breakEscapes->data[(*rt)->breakEscapes->count - 1].addr;
|
||||||
|
unsigned int depth = (*rt)->breakEscapes->data[(*rt)->breakEscapes->count - 1].depth;
|
||||||
|
|
||||||
|
unsigned int diff = depth - (*rt)->currentScopeDepth;
|
||||||
|
|
||||||
|
OVERWRITE_INT(rt, code, addr, CURRENT_ADDRESS(rt, code) - (addr + 8)); //tell break to come here AFTER reading the instruction
|
||||||
|
OVERWRITE_INT(rt, code, addr, diff);
|
||||||
|
|
||||||
|
//tick down
|
||||||
|
(*rt)->breakEscapes->count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((*rt)->continueEscapes->count > 0) {
|
||||||
|
//extract
|
||||||
|
unsigned int addr = (*rt)->continueEscapes->data[(*rt)->continueEscapes->count - 1].addr;
|
||||||
|
unsigned int depth = (*rt)->continueEscapes->data[(*rt)->continueEscapes->count - 1].depth;
|
||||||
|
|
||||||
|
unsigned int diff = depth - (*rt)->currentScopeDepth;
|
||||||
|
|
||||||
|
OVERWRITE_INT(rt, code, addr, addr - (CURRENT_ADDRESS(rt, code) + 8)); //tell continue to return to the start AFTER reading the instruction
|
||||||
|
OVERWRITE_INT(rt, code, addr, diff);
|
||||||
|
|
||||||
|
//tick down
|
||||||
|
(*rt)->continueEscapes->count--;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionBreak(Toy_Routine** rt, Toy_AstBreak ast) {
|
static unsigned int writeInstructionBreak(Toy_Routine** rt, Toy_AstBreak ast) {
|
||||||
//TODO: implement break
|
//unused
|
||||||
(void)ast;
|
(void)ast;
|
||||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Keyword 'break' not yet implemented\n" TOY_CC_RESET);
|
|
||||||
(*rt)->panic = true;
|
//escapes are always relative
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_ESCAPE);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
unsigned int addr = SKIP_INT(rt, code);
|
||||||
|
(void)SKIP_INT(rt, code); //empty space for depth
|
||||||
|
|
||||||
|
//expand the escape array if needed
|
||||||
|
if ((*rt)->breakEscapes->capacity <= (*rt)->breakEscapes->count) {
|
||||||
|
(*rt)->breakEscapes = Toy_private_resizeEscapeArray((*rt)->breakEscapes, (*rt)->breakEscapes->capacity * TOY_ESCAPE_EXPANSION_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store for later
|
||||||
|
(*rt)->breakEscapes->data[(*rt)->breakEscapes->count++] = (Toy_private_EscapeEntry_t){ .addr = addr, .depth = (*rt)->currentScopeDepth };
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionContinue(Toy_Routine** rt, Toy_AstContinue ast) {
|
static unsigned int writeInstructionContinue(Toy_Routine** rt, Toy_AstContinue ast) {
|
||||||
//TODO: implement continue
|
//unused
|
||||||
(void)ast;
|
(void)ast;
|
||||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Keyword 'continue' not yet implemented\n" TOY_CC_RESET);
|
|
||||||
(*rt)->panic = true;
|
//escapes are always relative
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_ESCAPE);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
unsigned int addr = SKIP_INT(rt, code);
|
||||||
|
(void)SKIP_INT(rt, code); //empty space for depth
|
||||||
|
|
||||||
|
//expand the escape array if needed
|
||||||
|
if ((*rt)->continueEscapes->capacity <= (*rt)->continueEscapes->count) {
|
||||||
|
(*rt)->continueEscapes = Toy_private_resizeEscapeArray((*rt)->continueEscapes, (*rt)->continueEscapes->capacity * TOY_ESCAPE_EXPANSION_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store for later
|
||||||
|
(*rt)->continueEscapes->data[(*rt)->continueEscapes->count++] = (Toy_private_EscapeEntry_t){ .addr = addr, .depth = (*rt)->currentScopeDepth };
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -700,6 +784,8 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
(*rt)->currentScopeDepth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
result += writeRoutineCode(rt, ast->block.child);
|
result += writeRoutineCode(rt, ast->block.child);
|
||||||
@@ -710,6 +796,8 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
(*rt)->currentScopeDepth--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -909,12 +997,19 @@ void* Toy_compileRoutine(Toy_Ast* ast) {
|
|||||||
rt.subsCapacity = 0;
|
rt.subsCapacity = 0;
|
||||||
rt.subsCount = 0;
|
rt.subsCount = 0;
|
||||||
|
|
||||||
|
rt.currentScopeDepth = 0;
|
||||||
|
rt.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
|
rt.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
|
|
||||||
rt.panic = false;
|
rt.panic = false;
|
||||||
|
|
||||||
//build
|
//build
|
||||||
void * buffer = writeRoutine(&rt, ast);
|
void * buffer = writeRoutine(&rt, ast);
|
||||||
|
|
||||||
//cleanup the temp object
|
//cleanup
|
||||||
|
Toy_private_resizeEscapeArray(rt.breakEscapes, 0);
|
||||||
|
Toy_private_resizeEscapeArray(rt.continueEscapes, 0);
|
||||||
|
|
||||||
free(rt.param);
|
free(rt.param);
|
||||||
free(rt.code);
|
free(rt.code);
|
||||||
free(rt.jumps);
|
free(rt.jumps);
|
||||||
|
|||||||
@@ -3,6 +3,29 @@
|
|||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_ast.h"
|
#include "toy_ast.h"
|
||||||
|
|
||||||
|
//the 'escapes' are lists of data used for processing the 'break' and 'continue' keywords, and can be safely ignored
|
||||||
|
typedef struct Toy_private_EscapeEntry_t {
|
||||||
|
unsigned int addr; //the address to write *to*
|
||||||
|
unsigned int depth; //the current depth
|
||||||
|
} Toy_private_EscapeEntry_t;
|
||||||
|
|
||||||
|
typedef struct Toy_private_EscapeArray {
|
||||||
|
unsigned int capacity;
|
||||||
|
unsigned int count;
|
||||||
|
Toy_private_EscapeEntry_t data[];
|
||||||
|
} Toy_private_EscapeArray;
|
||||||
|
|
||||||
|
//not needed at runtime, so they can be bigger
|
||||||
|
#ifndef TOY_ESCAPE_INITIAL_CAPACITY
|
||||||
|
#define TOY_ESCAPE_INITIAL_CAPACITY 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TOY_ESCAPE_EXPANSION_RATE
|
||||||
|
#define TOY_ESCAPE_EXPANSION_RATE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TOY_API void* Toy_private_resizeEscapeArray(Toy_private_EscapeArray* ptr, unsigned int capacity);
|
||||||
|
|
||||||
//internal structure that holds the individual parts of a compiled routine
|
//internal structure that holds the individual parts of a compiled routine
|
||||||
typedef struct Toy_Routine {
|
typedef struct Toy_Routine {
|
||||||
unsigned char* param; //c-string params in sequence (could be moved below the jump table?)
|
unsigned char* param; //c-string params in sequence (could be moved below the jump table?)
|
||||||
@@ -25,8 +48,11 @@ typedef struct Toy_Routine {
|
|||||||
unsigned int subsCapacity;
|
unsigned int subsCapacity;
|
||||||
unsigned int subsCount;
|
unsigned int subsCount;
|
||||||
|
|
||||||
|
unsigned int currentScopeDepth;
|
||||||
|
Toy_private_EscapeArray* breakEscapes;
|
||||||
|
Toy_private_EscapeArray* continueEscapes;
|
||||||
|
|
||||||
bool panic; //any issues found at this point are compilation errors
|
bool panic; //any issues found at this point are compilation errors
|
||||||
} Toy_Routine;
|
} Toy_Routine;
|
||||||
|
|
||||||
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
||||||
|
|
||||||
|
|||||||
@@ -84,14 +84,14 @@ typedef enum Toy_TokenType {
|
|||||||
TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
||||||
|
|
||||||
//other operators
|
//other operators
|
||||||
TOY_TOKEN_OPERATOR_AND,
|
TOY_TOKEN_OPERATOR_AND, // &&
|
||||||
TOY_TOKEN_OPERATOR_OR,
|
TOY_TOKEN_OPERATOR_OR, // ||
|
||||||
TOY_TOKEN_OPERATOR_NEGATE,
|
TOY_TOKEN_OPERATOR_NEGATE, // !
|
||||||
TOY_TOKEN_OPERATOR_QUESTION,
|
TOY_TOKEN_OPERATOR_QUESTION, // ?
|
||||||
TOY_TOKEN_OPERATOR_COLON,
|
TOY_TOKEN_OPERATOR_COLON, // :
|
||||||
|
|
||||||
TOY_TOKEN_OPERATOR_SEMICOLON,
|
TOY_TOKEN_OPERATOR_SEMICOLON, // ;
|
||||||
TOY_TOKEN_OPERATOR_COMMA,
|
TOY_TOKEN_OPERATOR_COMMA, // ,
|
||||||
|
|
||||||
TOY_TOKEN_OPERATOR_DOT, // .
|
TOY_TOKEN_OPERATOR_DOT, // .
|
||||||
TOY_TOKEN_OPERATOR_CONCAT, // ..
|
TOY_TOKEN_OPERATOR_CONCAT, // ..
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ static void processRead(Toy_VM* vm) {
|
|||||||
|
|
||||||
case TOY_VALUE_STRING: {
|
case TOY_VALUE_STRING: {
|
||||||
enum Toy_StringType stringType = READ_BYTE(vm);
|
enum Toy_StringType stringType = READ_BYTE(vm);
|
||||||
int len = (int)READ_BYTE(vm);
|
int len = (int)READ_BYTE(vm); //only needed for name strings
|
||||||
|
|
||||||
//grab the jump as an integer
|
//grab the jump as an integer
|
||||||
unsigned int jump = *((int*)(vm->module + vm->jumpsAddr + READ_INT(vm)));
|
unsigned int jump = *((int*)(vm->module + vm->jumpsAddr + READ_INT(vm)));
|
||||||
@@ -524,7 +524,7 @@ static void processLogical(Toy_VM* vm, Toy_OpcodeType opcode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void processJump(Toy_VM* vm) {
|
static void processJump(Toy_VM* vm) {
|
||||||
Toy_OpJumpType type = READ_BYTE(vm);
|
Toy_OpParamJumpType type = READ_BYTE(vm);
|
||||||
Toy_OpParamJumpConditional cond = READ_BYTE(vm);
|
Toy_OpParamJumpConditional cond = READ_BYTE(vm);
|
||||||
fixAlignment(vm);
|
fixAlignment(vm);
|
||||||
|
|
||||||
@@ -571,6 +571,19 @@ static void processJump(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void processEscape(Toy_VM* vm) {
|
||||||
|
fixAlignment(vm);
|
||||||
|
|
||||||
|
int addr = READ_INT(vm); //where to go
|
||||||
|
int diff = READ_INT(vm); //what to do
|
||||||
|
|
||||||
|
vm->programCounter += addr;
|
||||||
|
|
||||||
|
while (diff > 0 && vm->scope != NULL) {
|
||||||
|
vm->scope = Toy_popScope(vm->scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void processAssert(Toy_VM* vm) {
|
static void processAssert(Toy_VM* vm) {
|
||||||
unsigned int count = READ_BYTE(vm);
|
unsigned int count = READ_BYTE(vm);
|
||||||
|
|
||||||
@@ -881,6 +894,10 @@ static void process(Toy_VM* vm) {
|
|||||||
processJump(vm);
|
processJump(vm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOY_OPCODE_ESCAPE:
|
||||||
|
processEscape(vm);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOY_OPCODE_SCOPE_PUSH:
|
case TOY_OPCODE_SCOPE_PUSH:
|
||||||
vm->scope = Toy_pushScope(&vm->scopeBucket, vm->scope);
|
vm->scope = Toy_pushScope(&vm->scopeBucket, vm->scope);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user