diff --git a/docs/spec.md b/docs/spec.md index 692e710..601cf5f 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -63,7 +63,7 @@ The following mathematical operators are available. A definition is omitted here Likewise, the following logical operators are available (`&&` is more tightly bound than `||` due to historical reasons): ``` -( ) [ ] { } ! != == < > <= >= && || +( ) [ ] { } ?: ! != == < > <= >= && || ``` Other operators used throughout the language are: the assignment, colon, semicolon, comma, dot, rest operators: @@ -346,14 +346,14 @@ assert false, "This is not"; //Error! ## Import-As -`import` is used to load variables from the host - several optional libraries will be provided this way, as well. The import keyword can only take a string as it's argument, followed by an optional "as" which stores the results under a different name. +`import` is used to load variables from the host - several optional libraries will be provided this way, as well. The import keyword can only take a valid variable name as it's argument, followed by an optional "as" which stores the results under a different name. ``` -import "standard"; +import standard; print standard.clock(); //the clock function is provided by standard -import "standard" as std; +import standard as std; print std.clock(); //standard becomes a dictionary called "std" ``` @@ -530,7 +530,7 @@ The standard library has a number of utility functions available, and is provide ``` //gain access to the standard functions -import "standard"; +import standard; ``` The following functions are available in the standard library. diff --git a/scripts/test/separate-exports.toy b/scripts/test/separate-exports.toy new file mode 100644 index 0000000..ba381c4 --- /dev/null +++ b/scripts/test/separate-exports.toy @@ -0,0 +1,11 @@ +//test exports +var field: int = 42; + +fn function() { + return 69; +} + +export field; +export function; + +print "All good"; diff --git a/scripts/test/separate-imports.toy b/scripts/test/separate-imports.toy new file mode 100644 index 0000000..901a660 --- /dev/null +++ b/scripts/test/separate-imports.toy @@ -0,0 +1,10 @@ +//test imports +import field; +//import function; + +//assert field == 42, "import field failed"; + +//assert function() == 69, "import function failed"; + +print "All good"; + diff --git a/source/interpreter.c b/source/interpreter.c index 00e2b93..3d83447 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -72,41 +72,19 @@ bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr) { } void initInterpreter(Interpreter* interpreter) { - initLiteralArray(&interpreter->literalCache); - interpreter->scope = pushScope(NULL); - interpreter->bytecode = NULL; - interpreter->length = 0; - interpreter->count = 0; - interpreter->codeStart = -1; - - initLiteralArray(&interpreter->stack); - + //NOTE: separate initialization for exports interpreter->exports = ALLOCATE(LiteralDictionary, 1); initLiteralDictionary(interpreter->exports); interpreter->exportTypes = ALLOCATE(LiteralDictionary, 1); initLiteralDictionary(interpreter->exportTypes); + //set up the output streams setInterpreterPrint(interpreter, printWrapper); setInterpreterAssert(interpreter, assertWrapper); setInterpreterError(interpreter, errorWrapper); - - //globally available functions (tmp?) - injectNativeFn(interpreter, "_set", _set); - injectNativeFn(interpreter, "_get", _get); - injectNativeFn(interpreter, "_push", _push); - injectNativeFn(interpreter, "_pop", _pop); - injectNativeFn(interpreter, "_length", _length); - injectNativeFn(interpreter, "_clear", _clear); - - interpreter->panic = false; } void freeInterpreter(Interpreter* interpreter) { - //free the interpreter scope - while(interpreter->scope != NULL) { - interpreter->scope = popScope(interpreter->scope); - } - //BUGFIX: handle scopes/types in the exports for (int i = 0; i < interpreter->exports->capacity; i++) { if (IS_FUNCTION(interpreter->exports->entries[i].key)) { @@ -125,9 +103,6 @@ void freeInterpreter(Interpreter* interpreter) { freeLiteralDictionary(interpreter->exportTypes); FREE(LiteralDictionary, interpreter->exportTypes); interpreter->exportTypes = NULL; - - freeLiteralArray(&interpreter->literalCache); - freeLiteralArray(&interpreter->stack); } //utilities for the host program @@ -1849,6 +1824,32 @@ static void readInterpreterSections(Interpreter* interpreter) { } void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length) { + //check for export zone + if (!interpreter->exports || !interpreter->exportTypes) { + interpreter->errorOutput("Interpreter has no export region\n"); + return; + } + + //initialize here instead of initInterpreter() + initLiteralArray(&interpreter->literalCache); + interpreter->scope = pushScope(NULL); + interpreter->bytecode = NULL; + interpreter->length = 0; + interpreter->count = 0; + interpreter->codeStart = -1; + + initLiteralArray(&interpreter->stack); + + //globally available functions + injectNativeFn(interpreter, "_set", _set); + injectNativeFn(interpreter, "_get", _get); + injectNativeFn(interpreter, "_push", _push); + injectNativeFn(interpreter, "_pop", _pop); + injectNativeFn(interpreter, "_length", _length); + injectNativeFn(interpreter, "_clear", _clear); + + interpreter->panic = false; + //prep the bytecode interpreter->bytecode = bytecode; interpreter->length = length; @@ -1901,6 +1902,15 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt freeLiteral(lit); } - //free the bytecode immediately after use + //free the bytecode FREE_ARRAY(unsigned char, interpreter->bytecode, interpreter->length); + + //free the associated data + freeLiteralArray(&interpreter->literalCache); + freeLiteralArray(&interpreter->stack); + + //free the interpreter scope + while(interpreter->scope != NULL) { + interpreter->scope = popScope(interpreter->scope); + } } diff --git a/source/interpreter.h b/source/interpreter.h index d72bb4e..2552eee 100644 --- a/source/interpreter.h +++ b/source/interpreter.h @@ -35,13 +35,12 @@ typedef int (*NativeFn)(Interpreter* interpreter, LiteralArray* arguments); bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func); bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr); -//init & free -void initInterpreter(Interpreter* interpreter); -void freeInterpreter(Interpreter* interpreter); - //utilities for the host program void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput); void setInterpreterAssert(Interpreter* interpreter, PrintFn assertOutput); void setInterpreterError(Interpreter* interpreter, PrintFn errorOutput); +//main access +void initInterpreter(Interpreter* interpreter); void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length); +void freeInterpreter(Interpreter* interpreter); diff --git a/test/test_interpreter.c b/test/test_interpreter.c index 1a09fd1..e67b2b2 100644 --- a/test/test_interpreter.c +++ b/test/test_interpreter.c @@ -191,6 +191,34 @@ int main() { } } + { + //read source + size_t dummy; + size_t exportSize, importSize; + char* exportSource = readFile("../scripts/test/separate-exports.toy", &dummy); + char* importSource = readFile("../scripts/test/separate-imports.toy", &dummy); + + //compile + unsigned char* exportBinary = compileString(exportSource, &exportSize); + unsigned char* importBinary = compileString(importSource, &importSize); + + //run the interpreter over both binaries + Interpreter interpreter; + initInterpreter(&interpreter); + + //NOTE: supress print output for testing + setInterpreterPrint(&interpreter, noPrintFn); + + runInterpreter(&interpreter, exportBinary, exportSize); //automatically frees the binary data + runInterpreter(&interpreter, importBinary, importSize); //automatically frees the binary data + + freeInterpreter(&interpreter); + + //cleanup + free((void*)exportSource); + free((void*)importSource); + } + printf(NOTICE "All good\n" RESET); return 0; }