mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
WIP: Compiles but still very broken
This commit is contained in:
33
repl/main.c
33
repl/main.c
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "toy_lexer.h"
|
#include "toy_lexer.h"
|
||||||
#include "toy_parser.h"
|
#include "toy_parser.h"
|
||||||
#include "toy_module_compiler.h"
|
#include "toy_compiler.h"
|
||||||
#include "toy_vm.h"
|
#include "toy_vm.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -332,16 +332,15 @@ int repl(const char* filepath) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* buffer = Toy_compileModule(ast);
|
unsigned char* bytecode = Toy_compileToBytecode(ast);
|
||||||
Toy_Module module = Toy_parseModule(buffer);
|
Toy_bindVM(&vm, bytecode, runCount++ > 0);
|
||||||
Toy_bindVM(&vm, &module, runCount++ > 0);
|
|
||||||
|
|
||||||
//run
|
//run
|
||||||
Toy_runVM(&vm);
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
//free the memory, and leave the VM ready for the next loop
|
//free the memory, and leave the VM ready for the next loop
|
||||||
Toy_resetVM(&vm, true);
|
Toy_resetVM(&vm, true);
|
||||||
free(buffer);
|
free(bytecode);
|
||||||
|
|
||||||
printf("%s> ", prompt); //shows the terminal prompt
|
printf("%s> ", prompt); //shows the terminal prompt
|
||||||
}
|
}
|
||||||
@@ -368,7 +367,7 @@ static void debugStackPrint(Toy_Stack* stack) {
|
|||||||
|
|
||||||
//print value
|
//print value
|
||||||
Toy_String* string = Toy_stringifyValue(&stringBucket, Toy_unwrapValue(v));
|
Toy_String* string = Toy_stringifyValue(&stringBucket, Toy_unwrapValue(v));
|
||||||
char* buffer = Toy_getStringRawBuffer(string);
|
char* buffer = Toy_getStringRaw(string);
|
||||||
printf("%s", buffer);
|
printf("%s", buffer);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
Toy_freeString(string);
|
Toy_freeString(string);
|
||||||
@@ -382,23 +381,23 @@ static void debugStackPrint(Toy_Stack* stack) {
|
|||||||
|
|
||||||
static void debugScopePrint(Toy_Scope* scope, int depth) {
|
static void debugScopePrint(Toy_Scope* scope, int depth) {
|
||||||
//DEBUG: if there's anything in the scope, print it
|
//DEBUG: if there's anything in the scope, print it
|
||||||
if (scope->table->count > 0) {
|
if (scope->count > 0) {
|
||||||
Toy_Bucket* stringBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
Toy_Bucket* stringBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|
||||||
printf("Scope %d Dump\n-------------------------\ntype\tname\tvalue\n", depth);
|
printf("Scope %d Dump\n-------------------------\ntype\tname\tvalue\n", depth);
|
||||||
for (unsigned int i = 0; i < scope->table->capacity; i++) {
|
for (unsigned int i = 0; i < scope->capacity; i++) {
|
||||||
if ( (TOY_VALUE_IS_STRING(scope->table->data[i].key) && TOY_VALUE_AS_STRING(scope->table->data[i].key)->info.type == TOY_STRING_NAME) != true) {
|
if (scope->data[i].key.info.length == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value k = scope->table->data[i].key;
|
Toy_String k = scope->data[i].key;
|
||||||
Toy_Value v = scope->table->data[i].value;
|
Toy_Value v = scope->data[i].value;
|
||||||
|
|
||||||
printf("%s\t%s\t", Toy_private_getValueTypeAsCString(v.type), TOY_VALUE_AS_STRING(k)->name.data);
|
printf("%s\t%s\t", Toy_private_getValueTypeAsCString(v.type), k.leaf.data);
|
||||||
|
|
||||||
//print value
|
//print value
|
||||||
Toy_String* string = Toy_stringifyValue(&stringBucket, Toy_unwrapValue(v));
|
Toy_String* string = Toy_stringifyValue(&stringBucket, Toy_unwrapValue(v));
|
||||||
char* buffer = Toy_getStringRawBuffer(string);
|
char* buffer = Toy_getStringRaw(string);
|
||||||
printf("%s", buffer);
|
printf("%s", buffer);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
Toy_freeString(string);
|
Toy_freeString(string);
|
||||||
@@ -481,16 +480,14 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||||
unsigned char* buffer = Toy_compileModule(ast);
|
unsigned char* bytecode = Toy_compileToBytecode(ast);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
free(source);
|
free(source);
|
||||||
|
|
||||||
//run the compiled code
|
//run the compiled code
|
||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
Toy_initVM(&vm);
|
||||||
|
Toy_bindVM(&vm, bytecode, false);
|
||||||
Toy_Module module = Toy_parseModule(buffer);
|
|
||||||
Toy_bindVM(&vm, &module, false);
|
|
||||||
|
|
||||||
Toy_runVM(&vm);
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
@@ -502,7 +499,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_freeVM(&vm);
|
Toy_freeVM(&vm);
|
||||||
free(buffer);
|
free(bytecode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
repl(argv[0]);
|
repl(argv[0]);
|
||||||
|
|||||||
1
scripts/hello_world.toy
Normal file
1
scripts/hello_world.toy
Normal file
@@ -0,0 +1 @@
|
|||||||
|
print "Hello world";
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "toy_module_compiler.h"
|
#include "toy_compiler.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_opcodes.h"
|
#include "toy_opcodes.h"
|
||||||
@@ -43,7 +43,7 @@ Toy_private_EscapeArray* Toy_private_resizeEscapeArray(Toy_private_EscapeArray*
|
|||||||
ptr = (Toy_private_EscapeArray*)realloc(ptr, capacity * sizeof(Toy_private_EscapeEntry_t) + sizeof(Toy_private_EscapeArray));
|
ptr = (Toy_private_EscapeArray*)realloc(ptr, capacity * sizeof(Toy_private_EscapeEntry_t) + sizeof(Toy_private_EscapeArray));
|
||||||
|
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to resize an escape array within 'Toy_ModuleCompiler' from %d to %d capacity\n" TOY_CC_RESET, (int)originalCapacity, (int)capacity);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to resize an escape array within 'Toy_Bytecode' from %d to %d capacity\n" TOY_CC_RESET, (int)originalCapacity, (int)capacity);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ static void expand(unsigned char** handle, unsigned int* capacity, unsigned int*
|
|||||||
(*handle) = realloc((*handle), (*capacity));
|
(*handle) = realloc((*handle), (*capacity));
|
||||||
|
|
||||||
if ((*handle) == NULL) {
|
if ((*handle) == NULL) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate %d space for a part of 'Toy_ModuleCompiler'\n" TOY_CC_RESET, (int)(*capacity));
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate %d space for a part of 'Toy_Bytecode'\n" TOY_CC_RESET, (int)(*capacity));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ static unsigned int emitCStringToData(unsigned char** dataHandle, unsigned int*
|
|||||||
return addr; //return the address of the string in the data section
|
return addr; //return the address of the string in the data section
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int emitString(Toy_ModuleCompiler** mb, Toy_String* str) {
|
static unsigned int emitString(Toy_Bytecode** mb, Toy_String* str) {
|
||||||
//the address within the data section
|
//the address within the data section
|
||||||
unsigned int dataAddr = 0;
|
unsigned int dataAddr = 0;
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ static unsigned int emitString(Toy_ModuleCompiler** mb, Toy_String* str) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int emitParameters(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
|
static unsigned int emitParameters(Toy_Bytecode* mb, Toy_Ast* ast) {
|
||||||
//recursive checks
|
//recursive checks
|
||||||
if (ast == NULL) {
|
if (ast == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -211,12 +211,12 @@ static unsigned int emitParameters(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* ast); //forward declare for recursion
|
static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast); //forward declare for recursion
|
||||||
static void writeModuleCompilerBody(Toy_ModuleCompiler* mb, Toy_Ast* ast);
|
static void writeBytecodeBody(Toy_Bytecode* mb, Toy_Ast* ast);
|
||||||
static unsigned char* writeModuleCompilerResult(Toy_ModuleCompiler* mb);
|
static unsigned char* collateBytecodeBody(Toy_Bytecode* mb);
|
||||||
static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAssign ast, bool chainedAssignment); //forward declare for chaining of var declarations
|
static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment); //forward declare for chaining of var declarations
|
||||||
|
|
||||||
static unsigned int writeInstructionValue(Toy_ModuleCompiler** mb, Toy_AstValue ast) {
|
static unsigned int writeInstructionValue(Toy_Bytecode** mb, Toy_AstValue ast) {
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_READ);
|
EMIT_BYTE(mb, code, TOY_OPCODE_READ);
|
||||||
EMIT_BYTE(mb, code, ast.value.type);
|
EMIT_BYTE(mb, code, ast.value.type);
|
||||||
|
|
||||||
@@ -263,11 +263,11 @@ static unsigned int writeInstructionValue(Toy_ModuleCompiler** mb, Toy_AstValue
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionUnary(Toy_ModuleCompiler** mb, Toy_AstUnary ast) {
|
static unsigned int writeInstructionUnary(Toy_Bytecode** mb, Toy_AstUnary ast) {
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_NEGATE) {
|
if (ast.flag == TOY_AST_FLAG_NEGATE) {
|
||||||
result = writeModuleCompilerCode(mb, ast.child);
|
result = writeBytecodeFromAst(mb, ast.child);
|
||||||
|
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_NEGATE);
|
EMIT_BYTE(mb, code, TOY_OPCODE_NEGATE);
|
||||||
|
|
||||||
@@ -371,10 +371,10 @@ static unsigned int writeInstructionUnary(Toy_ModuleCompiler** mb, Toy_AstUnary
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionBinary(Toy_ModuleCompiler** mb, Toy_AstBinary ast) {
|
static unsigned int writeInstructionBinary(Toy_Bytecode** mb, Toy_AstBinary ast) {
|
||||||
//left, then right, then the binary's operation
|
//left, then right, then the binary's operation
|
||||||
writeModuleCompilerCode(mb, ast.left);
|
writeBytecodeFromAst(mb, ast.left);
|
||||||
writeModuleCompilerCode(mb, ast.right);
|
writeBytecodeFromAst(mb, ast.right);
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_ADD) {
|
if (ast.flag == TOY_AST_FLAG_ADD) {
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_ADD);
|
EMIT_BYTE(mb, code,TOY_OPCODE_ADD);
|
||||||
@@ -408,9 +408,9 @@ static unsigned int writeInstructionBinary(Toy_ModuleCompiler** mb, Toy_AstBinar
|
|||||||
return 1; //leaves only 1 value on the stack
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionBinaryShortCircuit(Toy_ModuleCompiler** mb, Toy_AstBinaryShortCircuit ast) {
|
static unsigned int writeInstructionBinaryShortCircuit(Toy_Bytecode** mb, Toy_AstBinaryShortCircuit ast) {
|
||||||
//lhs
|
//lhs
|
||||||
writeModuleCompilerCode(mb, ast.left);
|
writeBytecodeFromAst(mb, ast.left);
|
||||||
|
|
||||||
//duplicate the top (so the lhs can be 'returned' by this expression, if needed)
|
//duplicate the top (so the lhs can be 'returned' by this expression, if needed)
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_DUPLICATE);
|
EMIT_BYTE(mb, code,TOY_OPCODE_DUPLICATE);
|
||||||
@@ -449,7 +449,7 @@ static unsigned int writeInstructionBinaryShortCircuit(Toy_ModuleCompiler** mb,
|
|||||||
EMIT_BYTE(mb, code, 0);
|
EMIT_BYTE(mb, code, 0);
|
||||||
|
|
||||||
//rhs
|
//rhs
|
||||||
writeModuleCompilerCode(mb, ast.right);
|
writeBytecodeFromAst(mb, ast.right);
|
||||||
|
|
||||||
//set the parameter
|
//set the parameter
|
||||||
OVERWRITE_INT(mb, code, paramAddr, CURRENT_ADDRESS(mb, code) - (paramAddr + 4));
|
OVERWRITE_INT(mb, code, paramAddr, CURRENT_ADDRESS(mb, code) - (paramAddr + 4));
|
||||||
@@ -457,10 +457,10 @@ static unsigned int writeInstructionBinaryShortCircuit(Toy_ModuleCompiler** mb,
|
|||||||
return 1; //leaves only 1 value on the stack
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionCompare(Toy_ModuleCompiler** mb, Toy_AstCompare ast) {
|
static unsigned int writeInstructionCompare(Toy_Bytecode** mb, Toy_AstCompare ast) {
|
||||||
//left, then right, then the compare's operation
|
//left, then right, then the compare's operation
|
||||||
writeModuleCompilerCode(mb, ast.left);
|
writeBytecodeFromAst(mb, ast.left);
|
||||||
writeModuleCompilerCode(mb, ast.right);
|
writeBytecodeFromAst(mb, ast.right);
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_COMPARE_EQUAL) {
|
if (ast.flag == TOY_AST_FLAG_COMPARE_EQUAL) {
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_COMPARE_EQUAL);
|
EMIT_BYTE(mb, code,TOY_OPCODE_COMPARE_EQUAL);
|
||||||
@@ -499,13 +499,13 @@ static unsigned int writeInstructionCompare(Toy_ModuleCompiler** mb, Toy_AstComp
|
|||||||
return 1; //leaves only 1 value on the stack
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionGroup(Toy_ModuleCompiler** mb, Toy_AstGroup ast) {
|
static unsigned int writeInstructionGroup(Toy_Bytecode** mb, Toy_AstGroup ast) {
|
||||||
//not certain what this leaves
|
//not certain what this leaves
|
||||||
return writeModuleCompilerCode(mb, ast.child);
|
return writeBytecodeFromAst(mb, ast.child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionCompound(Toy_ModuleCompiler** mb, Toy_AstCompound ast) {
|
static unsigned int writeInstructionCompound(Toy_Bytecode** mb, Toy_AstCompound ast) {
|
||||||
unsigned int result = writeModuleCompilerCode(mb, ast.child);
|
unsigned int result = writeBytecodeFromAst(mb, ast.child);
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_COMPOUND_ARRAY) {
|
if (ast.flag == TOY_AST_FLAG_COMPOUND_ARRAY) {
|
||||||
//signal how many values to read in as array elements
|
//signal how many values to read in as array elements
|
||||||
@@ -542,12 +542,12 @@ static unsigned int writeInstructionCompound(Toy_ModuleCompiler** mb, Toy_AstCom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionAggregate(Toy_ModuleCompiler** mb, Toy_AstAggregate ast) {
|
static unsigned int writeInstructionAggregate(Toy_Bytecode** mb, Toy_AstAggregate ast) {
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
|
|
||||||
//left, then right
|
//left, then right
|
||||||
result += writeModuleCompilerCode(mb, ast.left);
|
result += writeBytecodeFromAst(mb, ast.left);
|
||||||
result += writeModuleCompilerCode(mb, ast.right);
|
result += writeBytecodeFromAst(mb, ast.right);
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_COLLECTION) {
|
if (ast.flag == TOY_AST_FLAG_COLLECTION) {
|
||||||
//collections are handled above
|
//collections are handled above
|
||||||
@@ -575,10 +575,10 @@ static unsigned int writeInstructionAggregate(Toy_ModuleCompiler** mb, Toy_AstAg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionAssert(Toy_ModuleCompiler** mb, Toy_AstAssert ast) {
|
static unsigned int writeInstructionAssert(Toy_Bytecode** mb, Toy_AstAssert ast) {
|
||||||
//the thing to print
|
//the thing to print
|
||||||
writeModuleCompilerCode(mb, ast.child);
|
writeBytecodeFromAst(mb, ast.child);
|
||||||
writeModuleCompilerCode(mb, ast.message);
|
writeBytecodeFromAst(mb, ast.message);
|
||||||
|
|
||||||
//output the print opcode
|
//output the print opcode
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_ASSERT);
|
EMIT_BYTE(mb, code, TOY_OPCODE_ASSERT);
|
||||||
@@ -591,9 +591,9 @@ static unsigned int writeInstructionAssert(Toy_ModuleCompiler** mb, Toy_AstAsser
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionIfThenElse(Toy_ModuleCompiler** mb, Toy_AstIfThenElse ast) {
|
static unsigned int writeInstructionIfThenElse(Toy_Bytecode** mb, Toy_AstIfThenElse ast) {
|
||||||
//cond-branch
|
//cond-branch
|
||||||
writeModuleCompilerCode(mb, ast.condBranch);
|
writeBytecodeFromAst(mb, ast.condBranch);
|
||||||
|
|
||||||
//emit the jump word (opcode, type, condition, padding)
|
//emit the jump word (opcode, type, condition, padding)
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
||||||
@@ -604,7 +604,7 @@ static unsigned int writeInstructionIfThenElse(Toy_ModuleCompiler** mb, Toy_AstI
|
|||||||
unsigned int thenParamAddr = SKIP_INT(mb, code); //parameter to be written later
|
unsigned int thenParamAddr = SKIP_INT(mb, code); //parameter to be written later
|
||||||
|
|
||||||
//emit then-branch
|
//emit then-branch
|
||||||
writeModuleCompilerCode(mb, ast.thenBranch);
|
writeBytecodeFromAst(mb, ast.thenBranch);
|
||||||
|
|
||||||
if (ast.elseBranch != NULL) {
|
if (ast.elseBranch != NULL) {
|
||||||
//emit the jump-to-end (opcode, type, condition, padding)
|
//emit the jump-to-end (opcode, type, condition, padding)
|
||||||
@@ -619,7 +619,7 @@ static unsigned int writeInstructionIfThenElse(Toy_ModuleCompiler** mb, Toy_AstI
|
|||||||
OVERWRITE_INT(mb, code, thenParamAddr, CURRENT_ADDRESS(mb, code) - (thenParamAddr + 4));
|
OVERWRITE_INT(mb, code, thenParamAddr, CURRENT_ADDRESS(mb, code) - (thenParamAddr + 4));
|
||||||
|
|
||||||
//emit the else branch
|
//emit the else branch
|
||||||
writeModuleCompilerCode(mb, ast.elseBranch);
|
writeBytecodeFromAst(mb, ast.elseBranch);
|
||||||
|
|
||||||
//specify the ending position for the else branch
|
//specify the ending position for the else branch
|
||||||
OVERWRITE_INT(mb, code, elseParamAddr, CURRENT_ADDRESS(mb, code) - (elseParamAddr + 4));
|
OVERWRITE_INT(mb, code, elseParamAddr, CURRENT_ADDRESS(mb, code) - (elseParamAddr + 4));
|
||||||
@@ -633,12 +633,12 @@ static unsigned int writeInstructionIfThenElse(Toy_ModuleCompiler** mb, Toy_AstI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionWhileThen(Toy_ModuleCompiler** mb, Toy_AstWhileThen ast) {
|
static unsigned int writeInstructionWhileThen(Toy_Bytecode** mb, Toy_AstWhileThen ast) {
|
||||||
//begin
|
//begin
|
||||||
unsigned int beginAddr = CURRENT_ADDRESS(mb, code);
|
unsigned int beginAddr = CURRENT_ADDRESS(mb, code);
|
||||||
|
|
||||||
//cond-branch
|
//cond-branch
|
||||||
writeModuleCompilerCode(mb, ast.condBranch);
|
writeBytecodeFromAst(mb, ast.condBranch);
|
||||||
|
|
||||||
//emit the jump word (opcode, type, condition, padding)
|
//emit the jump word (opcode, type, condition, padding)
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
||||||
@@ -649,7 +649,7 @@ static unsigned int writeInstructionWhileThen(Toy_ModuleCompiler** mb, Toy_AstWh
|
|||||||
unsigned int paramAddr = SKIP_INT(mb, code); //parameter to be written later
|
unsigned int paramAddr = SKIP_INT(mb, code); //parameter to be written later
|
||||||
|
|
||||||
//emit then-branch
|
//emit then-branch
|
||||||
writeModuleCompilerCode(mb, ast.thenBranch);
|
writeBytecodeFromAst(mb, ast.thenBranch);
|
||||||
|
|
||||||
//jump to begin to repeat the conditional test
|
//jump to begin to repeat the conditional test
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
EMIT_BYTE(mb, code, TOY_OPCODE_JUMP);
|
||||||
@@ -694,7 +694,7 @@ static unsigned int writeInstructionWhileThen(Toy_ModuleCompiler** mb, Toy_AstWh
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionBreak(Toy_ModuleCompiler** mb, Toy_AstBreak ast) {
|
static unsigned int writeInstructionBreak(Toy_Bytecode** mb, Toy_AstBreak ast) {
|
||||||
//unused
|
//unused
|
||||||
(void)ast;
|
(void)ast;
|
||||||
|
|
||||||
@@ -718,7 +718,7 @@ static unsigned int writeInstructionBreak(Toy_ModuleCompiler** mb, Toy_AstBreak
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionContinue(Toy_ModuleCompiler** mb, Toy_AstContinue ast) {
|
static unsigned int writeInstructionContinue(Toy_Bytecode** mb, Toy_AstContinue ast) {
|
||||||
//unused
|
//unused
|
||||||
(void)ast;
|
(void)ast;
|
||||||
|
|
||||||
@@ -742,9 +742,9 @@ static unsigned int writeInstructionContinue(Toy_ModuleCompiler** mb, Toy_AstCon
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionReturn(Toy_ModuleCompiler** mb, Toy_AstReturn ast) {
|
static unsigned int writeInstructionReturn(Toy_Bytecode** mb, Toy_AstReturn ast) {
|
||||||
//the things to return
|
//the things to return
|
||||||
unsigned int retCount = writeModuleCompilerCode(mb, ast.child);
|
unsigned int retCount = writeBytecodeFromAst(mb, ast.child);
|
||||||
|
|
||||||
//output the print opcode
|
//output the print opcode
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_RETURN);
|
EMIT_BYTE(mb, code,TOY_OPCODE_RETURN);
|
||||||
@@ -757,9 +757,9 @@ static unsigned int writeInstructionReturn(Toy_ModuleCompiler** mb, Toy_AstRetur
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionPrint(Toy_ModuleCompiler** mb, Toy_AstPrint ast) {
|
static unsigned int writeInstructionPrint(Toy_Bytecode** mb, Toy_AstPrint ast) {
|
||||||
//the thing to print
|
//the thing to print
|
||||||
writeModuleCompilerCode(mb, ast.child);
|
writeBytecodeFromAst(mb, ast.child);
|
||||||
|
|
||||||
//output the print opcode
|
//output the print opcode
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_PRINT);
|
EMIT_BYTE(mb, code,TOY_OPCODE_PRINT);
|
||||||
@@ -772,13 +772,13 @@ static unsigned int writeInstructionPrint(Toy_ModuleCompiler** mb, Toy_AstPrint
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionVarDeclare(Toy_ModuleCompiler** mb, Toy_AstVarDeclare ast) {
|
static unsigned int writeInstructionVarDeclare(Toy_Bytecode** mb, Toy_AstVarDeclare ast) {
|
||||||
//if we're dealing with chained assignments, hijack the next assignment with 'chainedAssignment' set to true
|
//if we're dealing with chained assignments, hijack the next assignment with 'chainedAssignment' set to true
|
||||||
if (checkForChaining(ast.expr)) {
|
if (checkForChaining(ast.expr)) {
|
||||||
writeInstructionAssign(mb, ast.expr->varAssign, true);
|
writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writeModuleCompilerCode(mb, ast.expr); //default value
|
writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
//delcare with the given name string
|
//delcare with the given name string
|
||||||
@@ -792,7 +792,7 @@ static unsigned int writeInstructionVarDeclare(Toy_ModuleCompiler** mb, Toy_AstV
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAssign ast, bool chainedAssignment) {
|
static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment) {
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
|
|
||||||
//target is a name string
|
//target is a name string
|
||||||
@@ -811,15 +811,15 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
|
|
||||||
//target is an indexing of some compound value
|
//target is an indexing of some compound value
|
||||||
else if (ast.target->type == TOY_AST_AGGREGATE && ast.target->aggregate.flag == TOY_AST_FLAG_INDEX) {
|
else if (ast.target->type == TOY_AST_AGGREGATE && ast.target->aggregate.flag == TOY_AST_FLAG_INDEX) {
|
||||||
writeModuleCompilerCode(mb, ast.target->aggregate.left); //any deeper indexing will just work, using reference values
|
writeBytecodeFromAst(mb, ast.target->aggregate.left); //any deeper indexing will just work, using reference values
|
||||||
writeModuleCompilerCode(mb, ast.target->aggregate.right); //key
|
writeBytecodeFromAst(mb, ast.target->aggregate.right); //key
|
||||||
|
|
||||||
//if we're dealing with chained assignments, hijack the next assignment with 'chainedAssignment' set to true
|
//if we're dealing with chained assignments, hijack the next assignment with 'chainedAssignment' set to true
|
||||||
if (checkForChaining(ast.expr)) {
|
if (checkForChaining(ast.expr)) {
|
||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_ASSIGN_COMPOUND); //uses the top three values on the stack
|
EMIT_BYTE(mb, code, TOY_OPCODE_ASSIGN_COMPOUND); //uses the top three values on the stack
|
||||||
@@ -844,7 +844,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_ASSIGN);
|
EMIT_BYTE(mb, code, TOY_OPCODE_ASSIGN);
|
||||||
@@ -863,7 +863,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_ADD);
|
EMIT_BYTE(mb, code,TOY_OPCODE_ADD);
|
||||||
@@ -882,7 +882,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_SUBTRACT);
|
EMIT_BYTE(mb, code,TOY_OPCODE_SUBTRACT);
|
||||||
@@ -901,7 +901,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_MULTIPLY);
|
EMIT_BYTE(mb, code,TOY_OPCODE_MULTIPLY);
|
||||||
@@ -920,7 +920,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_DIVIDE);
|
EMIT_BYTE(mb, code,TOY_OPCODE_DIVIDE);
|
||||||
@@ -939,7 +939,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
result += writeInstructionAssign(mb, ast.expr->varAssign, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result += writeModuleCompilerCode(mb, ast.expr); //default value
|
result += writeBytecodeFromAst(mb, ast.expr); //default value
|
||||||
}
|
}
|
||||||
|
|
||||||
EMIT_BYTE(mb, code,TOY_OPCODE_MODULO);
|
EMIT_BYTE(mb, code,TOY_OPCODE_MODULO);
|
||||||
@@ -956,7 +956,7 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
|
|||||||
return result + (chainedAssignment ? 1 : 0);
|
return result + (chainedAssignment ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionAccess(Toy_ModuleCompiler** mb, Toy_AstVarAccess ast) {
|
static unsigned int writeInstructionAccess(Toy_Bytecode** mb, Toy_AstVarAccess ast) {
|
||||||
if (!(ast.child->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.child->value.value))) {
|
if (!(ast.child->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.child->value.value))) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Found a non-name-string in a value node when trying to write access\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Found a non-name-string in a value node when trying to write access\n" TOY_CC_RESET);
|
||||||
(*mb)->panic = true;
|
(*mb)->panic = true;
|
||||||
@@ -982,7 +982,7 @@ static unsigned int writeInstructionAccess(Toy_ModuleCompiler** mb, Toy_AstVarAc
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFnDeclare ast) {
|
static unsigned int writeInstructionFnDeclare(Toy_Bytecode** mb, Toy_AstFnDeclare ast) {
|
||||||
/*
|
/*
|
||||||
FnDeclare: name, params, body
|
FnDeclare: name, params, body
|
||||||
|
|
||||||
@@ -1001,16 +1001,16 @@ static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFn
|
|||||||
.right->value.value.as.string.name (param4: any)
|
.right->value.value.as.string.name (param4: any)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//generate the submodule
|
//generate the subroutine
|
||||||
Toy_ModuleCompiler compiler = { 0 };
|
Toy_Bytecode compiler = { 0 };
|
||||||
|
|
||||||
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
|
|
||||||
//compile the ast to memory
|
//compile the ast to memory
|
||||||
unsigned int paramCount = emitParameters(&compiler, ast.params);
|
unsigned int paramCount = emitParameters(&compiler, ast.params);
|
||||||
writeModuleCompilerBody(&compiler, ast.body);
|
writeBytecodeBody(&compiler, ast.body);
|
||||||
unsigned char* submodule = writeModuleCompilerResult(&compiler);
|
unsigned char* subroutine = collateBytecodeBody(&compiler);
|
||||||
|
|
||||||
//cleanup the compiler
|
//cleanup the compiler
|
||||||
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);
|
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);
|
||||||
@@ -1022,10 +1022,10 @@ static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFn
|
|||||||
free(compiler.data);
|
free(compiler.data);
|
||||||
free(compiler.subs);
|
free(compiler.subs);
|
||||||
|
|
||||||
//write the submodule to the subs section
|
//write the subroutine to the subs section
|
||||||
unsigned int subsAddr = (*mb)->subsCount;
|
unsigned int subsAddr = (*mb)->subsCount;
|
||||||
emitBuffer(&((*mb)->subs), &((*mb)->subsCapacity), &((*mb)->subsCount), submodule, *((unsigned int*)submodule));
|
emitBuffer(&((*mb)->subs), &((*mb)->subsCapacity), &((*mb)->subsCount), subroutine, *((unsigned int*)subroutine));
|
||||||
free(submodule);
|
free(subroutine);
|
||||||
|
|
||||||
//read the function as a value, with the address as a parameter
|
//read the function as a value, with the address as a parameter
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_READ);
|
EMIT_BYTE(mb, code, TOY_OPCODE_READ);
|
||||||
@@ -1047,8 +1047,8 @@ static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFn
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionFnInvoke(Toy_ModuleCompiler** mb, Toy_AstFnInvoke ast) {
|
static unsigned int writeInstructionFnInvoke(Toy_Bytecode** mb, Toy_AstFnInvoke ast) {
|
||||||
unsigned int argCount = writeModuleCompilerCode(mb, ast.args);
|
unsigned int argCount = writeBytecodeFromAst(mb, ast.args);
|
||||||
|
|
||||||
if (argCount > 255) {
|
if (argCount > 255) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid function invokation with %d functions arguments (maximum 255)\n" TOY_CC_RESET, (int)argCount);
|
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid function invokation with %d functions arguments (maximum 255)\n" TOY_CC_RESET, (int)argCount);
|
||||||
@@ -1056,7 +1056,7 @@ static unsigned int writeInstructionFnInvoke(Toy_ModuleCompiler** mb, Toy_AstFnI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int fnCount = writeModuleCompilerCode(mb, ast.function);
|
unsigned int fnCount = writeBytecodeFromAst(mb, ast.function);
|
||||||
|
|
||||||
if (fnCount != 1) {
|
if (fnCount != 1) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid function invokation with %d function AST nodes (expected 1)\n" TOY_CC_RESET, (int)fnCount);
|
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Invalid function invokation with %d function AST nodes (expected 1)\n" TOY_CC_RESET, (int)fnCount);
|
||||||
@@ -1073,7 +1073,7 @@ static unsigned int writeInstructionFnInvoke(Toy_ModuleCompiler** mb, Toy_AstFnI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* ast) {
|
static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
|
||||||
if (ast == NULL) {
|
if (ast == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1098,8 +1098,8 @@ static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* as
|
|||||||
(*mb)->currentScopeDepth++;
|
(*mb)->currentScopeDepth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
result += writeModuleCompilerCode(mb, ast->block.child);
|
result += writeBytecodeFromAst(mb, ast->block.child);
|
||||||
result += writeModuleCompilerCode(mb, ast->block.next);
|
result += writeBytecodeFromAst(mb, ast->block.next);
|
||||||
|
|
||||||
if (ast->block.innerScope) {
|
if (ast->block.innerScope) {
|
||||||
EMIT_BYTE(mb, code, TOY_OPCODE_SCOPE_POP);
|
EMIT_BYTE(mb, code, TOY_OPCODE_SCOPE_POP);
|
||||||
@@ -1210,10 +1210,10 @@ static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* as
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeModuleCompilerBody(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
|
static void writeBytecodeBody(Toy_Bytecode* mb, Toy_Ast* ast) {
|
||||||
//this is separated from 'writeModuleCompilerResult', to separate the concerns for modules & functions
|
//this is separated from 'collateBytecodeBody', to separate the concerns for bytecode & functions
|
||||||
|
|
||||||
writeModuleCompilerCode(&mb, ast);
|
writeBytecodeFromAst(&mb, ast);
|
||||||
|
|
||||||
EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator
|
EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator
|
||||||
EMIT_BYTE(&mb, code, 0); //4-byte alignment
|
EMIT_BYTE(&mb, code, 0); //4-byte alignment
|
||||||
@@ -1221,7 +1221,7 @@ static void writeModuleCompilerBody(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
|
|||||||
EMIT_BYTE(&mb, code, 0);
|
EMIT_BYTE(&mb, code, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* writeModuleCompilerResult(Toy_ModuleCompiler* mb) {
|
static unsigned char* collateBytecodeBody(Toy_Bytecode* mb) {
|
||||||
//if an error occurred, just exit
|
//if an error occurred, just exit
|
||||||
if (mb->panic) {
|
if (mb->panic) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1312,16 +1312,16 @@ static unsigned char* writeModuleCompilerResult(Toy_ModuleCompiler* mb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
unsigned char* Toy_compileModule(Toy_Ast* ast) {
|
unsigned char* Toy_compileToBytecode(Toy_Ast* ast) {
|
||||||
//setup
|
//setup
|
||||||
Toy_ModuleCompiler compiler = { 0 };
|
Toy_Bytecode compiler = { 0 };
|
||||||
|
|
||||||
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
|
||||||
|
|
||||||
//compile the ast to memory
|
//compile the ast to memory
|
||||||
writeModuleCompilerBody(&compiler, ast);
|
writeBytecodeBody(&compiler, ast);
|
||||||
unsigned char* buffer = writeModuleCompilerResult(&compiler);
|
unsigned char* buffer = collateBytecodeBody(&compiler);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);
|
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);
|
||||||
@@ -26,8 +26,8 @@ typedef struct Toy_private_EscapeArray {
|
|||||||
|
|
||||||
TOY_API Toy_private_EscapeArray* Toy_private_resizeEscapeArray(Toy_private_EscapeArray* ptr, unsigned int capacity);
|
TOY_API Toy_private_EscapeArray* Toy_private_resizeEscapeArray(Toy_private_EscapeArray* ptr, unsigned int capacity);
|
||||||
|
|
||||||
//structure for holding the module as it is built
|
//structure for holding the bytecode during compilation
|
||||||
typedef struct Toy_ModuleCompiler {
|
typedef struct Toy_Bytecode {
|
||||||
unsigned char* code; //the instruction set
|
unsigned char* code; //the instruction set
|
||||||
unsigned int codeCapacity;
|
unsigned int codeCapacity;
|
||||||
unsigned int codeCount;
|
unsigned int codeCount;
|
||||||
@@ -44,7 +44,7 @@ typedef struct Toy_ModuleCompiler {
|
|||||||
unsigned int dataCapacity;
|
unsigned int dataCapacity;
|
||||||
unsigned int dataCount;
|
unsigned int dataCount;
|
||||||
|
|
||||||
unsigned char* subs; //submodules, built recursively
|
unsigned char* subs; //subroutines etc, built recursively
|
||||||
unsigned int subsCapacity;
|
unsigned int subsCapacity;
|
||||||
unsigned int subsCount;
|
unsigned int subsCount;
|
||||||
|
|
||||||
@@ -57,6 +57,6 @@ typedef struct Toy_ModuleCompiler {
|
|||||||
|
|
||||||
//compilation errors
|
//compilation errors
|
||||||
bool panic;
|
bool panic;
|
||||||
} Toy_ModuleCompiler;
|
} Toy_Bytecode;
|
||||||
|
|
||||||
TOY_API unsigned char* Toy_compileModule(Toy_Ast* ast);
|
TOY_API unsigned char* Toy_compileToBytecode(Toy_Ast* ast);
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "toy_function.h"
|
#include "toy_function.h"
|
||||||
|
|
||||||
Toy_Function* Toy_createModuleFunction(Toy_Bucket** bucketHandle, Toy_Module module) {
|
Toy_Function* Toy_createFunctionFromBytecode(Toy_Bucket** bucketHandle, unsigned char* bytecode) {
|
||||||
Toy_Function* fn = (Toy_Function*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Function));
|
Toy_Function* fn = (Toy_Function*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Function));
|
||||||
|
|
||||||
fn->type = TOY_FUNCTION_MODULE;
|
fn->type = TOY_FUNCTION_CUSTOM;
|
||||||
fn->module.module = module;
|
fn->bytecode.code = bytecode;
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
|
#include "toy_bucket.h"
|
||||||
#include "toy_module.h"
|
|
||||||
|
|
||||||
typedef enum Toy_FunctionType {
|
typedef enum Toy_FunctionType {
|
||||||
TOY_FUNCTION_MODULE,
|
TOY_FUNCTION_CUSTOM,
|
||||||
TOY_FUNCTION_NATIVE,
|
TOY_FUNCTION_NATIVE,
|
||||||
} Toy_FunctionType;
|
} Toy_FunctionType;
|
||||||
|
|
||||||
typedef struct Toy_FunctionModule {
|
typedef struct Toy_FunctionBytecode {
|
||||||
Toy_FunctionType type;
|
Toy_FunctionType type;
|
||||||
Toy_Module module;
|
unsigned char* code;
|
||||||
} Toy_FunctionModule;
|
} Toy_FunctionBytecode;
|
||||||
|
|
||||||
typedef struct Toy_FunctionNative {
|
typedef struct Toy_FunctionNative {
|
||||||
Toy_FunctionType type;
|
Toy_FunctionType type;
|
||||||
@@ -21,8 +20,8 @@ typedef struct Toy_FunctionNative {
|
|||||||
|
|
||||||
typedef union Toy_Function_t {
|
typedef union Toy_Function_t {
|
||||||
Toy_FunctionType type;
|
Toy_FunctionType type;
|
||||||
Toy_FunctionModule module;
|
Toy_FunctionBytecode bytecode;
|
||||||
Toy_FunctionNative native;
|
Toy_FunctionNative native;
|
||||||
} Toy_Function;
|
} Toy_Function;
|
||||||
|
|
||||||
TOY_API Toy_Function* Toy_createModuleFunction(Toy_Bucket** bucketHandle, Toy_Module module);
|
TOY_API Toy_Function* Toy_createFunctionFromBytecode(Toy_Bucket** bucketHandle, unsigned char* bytecode);
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
#include "toy_module.h"
|
|
||||||
#include "toy_console_colors.h"
|
|
||||||
|
|
||||||
static inline unsigned int readUnsignedInt(unsigned char** handle) {
|
|
||||||
unsigned int i = *((unsigned int*)(*handle));
|
|
||||||
(*handle) += 4;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_Module Toy_parseModule(unsigned char* ptr) {
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return (Toy_Module){ 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_Module module;
|
|
||||||
|
|
||||||
module.parentScope = NULL;
|
|
||||||
|
|
||||||
module.code = ptr;
|
|
||||||
|
|
||||||
//header
|
|
||||||
readUnsignedInt(&ptr);
|
|
||||||
|
|
||||||
module.jumpsCount = readUnsignedInt(&ptr);
|
|
||||||
module.paramCount = readUnsignedInt(&ptr);
|
|
||||||
module.dataCount = readUnsignedInt(&ptr);
|
|
||||||
module.subsCount = readUnsignedInt(&ptr);
|
|
||||||
|
|
||||||
module.codeAddr = readUnsignedInt(&ptr);
|
|
||||||
if (module.jumpsCount) {
|
|
||||||
module.jumpsAddr = readUnsignedInt(&ptr);
|
|
||||||
}
|
|
||||||
if (module.paramCount) {
|
|
||||||
module.paramAddr = readUnsignedInt(&ptr);
|
|
||||||
}
|
|
||||||
if (module.dataCount) {
|
|
||||||
module.dataAddr = readUnsignedInt(&ptr);
|
|
||||||
}
|
|
||||||
if (module.subsCount) {
|
|
||||||
module.subsAddr = readUnsignedInt(&ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "toy_common.h"
|
|
||||||
#include "toy_scope.h"
|
|
||||||
|
|
||||||
//runtime module info
|
|
||||||
typedef struct Toy_Module {
|
|
||||||
//closure support - points to parent scope
|
|
||||||
Toy_Scope* parentScope;
|
|
||||||
|
|
||||||
unsigned char* code;
|
|
||||||
|
|
||||||
//extracted metadata
|
|
||||||
// unsigned int codeCount; //NOTE: not used
|
|
||||||
unsigned int jumpsCount;
|
|
||||||
unsigned int paramCount;
|
|
||||||
unsigned int dataCount;
|
|
||||||
unsigned int subsCount;
|
|
||||||
|
|
||||||
unsigned int codeAddr;
|
|
||||||
unsigned int jumpsAddr;
|
|
||||||
unsigned int paramAddr;
|
|
||||||
unsigned int dataAddr;
|
|
||||||
unsigned int subsAddr;
|
|
||||||
} Toy_Module;
|
|
||||||
|
|
||||||
TOY_API Toy_Module Toy_parseModule(unsigned char* ptr);
|
|
||||||
@@ -430,19 +430,17 @@ int Toy_compareValues(Toy_Value left, Toy_Value right) {
|
|||||||
Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
||||||
MAYBE_UNWRAP(value);
|
MAYBE_UNWRAP(value);
|
||||||
|
|
||||||
//TODO: could have "constant" strings that can be referenced, instead of null, true, false, etc. - new string type of 'permanent'
|
|
||||||
|
|
||||||
switch(value.type) {
|
switch(value.type) {
|
||||||
case TOY_VALUE_NULL:
|
case TOY_VALUE_NULL:
|
||||||
return Toy_createString(bucketHandle, "<null>"); //TODO: remake "createString" to to handle params like this
|
return Toy_toString(bucketHandle, "<null>");
|
||||||
|
|
||||||
case TOY_VALUE_BOOLEAN:
|
case TOY_VALUE_BOOLEAN:
|
||||||
return Toy_createString(bucketHandle, value.as.boolean ? "<true>" : "<false>");
|
return Toy_toString(bucketHandle, value.as.boolean ? "<true>" : "<false>");
|
||||||
|
|
||||||
case TOY_VALUE_INTEGER: {
|
case TOY_VALUE_INTEGER: {
|
||||||
char buffer[16];
|
char buffer[16];
|
||||||
sprintf(buffer, "%d", value.as.integer);
|
sprintf(buffer, "%d", value.as.integer);
|
||||||
return Toy_createString(bucketHandle, buffer);
|
return Toy_toString(bucketHandle, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOY_VALUE_FLOAT: {
|
case TOY_VALUE_FLOAT: {
|
||||||
@@ -463,7 +461,7 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
|||||||
//wipe the trailing zeros
|
//wipe the trailing zeros
|
||||||
while(decimal != length && buffer[length-1] == '0') buffer[--length] = '\0';
|
while(decimal != length && buffer[length-1] == '0') buffer[--length] = '\0';
|
||||||
|
|
||||||
return Toy_createStringLength(bucketHandle, buffer, length);
|
return Toy_toStringLength(bucketHandle, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOY_VALUE_STRING:
|
case TOY_VALUE_STRING:
|
||||||
@@ -475,14 +473,14 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
|||||||
|
|
||||||
//if array is empty, skip below
|
//if array is empty, skip below
|
||||||
if (ptr->count == 0) {
|
if (ptr->count == 0) {
|
||||||
Toy_String* empty = Toy_createString(bucketHandle, "[]");
|
Toy_String* empty = Toy_toString(bucketHandle, "[]");
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_String* open = Toy_createStringLength(bucketHandle, "[", 1);
|
Toy_String* open = Toy_toStringLength(bucketHandle, "[", 1);
|
||||||
Toy_String* close = Toy_createStringLength(bucketHandle, "]", 1);
|
Toy_String* close = Toy_toStringLength(bucketHandle, "]", 1);
|
||||||
Toy_String* comma = Toy_createStringLength(bucketHandle, ",", 1); //reusable
|
Toy_String* comma = Toy_toStringLength(bucketHandle, ",", 1); //reusable
|
||||||
Toy_String* quote = Toy_createStringLength(bucketHandle, "\"", 1); //reusable
|
Toy_String* quote = Toy_toStringLength(bucketHandle, "\"", 1); //reusable
|
||||||
bool needsComma = false;
|
bool needsComma = false;
|
||||||
|
|
||||||
Toy_String* string = open;
|
Toy_String* string = open;
|
||||||
@@ -538,15 +536,15 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
|||||||
|
|
||||||
//if table is empty, skip below
|
//if table is empty, skip below
|
||||||
if (ptr->count == 0) {
|
if (ptr->count == 0) {
|
||||||
Toy_String* empty = Toy_createString(bucketHandle, "[:]");
|
Toy_String* empty = Toy_toString(bucketHandle, "[:]");
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_String* open = Toy_createStringLength(bucketHandle, "[", 1);
|
Toy_String* open = Toy_toStringLength(bucketHandle, "[", 1);
|
||||||
Toy_String* close = Toy_createStringLength(bucketHandle, "]", 1);
|
Toy_String* close = Toy_toStringLength(bucketHandle, "]", 1);
|
||||||
Toy_String* colon = Toy_createStringLength(bucketHandle, ":", 1); //reusable
|
Toy_String* colon = Toy_toStringLength(bucketHandle, ":", 1); //reusable
|
||||||
Toy_String* comma = Toy_createStringLength(bucketHandle, ",", 1); //reusable
|
Toy_String* comma = Toy_toStringLength(bucketHandle, ",", 1); //reusable
|
||||||
Toy_String* quote = Toy_createStringLength(bucketHandle, "\"", 1); //reusable
|
Toy_String* quote = Toy_toStringLength(bucketHandle, "\"", 1); //reusable
|
||||||
bool needsComma = false;
|
bool needsComma = false;
|
||||||
|
|
||||||
Toy_String* string = open;
|
Toy_String* string = open;
|
||||||
@@ -626,7 +624,7 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
|||||||
|
|
||||||
case TOY_VALUE_FUNCTION:
|
case TOY_VALUE_FUNCTION:
|
||||||
//dummy
|
//dummy
|
||||||
return Toy_createString(bucketHandle, "<fn>");
|
return Toy_toString(bucketHandle, "<fn>");
|
||||||
|
|
||||||
case TOY_VALUE_OPAQUE:
|
case TOY_VALUE_OPAQUE:
|
||||||
case TOY_VALUE_ANY:
|
case TOY_VALUE_ANY:
|
||||||
|
|||||||
131
source/toy_vm.c
131
source/toy_vm.c
@@ -73,12 +73,7 @@ static void processRead(Toy_VM* vm) {
|
|||||||
|
|
||||||
//build a string from the data section
|
//build a string from the data section
|
||||||
if (stringType == TOY_STRING_LEAF) {
|
if (stringType == TOY_STRING_LEAF) {
|
||||||
value = TOY_VALUE_FROM_STRING(Toy_createString(&vm->memoryBucket, cstring));
|
value = TOY_VALUE_FROM_STRING(Toy_toStringLength(&vm->memoryBucket, cstring, len));
|
||||||
}
|
|
||||||
else if (stringType == TOY_STRING_NAME) {
|
|
||||||
Toy_ValueType valueType = TOY_VALUE_UNKNOWN;
|
|
||||||
|
|
||||||
value = TOY_VALUE_FROM_STRING(Toy_createNameStringLength(&vm->memoryBucket, cstring, len, valueType, false));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Toy_error("Invalid string type found in opcode read");
|
Toy_error("Invalid string type found in opcode read");
|
||||||
@@ -161,11 +156,8 @@ static void processRead(Toy_VM* vm) {
|
|||||||
|
|
||||||
unsigned int addr = (unsigned int)READ_INT(vm);
|
unsigned int addr = (unsigned int)READ_INT(vm);
|
||||||
|
|
||||||
Toy_Module module = Toy_parseModule(vm->code + vm->subsAddr + addr);
|
|
||||||
module.parentScope = Toy_private_pushDummyScope(&vm->memoryBucket, vm->scope);
|
|
||||||
|
|
||||||
//create and push the function value
|
//create and push the function value
|
||||||
Toy_Function* function = Toy_createModuleFunction(&vm->memoryBucket, module);
|
Toy_Function* function = Toy_createFunctionFromBytecode(&vm->memoryBucket, vm->code + vm->subsAddr + addr);
|
||||||
value = TOY_VALUE_FROM_FUNCTION(function);
|
value = TOY_VALUE_FROM_FUNCTION(function);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -210,7 +202,7 @@ static void processDeclare(Toy_VM* vm) {
|
|||||||
char* cstring = (char*)(vm->code + vm->dataAddr + jump);
|
char* cstring = (char*)(vm->code + vm->dataAddr + jump);
|
||||||
|
|
||||||
//build the name string
|
//build the name string
|
||||||
Toy_String* name = Toy_createNameStringLength(&vm->memoryBucket, cstring, len, type, constant);
|
Toy_String* name = Toy_toStringLength(&vm->memoryBucket, cstring, len);
|
||||||
|
|
||||||
//get the value
|
//get the value
|
||||||
Toy_Value value = Toy_popStack(&vm->stack);
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
@@ -221,7 +213,7 @@ static void processDeclare(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//declare it
|
//declare it
|
||||||
Toy_declareScope(vm->scope, name, value);
|
Toy_declareScope(vm->scope, name, type, value, constant);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_freeString(name);
|
Toy_freeString(name);
|
||||||
@@ -232,18 +224,20 @@ static void processAssign(Toy_VM* vm) {
|
|||||||
Toy_Value value = Toy_popStack(&vm->stack);
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
Toy_Value name = Toy_popStack(&vm->stack);
|
Toy_Value name = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
//check name string type
|
//TODO: remove 'TOY_STRING_NAME' entirely
|
||||||
if (!TOY_VALUE_IS_STRING(name) || TOY_VALUE_AS_STRING(name)->info.type != TOY_STRING_NAME) {
|
// //check name string type
|
||||||
Toy_error("Invalid assignment target");
|
// if (!TOY_VALUE_IS_STRING(name) || TOY_VALUE_AS_STRING(name)->info.type != TOY_STRING_NAME) {
|
||||||
Toy_freeValue(name);
|
// Toy_error("Invalid assignment target");
|
||||||
Toy_freeValue(value);
|
// Toy_freeValue(name);
|
||||||
return;
|
// Toy_freeValue(value);
|
||||||
}
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
//BUGFIX: only allowable type coersion
|
// //FIXME
|
||||||
if (TOY_VALUE_AS_STRING(name)->name.varType == TOY_VALUE_FLOAT && value.type == TOY_VALUE_INTEGER) {
|
// //BUGFIX: only allowable type coersion
|
||||||
value = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(value) );
|
// if (TOY_VALUE_AS_STRING(name)->name.varType == TOY_VALUE_FLOAT && value.type == TOY_VALUE_INTEGER) {
|
||||||
}
|
// value = TOY_VALUE_FROM_FLOAT( (float)TOY_VALUE_AS_INTEGER(value) );
|
||||||
|
// }
|
||||||
|
|
||||||
//assign it
|
//assign it
|
||||||
Toy_assignScope(vm->scope, TOY_VALUE_AS_STRING(name), value); //scope now owns the value, doesn't need to be freed
|
Toy_assignScope(vm->scope, TOY_VALUE_AS_STRING(name), value); //scope now owns the value, doesn't need to be freed
|
||||||
@@ -265,7 +259,7 @@ static void processAssignCompound(Toy_VM* vm) {
|
|||||||
Toy_Value target = Toy_popStack(&vm->stack);
|
Toy_Value target = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
//shake out variable names
|
//shake out variable names
|
||||||
if (TOY_VALUE_IS_STRING(target) && TOY_VALUE_AS_STRING(target)->info.type == TOY_STRING_NAME) {
|
if (TOY_VALUE_IS_STRING(target)) {
|
||||||
Toy_Value* valuePtr = Toy_accessScopeAsPointer(vm->scope, TOY_VALUE_AS_STRING(target));
|
Toy_Value* valuePtr = Toy_accessScopeAsPointer(vm->scope, TOY_VALUE_AS_STRING(target));
|
||||||
Toy_freeValue(target);
|
Toy_freeValue(target);
|
||||||
if (valuePtr == NULL) {
|
if (valuePtr == NULL) {
|
||||||
@@ -344,12 +338,12 @@ static void processAssignCompound(Toy_VM* vm) {
|
|||||||
static void processAccess(Toy_VM* vm) {
|
static void processAccess(Toy_VM* vm) {
|
||||||
Toy_Value name = Toy_popStack(&vm->stack);
|
Toy_Value name = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
//check name string type
|
// //check name string type
|
||||||
if (!TOY_VALUE_IS_STRING(name) || TOY_VALUE_AS_STRING(name)->info.type != TOY_STRING_NAME) {
|
// if (!TOY_VALUE_IS_STRING(name) || TOY_VALUE_AS_STRING(name)->info.type != TOY_STRING_NAME) {
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
// Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
||||||
Toy_error("Invalid access target");
|
// Toy_error("Invalid access target");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//find the value
|
//find the value
|
||||||
Toy_Value* valuePtr = Toy_accessScopeAsPointer(vm->scope, TOY_VALUE_AS_STRING(name));
|
Toy_Value* valuePtr = Toy_accessScopeAsPointer(vm->scope, TOY_VALUE_AS_STRING(name));
|
||||||
@@ -397,13 +391,14 @@ static void processInvoke(Toy_VM* vm) {
|
|||||||
Toy_Function* fn = TOY_VALUE_AS_FUNCTION(value);
|
Toy_Function* fn = TOY_VALUE_AS_FUNCTION(value);
|
||||||
|
|
||||||
switch(fn->type) {
|
switch(fn->type) {
|
||||||
case TOY_FUNCTION_MODULE: {
|
case TOY_FUNCTION_CUSTOM: {
|
||||||
Toy_Module module = fn->module.module;
|
//spin up a new sub-vm
|
||||||
|
Toy_VM subVM;
|
||||||
//NOTE: counts within the modules actually specify size in memory, so the argCount is multiplied by 8 for the 8 bytes used in the params table
|
Toy_inheritVM(&subVM, vm);
|
||||||
|
Toy_bindVM(&subVM, fn->bytecode.code, false);
|
||||||
|
|
||||||
//check args count
|
//check args count
|
||||||
if (argCount * 8 != module.paramCount) {
|
if (argCount * 8 != subVM.paramCount) {
|
||||||
Toy_error("Incorrect number of parameters specified for function call");
|
Toy_error("Incorrect number of parameters specified for function call");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -413,26 +408,21 @@ static void processInvoke(Toy_VM* vm) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//spin up a new sub-vm
|
|
||||||
Toy_VM subVM;
|
|
||||||
Toy_inheritVM(&subVM, vm);
|
|
||||||
Toy_bindVM(&subVM, &module, false);
|
|
||||||
|
|
||||||
//inject params, backwards from the stack
|
//inject params, backwards from the stack
|
||||||
for (unsigned int i = argCount; i > 0; i--) {
|
for (unsigned int i = argCount; i > 0; i--) {
|
||||||
Toy_Value argValue = Toy_popStack(&vm->stack);
|
Toy_Value argValue = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
//paramAddr is relative to the data section, and is followed by the param type
|
//paramAddr is relative to the data section, and is followed by the param type
|
||||||
unsigned int paramAddr = ((unsigned int*)(module.code + module.paramAddr))[(i-1)*2];
|
unsigned int paramAddr = ((unsigned int*)(subVM.code + subVM.paramAddr))[(i-1)*2];
|
||||||
Toy_ValueType paramType = (Toy_ValueType)(((unsigned int*)(module.code + module.paramAddr))[(i-1)*2 + 1]);
|
Toy_ValueType paramType = (Toy_ValueType)(((unsigned int*)(subVM.code + subVM.paramAddr))[(i-1)*2 + 1]);
|
||||||
|
|
||||||
//c-string of the param's name
|
//c-string of the param's name
|
||||||
const char* cstr = ((char*)(module.code + module.dataAddr)) + paramAddr;
|
const char* cstr = ((char*)(subVM.code + subVM.dataAddr)) + paramAddr;
|
||||||
|
|
||||||
//as a name string
|
//as a name string
|
||||||
Toy_String* name = Toy_createNameStringLength(&subVM.memoryBucket, cstr, strlen(cstr), paramType, true);
|
Toy_String* name = Toy_toStringLength(&subVM.memoryBucket, cstr, strlen(cstr));
|
||||||
|
|
||||||
Toy_declareScope(subVM.scope, name, argValue);
|
Toy_declareScope(subVM.scope, name, paramType, argValue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//run
|
//run
|
||||||
@@ -723,7 +713,7 @@ static void processAssert(Toy_VM* vm) {
|
|||||||
|
|
||||||
//determine the args
|
//determine the args
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
message = TOY_VALUE_FROM_STRING(Toy_createString(&vm->memoryBucket, "assertion failed")); //TODO: needs a better default message
|
message = TOY_VALUE_FROM_STRING(Toy_toString(&vm->memoryBucket, "assertion failed")); //TODO: needs a better default message
|
||||||
value = Toy_popStack(&vm->stack);
|
value = Toy_popStack(&vm->stack);
|
||||||
}
|
}
|
||||||
else if (count == 2) {
|
else if (count == 2) {
|
||||||
@@ -739,7 +729,7 @@ static void processAssert(Toy_VM* vm) {
|
|||||||
if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) != true) {
|
if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) != true) {
|
||||||
//on a failure, print the message
|
//on a failure, print the message
|
||||||
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, message);
|
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, message);
|
||||||
char* buffer = Toy_getStringRawBuffer(string);
|
char* buffer = Toy_getStringRaw(string);
|
||||||
|
|
||||||
Toy_assertFailure(buffer);
|
Toy_assertFailure(buffer);
|
||||||
|
|
||||||
@@ -757,7 +747,7 @@ static void processPrint(Toy_VM* vm) {
|
|||||||
//print the value on top of the stack, popping it
|
//print the value on top of the stack, popping it
|
||||||
Toy_Value value = Toy_popStack(&vm->stack);
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value);
|
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value);
|
||||||
char* buffer = Toy_getStringRawBuffer(string); //TODO: check string type to skip this call
|
char* buffer = Toy_getStringRaw(string); //TODO: check string type to skip this call
|
||||||
|
|
||||||
Toy_print(buffer);
|
Toy_print(buffer);
|
||||||
|
|
||||||
@@ -847,11 +837,11 @@ static void processIndex(Toy_VM* vm) {
|
|||||||
//extract cstring, based on type
|
//extract cstring, based on type
|
||||||
if (str->info.type == TOY_STRING_LEAF) {
|
if (str->info.type == TOY_STRING_LEAF) {
|
||||||
const char* cstr = str->leaf.data;
|
const char* cstr = str->leaf.data;
|
||||||
result = Toy_createStringLength(&vm->memoryBucket, cstr + i, l);
|
result = Toy_toStringLength(&vm->memoryBucket, cstr + i, l);
|
||||||
}
|
}
|
||||||
else if (str->info.type == TOY_STRING_NODE) {
|
else if (str->info.type == TOY_STRING_NODE) {
|
||||||
char* cstr = Toy_getStringRawBuffer(str);
|
char* cstr = Toy_getStringRaw(str);
|
||||||
result = Toy_createStringLength(&vm->memoryBucket, cstr + i, l);
|
result = Toy_toStringLength(&vm->memoryBucket, cstr + i, l);
|
||||||
free(cstr);
|
free(cstr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1113,28 +1103,41 @@ void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent) {
|
|||||||
Toy_resetVM(vm, true);
|
Toy_resetVM(vm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope) {
|
void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, bool preserveScope) {
|
||||||
vm->code = module->code;
|
vm->code = bytecode; //set code, so it can be read
|
||||||
|
|
||||||
vm->jumpsCount = module->jumpsCount;
|
(void)READ_UNSIGNED_INT(vm); //global header
|
||||||
vm->paramCount = module->paramCount;
|
|
||||||
vm->dataCount = module->dataCount;
|
|
||||||
vm->subsCount = module->subsCount;
|
|
||||||
|
|
||||||
vm->codeAddr = module->codeAddr;
|
//section headers
|
||||||
vm->jumpsAddr = module->jumpsAddr;
|
vm->jumpsCount = READ_UNSIGNED_INT(vm);
|
||||||
vm->paramAddr = module->paramAddr;
|
vm->paramCount = READ_UNSIGNED_INT(vm);
|
||||||
vm->dataAddr = module->dataAddr;
|
vm->dataCount = READ_UNSIGNED_INT(vm);
|
||||||
vm->subsAddr = module->subsAddr;
|
vm->subsCount = READ_UNSIGNED_INT(vm);
|
||||||
|
|
||||||
|
//section locations
|
||||||
|
vm->codeAddr = READ_UNSIGNED_INT(vm);
|
||||||
|
if (vm->jumpsCount) {
|
||||||
|
vm->jumpsAddr = READ_UNSIGNED_INT(vm);
|
||||||
|
}
|
||||||
|
if (vm->paramCount) {
|
||||||
|
vm->paramAddr = READ_UNSIGNED_INT(vm);
|
||||||
|
}
|
||||||
|
if (vm->dataCount) {
|
||||||
|
vm->dataAddr = READ_UNSIGNED_INT(vm);
|
||||||
|
}
|
||||||
|
if (vm->subsCount) {
|
||||||
|
vm->subsAddr = READ_UNSIGNED_INT(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//scopes
|
||||||
if (preserveScope == false) {
|
if (preserveScope == false) {
|
||||||
vm->scope = Toy_pushScope(&vm->memoryBucket, module->parentScope);
|
vm->scope = Toy_pushScope(&vm->memoryBucket, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Toy_runVM(Toy_VM* vm) {
|
unsigned int Toy_runVM(Toy_VM* vm) {
|
||||||
if (vm->codeAddr == 0) {
|
if (vm->codeAddr == 0) {
|
||||||
//ignore uninitialized VMs or empty modules
|
//ignore uninitialized VMs or empty bytecode
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "toy_bucket.h"
|
#include "toy_bucket.h"
|
||||||
#include "toy_scope.h"
|
#include "toy_scope.h"
|
||||||
#include "toy_module.h"
|
|
||||||
|
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
#include "toy_string.h"
|
#include "toy_string.h"
|
||||||
@@ -48,7 +47,7 @@ TOY_API void Toy_resetVM(Toy_VM* vm, bool preserveScope);
|
|||||||
TOY_API void Toy_initVM(Toy_VM* vm); //creates memory
|
TOY_API void Toy_initVM(Toy_VM* vm); //creates memory
|
||||||
TOY_API void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent); //inherits scope bucket
|
TOY_API void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent); //inherits scope bucket
|
||||||
|
|
||||||
TOY_API void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope);
|
void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, bool preserveScope);
|
||||||
TOY_API unsigned int Toy_runVM(Toy_VM* vm);
|
TOY_API unsigned int Toy_runVM(Toy_VM* vm);
|
||||||
TOY_API void Toy_freeVM(Toy_VM* vm);
|
TOY_API void Toy_freeVM(Toy_VM* vm);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user