mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Rearranged some internal initialization to support multiple files being run
This commit is contained in:
10
docs/spec.md
10
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):
|
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:
|
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-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
|
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"
|
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
|
//gain access to the standard functions
|
||||||
import "standard";
|
import standard;
|
||||||
```
|
```
|
||||||
|
|
||||||
The following functions are available in the standard library.
|
The following functions are available in the standard library.
|
||||||
|
|||||||
11
scripts/test/separate-exports.toy
Normal file
11
scripts/test/separate-exports.toy
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//test exports
|
||||||
|
var field: int = 42;
|
||||||
|
|
||||||
|
fn function() {
|
||||||
|
return 69;
|
||||||
|
}
|
||||||
|
|
||||||
|
export field;
|
||||||
|
export function;
|
||||||
|
|
||||||
|
print "All good";
|
||||||
10
scripts/test/separate-imports.toy
Normal file
10
scripts/test/separate-imports.toy
Normal file
@@ -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";
|
||||||
|
|
||||||
@@ -72,41 +72,19 @@ bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initInterpreter(Interpreter* interpreter) {
|
void initInterpreter(Interpreter* interpreter) {
|
||||||
initLiteralArray(&interpreter->literalCache);
|
//NOTE: separate initialization for exports
|
||||||
interpreter->scope = pushScope(NULL);
|
|
||||||
interpreter->bytecode = NULL;
|
|
||||||
interpreter->length = 0;
|
|
||||||
interpreter->count = 0;
|
|
||||||
interpreter->codeStart = -1;
|
|
||||||
|
|
||||||
initLiteralArray(&interpreter->stack);
|
|
||||||
|
|
||||||
interpreter->exports = ALLOCATE(LiteralDictionary, 1);
|
interpreter->exports = ALLOCATE(LiteralDictionary, 1);
|
||||||
initLiteralDictionary(interpreter->exports);
|
initLiteralDictionary(interpreter->exports);
|
||||||
interpreter->exportTypes = ALLOCATE(LiteralDictionary, 1);
|
interpreter->exportTypes = ALLOCATE(LiteralDictionary, 1);
|
||||||
initLiteralDictionary(interpreter->exportTypes);
|
initLiteralDictionary(interpreter->exportTypes);
|
||||||
|
|
||||||
|
//set up the output streams
|
||||||
setInterpreterPrint(interpreter, printWrapper);
|
setInterpreterPrint(interpreter, printWrapper);
|
||||||
setInterpreterAssert(interpreter, assertWrapper);
|
setInterpreterAssert(interpreter, assertWrapper);
|
||||||
setInterpreterError(interpreter, errorWrapper);
|
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) {
|
void freeInterpreter(Interpreter* interpreter) {
|
||||||
//free the interpreter scope
|
|
||||||
while(interpreter->scope != NULL) {
|
|
||||||
interpreter->scope = popScope(interpreter->scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
//BUGFIX: handle scopes/types in the exports
|
//BUGFIX: handle scopes/types in the exports
|
||||||
for (int i = 0; i < interpreter->exports->capacity; i++) {
|
for (int i = 0; i < interpreter->exports->capacity; i++) {
|
||||||
if (IS_FUNCTION(interpreter->exports->entries[i].key)) {
|
if (IS_FUNCTION(interpreter->exports->entries[i].key)) {
|
||||||
@@ -125,9 +103,6 @@ void freeInterpreter(Interpreter* interpreter) {
|
|||||||
freeLiteralDictionary(interpreter->exportTypes);
|
freeLiteralDictionary(interpreter->exportTypes);
|
||||||
FREE(LiteralDictionary, interpreter->exportTypes);
|
FREE(LiteralDictionary, interpreter->exportTypes);
|
||||||
interpreter->exportTypes = NULL;
|
interpreter->exportTypes = NULL;
|
||||||
|
|
||||||
freeLiteralArray(&interpreter->literalCache);
|
|
||||||
freeLiteralArray(&interpreter->stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//utilities for the host program
|
//utilities for the host program
|
||||||
@@ -1849,6 +1824,32 @@ static void readInterpreterSections(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length) {
|
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
|
//prep the bytecode
|
||||||
interpreter->bytecode = bytecode;
|
interpreter->bytecode = bytecode;
|
||||||
interpreter->length = length;
|
interpreter->length = length;
|
||||||
@@ -1901,6 +1902,15 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt
|
|||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
//free the bytecode immediately after use
|
//free the bytecode
|
||||||
FREE_ARRAY(unsigned char, interpreter->bytecode, interpreter->length);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,13 +35,12 @@ typedef int (*NativeFn)(Interpreter* interpreter, LiteralArray* arguments);
|
|||||||
bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func);
|
bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func);
|
||||||
bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr);
|
bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr);
|
||||||
|
|
||||||
//init & free
|
|
||||||
void initInterpreter(Interpreter* interpreter);
|
|
||||||
void freeInterpreter(Interpreter* interpreter);
|
|
||||||
|
|
||||||
//utilities for the host program
|
//utilities for the host program
|
||||||
void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput);
|
void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput);
|
||||||
void setInterpreterAssert(Interpreter* interpreter, PrintFn assertOutput);
|
void setInterpreterAssert(Interpreter* interpreter, PrintFn assertOutput);
|
||||||
void setInterpreterError(Interpreter* interpreter, PrintFn errorOutput);
|
void setInterpreterError(Interpreter* interpreter, PrintFn errorOutput);
|
||||||
|
|
||||||
|
//main access
|
||||||
|
void initInterpreter(Interpreter* interpreter);
|
||||||
void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length);
|
void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length);
|
||||||
|
void freeInterpreter(Interpreter* interpreter);
|
||||||
|
|||||||
@@ -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);
|
printf(NOTICE "All good\n" RESET);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user