Renamed everything to fit the new naming scheme
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
#include "core_common.h"
|
#include "box_common.h"
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(char) == 1);
|
STATIC_ASSERT(sizeof(char) == 1);
|
||||||
STATIC_ASSERT(sizeof(short) == 2);
|
STATIC_ASSERT(sizeof(short) == 2);
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
//platform exports/imports
|
//platform exports/imports
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#define CORE_API extern
|
#define BOX_API extern
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define CORE_API
|
#define BOX_API
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
114
box/box_engine.c
114
box/box_engine.c
@@ -1,4 +1,4 @@
|
|||||||
#include "engine.h"
|
#include "box_engine.h"
|
||||||
|
|
||||||
#include "lib_engine.h"
|
#include "lib_engine.h"
|
||||||
#include "lib_input.h"
|
#include "lib_input.h"
|
||||||
@@ -8,31 +8,31 @@
|
|||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
|
|
||||||
#include "memory.h"
|
#include "toy_memory.h"
|
||||||
#include "lexer.h"
|
#include "toy_lexer.h"
|
||||||
#include "parser.h"
|
#include "toy_parser.h"
|
||||||
#include "compiler.h"
|
#include "toy_compiler.h"
|
||||||
#include "interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
#include "literal_array.h"
|
#include "toy_literal_array.h"
|
||||||
#include "literal_dictionary.h"
|
#include "toy_literal_dictionary.h"
|
||||||
|
|
||||||
#include "console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//define the extern engine object
|
//define the extern engine object
|
||||||
Engine engine;
|
Box_Engine engine;
|
||||||
|
|
||||||
//errors here should be fatal
|
//errors here should be fatal
|
||||||
static void fatalError(char* message) {
|
static void fatalError(char* message) {
|
||||||
fprintf(stderr, "%s", message);
|
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, message);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
void initEngine() {
|
void Box_initEngine() {
|
||||||
//clear
|
//clear
|
||||||
engine.rootNode = NULL;
|
engine.rootNode = NULL;
|
||||||
engine.running = false;
|
engine.running = false;
|
||||||
@@ -45,45 +45,45 @@ void initEngine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//init events
|
//init events
|
||||||
initLiteralArray(&engine.keyDownEvents);
|
Toy_initLiteralArray(&engine.keyDownEvents);
|
||||||
initLiteralDictionary(&engine.symKeyDownEvents);
|
Toy_initLiteralDictionary(&engine.symKeyDownEvents);
|
||||||
initLiteralArray(&engine.keyUpEvents);
|
Toy_initLiteralArray(&engine.keyUpEvents);
|
||||||
initLiteralDictionary(&engine.symKeyUpEvents);
|
Toy_initLiteralDictionary(&engine.symKeyUpEvents);
|
||||||
|
|
||||||
//init Toy
|
//init Toy
|
||||||
initInterpreter(&engine.interpreter);
|
Toy_initInterpreter(&engine.interpreter);
|
||||||
injectNativeHook(&engine.interpreter, "engine", hookEngine);
|
Toy_injectNativeHook(&engine.interpreter, "engine", Box_hookEngine);
|
||||||
injectNativeHook(&engine.interpreter, "node", hookNode);
|
Toy_injectNativeHook(&engine.interpreter, "node", Box_hookNode);
|
||||||
injectNativeHook(&engine.interpreter, "input", hookInput);
|
Toy_injectNativeHook(&engine.interpreter, "input", Box_hookInput);
|
||||||
injectNativeHook(&engine.interpreter, "standard", hookStandard);
|
Toy_injectNativeHook(&engine.interpreter, "standard", Toy_hookStandard);
|
||||||
injectNativeHook(&engine.interpreter, "timer", hookTimer);
|
Toy_injectNativeHook(&engine.interpreter, "timer", Toy_hookTimer);
|
||||||
injectNativeHook(&engine.interpreter, "runner", hookRunner);
|
Toy_injectNativeHook(&engine.interpreter, "runner", Toy_hookRunner);
|
||||||
|
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = readFile("./assets/scripts/init.toy", &size);
|
char* source = Toy_readFile("./assets/scripts/init.toy", &size);
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
runInterpreter(&engine.interpreter, tb, size);
|
Toy_runInterpreter(&engine.interpreter, tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeEngine() {
|
void Box_freeEngine() {
|
||||||
//clear existing root node
|
//clear existing root node
|
||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
||||||
|
|
||||||
freeEngineNode(engine.rootNode);
|
Box_freeEngineNode(engine.rootNode);
|
||||||
|
|
||||||
engine.rootNode = NULL;
|
engine.rootNode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeInterpreter(&engine.interpreter);
|
Toy_freeInterpreter(&engine.interpreter);
|
||||||
|
|
||||||
//free events
|
//free events
|
||||||
freeLiteralArray(&engine.keyDownEvents);
|
Toy_freeLiteralArray(&engine.keyDownEvents);
|
||||||
freeLiteralDictionary(&engine.symKeyDownEvents);
|
Toy_freeLiteralDictionary(&engine.symKeyDownEvents);
|
||||||
freeLiteralArray(&engine.keyUpEvents);
|
Toy_freeLiteralArray(&engine.keyUpEvents);
|
||||||
freeLiteralDictionary(&engine.symKeyUpEvents);
|
Toy_freeLiteralDictionary(&engine.symKeyUpEvents);
|
||||||
|
|
||||||
//free SDL
|
//free SDL
|
||||||
SDL_DestroyRenderer(engine.renderer);
|
SDL_DestroyRenderer(engine.renderer);
|
||||||
@@ -97,13 +97,13 @@ void freeEngine() {
|
|||||||
static void execEvents() {
|
static void execEvents() {
|
||||||
//clear event lists
|
//clear event lists
|
||||||
if (engine.keyDownEvents.count > 0) {
|
if (engine.keyDownEvents.count > 0) {
|
||||||
freeLiteralArray(&engine.keyDownEvents);
|
Toy_freeLiteralArray(&engine.keyDownEvents);
|
||||||
//NOTE: this is likely memory intensive - a more bespoke linked list designed for this task would be better
|
//NOTE: this is likely memory intensive - a more bespoke linked list designed for this task would be better
|
||||||
//NOTE: alternatively - manual memory-wipes, skipping the free step could be better
|
//NOTE: alternatively - manual memory-wipes, skipping the free step could be better
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engine.keyUpEvents.count > 0) {
|
if (engine.keyUpEvents.count > 0) {
|
||||||
freeLiteralArray(&engine.keyUpEvents);
|
Toy_freeLiteralArray(&engine.keyUpEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
//poll all events
|
//poll all events
|
||||||
@@ -136,16 +136,16 @@ static void execEvents() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//determine the given keycode
|
//determine the given keycode
|
||||||
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
|
Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
|
||||||
if (!existsLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral)) {
|
if (!Toy_existsLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the event name
|
//get the event name
|
||||||
Literal eventLiteral = getLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral);
|
Toy_Literal eventLiteral = Toy_getLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral);
|
||||||
|
|
||||||
//push to the event list
|
//push to the event list
|
||||||
pushLiteralArray(&engine.keyDownEvents, eventLiteral);
|
Toy_pushLiteralArray(&engine.keyDownEvents, eventLiteral);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -156,16 +156,16 @@ static void execEvents() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//determine the given keycode
|
//determine the given keycode
|
||||||
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
|
Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
|
||||||
if (!existsLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral)) {
|
if (!Toy_existsLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the event name
|
//get the event name
|
||||||
Literal eventLiteral = getLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral);
|
Toy_Literal eventLiteral = Toy_getLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral);
|
||||||
|
|
||||||
//push to the event list
|
//push to the event list
|
||||||
pushLiteralArray(&engine.keyUpEvents, eventLiteral);
|
Toy_pushLiteralArray(&engine.keyUpEvents, eventLiteral);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -175,20 +175,20 @@ static void execEvents() {
|
|||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
//key down events
|
//key down events
|
||||||
for (int i = 0; i < engine.keyDownEvents.count; i++) { //TODO: could pass in the whole array?
|
for (int i = 0; i < engine.keyDownEvents.count; i++) { //TODO: could pass in the whole array?
|
||||||
LiteralArray args;
|
Toy_LiteralArray args;
|
||||||
initLiteralArray(&args);
|
Toy_initLiteralArray(&args);
|
||||||
pushLiteralArray(&args, engine.keyDownEvents.literals[i]);
|
Toy_pushLiteralArray(&args, engine.keyDownEvents.literals[i]);
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyDown", &args);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyDown", &args);
|
||||||
freeLiteralArray(&args);
|
Toy_freeLiteralArray(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
//key up events
|
//key up events
|
||||||
for (int i = 0; i < engine.keyUpEvents.count; i++) {
|
for (int i = 0; i < engine.keyUpEvents.count; i++) {
|
||||||
LiteralArray args;
|
Toy_LiteralArray args;
|
||||||
initLiteralArray(&args);
|
Toy_initLiteralArray(&args);
|
||||||
pushLiteralArray(&args, engine.keyUpEvents.literals[i]);
|
Toy_pushLiteralArray(&args, engine.keyUpEvents.literals[i]);
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyUp", &args);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyUp", &args);
|
||||||
freeLiteralArray(&args);
|
Toy_freeLiteralArray(&args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,12 +196,12 @@ static void execEvents() {
|
|||||||
void execStep() {
|
void execStep() {
|
||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
//steps
|
//steps
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//the heart of the engine
|
//the heart of the engine
|
||||||
void execEngine() {
|
void Box_execEngine() {
|
||||||
if (!engine.running) {
|
if (!engine.running) {
|
||||||
fatalError("Can't execute the engine (did you forget to initialize the screen?)");
|
fatalError("Can't execute the engine (did you forget to initialize the screen?)");
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ void execEngine() {
|
|||||||
SDL_SetRenderDrawColor(engine.renderer, 0, 0, 0, 255); //NOTE: This line can be disabled later
|
SDL_SetRenderDrawColor(engine.renderer, 0, 0, 0, 255); //NOTE: This line can be disabled later
|
||||||
SDL_RenderClear(engine.renderer); //NOTE: This line can be disabled later
|
SDL_RenderClear(engine.renderer); //NOTE: This line can be disabled later
|
||||||
|
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onDraw", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onDraw", NULL);
|
||||||
|
|
||||||
SDL_RenderPresent(engine.renderer);
|
SDL_RenderPresent(engine.renderer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core_common.h"
|
#include "box_common.h"
|
||||||
#include "engine_node.h"
|
#include "box_engine_node.h"
|
||||||
#include "interpreter.h"
|
|
||||||
|
|
||||||
#include "literal_array.h"
|
#include "toy_interpreter.h"
|
||||||
#include "literal_dictionary.h"
|
#include "toy_literal_array.h"
|
||||||
|
#include "toy_literal_dictionary.h"
|
||||||
#include "core_common.h"
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
//the base engine object, which represents the state of the game
|
//the base engine object, which represents the state of the game
|
||||||
typedef struct _engine {
|
typedef struct Box_private_engine {
|
||||||
//engine stuff
|
//engine stuff
|
||||||
EngineNode* rootNode;
|
Box_EngineNode* rootNode;
|
||||||
struct timeval simTime;
|
struct timeval simTime;
|
||||||
struct timeval realTime;
|
struct timeval realTime;
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
//Toy stuff
|
//Toy stuff
|
||||||
Interpreter interpreter;
|
Toy_Interpreter interpreter;
|
||||||
|
|
||||||
//SDL stuff
|
//SDL stuff
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
@@ -29,18 +27,18 @@ typedef struct _engine {
|
|||||||
int screenHeight;
|
int screenHeight;
|
||||||
|
|
||||||
//input syms mapped to events
|
//input syms mapped to events
|
||||||
LiteralArray keyDownEvents; //list of events that occurred this frame
|
Toy_LiteralArray keyDownEvents; //list of events that occurred this frame
|
||||||
LiteralDictionary symKeyDownEvents; //keysym -> event names
|
Toy_LiteralDictionary symKeyDownEvents; //keysym -> event names
|
||||||
|
|
||||||
LiteralArray keyUpEvents; //list of events that occurred this frame
|
Toy_LiteralArray keyUpEvents; //list of events that occurred this frame
|
||||||
LiteralDictionary symKeyUpEvents; //keysym -> event names
|
Toy_LiteralDictionary symKeyUpEvents; //keysym -> event names
|
||||||
} Engine;
|
} Box_Engine;
|
||||||
|
|
||||||
//extern singleton - used by various libraries
|
//extern singleton - used by various libraries
|
||||||
extern Engine engine;
|
extern Box_Engine engine;
|
||||||
|
|
||||||
//APIs for running the engine in main()
|
//APIs for running the engine in main()
|
||||||
CORE_API void initEngine();
|
BOX_API void Box_initEngine();
|
||||||
CORE_API void execEngine();
|
BOX_API void Box_execEngine();
|
||||||
CORE_API void freeEngine();
|
BOX_API void Box_freeEngine();
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
#include "engine_node.h"
|
#include "box_engine_node.h"
|
||||||
|
#include "box_engine.h"
|
||||||
|
|
||||||
#include "engine.h"
|
#include "toy_memory.h"
|
||||||
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
static void freeMemory(void* ptr) {
|
static void freeMemory(void* ptr) {
|
||||||
EngineNode* node = (EngineNode*)ptr;
|
Box_EngineNode* node = (Box_EngineNode*)ptr;
|
||||||
//SDL stuff
|
//SDL stuff
|
||||||
SDL_DestroyTexture(node->texture);
|
SDL_DestroyTexture(node->texture);
|
||||||
|
|
||||||
//free this node type's memory
|
//free this node type's memory
|
||||||
FREE(EngineNode, ptr);
|
TOY_FREE(Box_EngineNode, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t size) {
|
void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, void* tb, size_t size) {
|
||||||
//init
|
//init
|
||||||
// node->freeMemory = freeMemory;
|
// node->freeMemory = freeMemory;
|
||||||
node->functions = ALLOCATE(LiteralDictionary, 1);
|
node->functions = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
node->parent = NULL;
|
node->parent = NULL;
|
||||||
node->tag = OPAQUE_TAG_ENGINE_NODE;
|
node->tag = OPAQUE_TAG_ENGINE_NODE;
|
||||||
node->children = NULL;
|
node->children = NULL;
|
||||||
@@ -24,36 +23,36 @@ void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t
|
|||||||
node->count = 0;
|
node->count = 0;
|
||||||
node->texture = NULL;
|
node->texture = NULL;
|
||||||
|
|
||||||
initLiteralDictionary(node->functions);
|
Toy_initLiteralDictionary(node->functions);
|
||||||
|
|
||||||
//run bytecode
|
//run bytecode
|
||||||
runInterpreter(interpreter, tb, size);
|
Toy_runInterpreter(interpreter, tb, size);
|
||||||
|
|
||||||
//grab all top-level functions from the dirty interpreter
|
//grab all top-level functions from the dirty interpreter
|
||||||
LiteralDictionary* variablesPtr = &interpreter->scope->variables;
|
Toy_LiteralDictionary* variablesPtr = &interpreter->scope->variables;
|
||||||
|
|
||||||
for (int i = 0; i < variablesPtr->capacity; i++) {
|
for (int i = 0; i < variablesPtr->capacity; i++) {
|
||||||
//skip empties and tombstones
|
//skip empties and tombstones
|
||||||
if (IS_NULL(variablesPtr->entries[i].key)) {
|
if (TOY_IS_NULL(variablesPtr->entries[i].key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if this variable is a function (this outmodes import and export)
|
//if this variable is a function (this outmodes import and export)
|
||||||
_entry* entry = &variablesPtr->entries[i];
|
Toy_private_entry* entry = &variablesPtr->entries[i];
|
||||||
if (IS_FUNCTION(entry->value)) {
|
if (TOY_IS_FUNCTION(entry->value)) {
|
||||||
//save a copy
|
//save a copy
|
||||||
setLiteralDictionary(node->functions, entry->key, entry->value);
|
Toy_setLiteralDictionary(node->functions, entry->key, entry->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushEngineNode(EngineNode* node, EngineNode* child) {
|
void Box_pushEngineNode(Box_EngineNode* node, Box_EngineNode* child) {
|
||||||
//push to the array (prune tombstones when expanding/copying)
|
//push to the array (prune tombstones when expanding/copying)
|
||||||
if (node->count + 1 > node->capacity) {
|
if (node->count + 1 > node->capacity) {
|
||||||
int oldCapacity = node->capacity;
|
int oldCapacity = node->capacity;
|
||||||
|
|
||||||
node->capacity = GROW_CAPACITY(oldCapacity);
|
node->capacity = TOY_GROW_CAPACITY(oldCapacity);
|
||||||
node->children = GROW_ARRAY(EngineNode*, node->children, oldCapacity, node->capacity);
|
node->children = TOY_GROW_ARRAY(Box_EngineNode*, node->children, oldCapacity, node->capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//prune tombstones (experimental)
|
//prune tombstones (experimental)
|
||||||
@@ -77,22 +76,22 @@ void pushEngineNode(EngineNode* node, EngineNode* child) {
|
|||||||
child->parent = node;
|
child->parent = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeEngineNode(EngineNode* node) {
|
void Box_freeEngineNode(Box_EngineNode* node) {
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
return; //NO-OP
|
return; //NO-OP
|
||||||
}
|
}
|
||||||
|
|
||||||
//free and tombstone this node
|
//free and tombstone this node
|
||||||
for (int i = 0; i < node->count; i++) {
|
for (int i = 0; i < node->count; i++) {
|
||||||
freeEngineNode(node->children[i]);
|
Box_freeEngineNode(node->children[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//free the pointer array to the children
|
//free the pointer array to the children
|
||||||
FREE_ARRAY(EngineNode*, node->children, node->capacity);
|
TOY_FREE_ARRAY(Box_EngineNode*, node->children, node->capacity);
|
||||||
|
|
||||||
if (node->functions != NULL) {
|
if (node->functions != NULL) {
|
||||||
freeLiteralDictionary(node->functions);
|
Toy_freeLiteralDictionary(node->functions);
|
||||||
FREE(LiteralDictionary, node->functions);
|
TOY_FREE(Toy_LiteralDictionary, node->functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
//free this node's memory
|
//free this node's memory
|
||||||
@@ -100,100 +99,100 @@ void freeEngineNode(EngineNode* node) {
|
|||||||
freeMemory(node);
|
freeMemory(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal callEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args) {
|
Toy_Literal Box_callEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) {
|
||||||
Literal ret = TO_NULL_LITERAL;
|
Toy_Literal ret = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
//if this fn exists
|
//if this fn exists
|
||||||
if (existsLiteralDictionary(node->functions, key)) {
|
if (Toy_existsLiteralDictionary(node->functions, key)) {
|
||||||
Literal fn = getLiteralDictionary(node->functions, key);
|
Toy_Literal fn = Toy_getLiteralDictionary(node->functions, key);
|
||||||
Literal n = TO_OPAQUE_LITERAL(node, node->tag);
|
Toy_Literal n = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||||
|
|
||||||
LiteralArray arguments;
|
Toy_LiteralArray arguments;
|
||||||
LiteralArray returns;
|
Toy_LiteralArray returns;
|
||||||
initLiteralArray(&arguments);
|
Toy_initLiteralArray(&arguments);
|
||||||
initLiteralArray(&returns);
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
//feed the arguments in backwards!
|
//feed the arguments in backwards!
|
||||||
if (args) {
|
if (args) {
|
||||||
for (int i = args->count -1; i >= 0; i--) {
|
for (int i = args->count -1; i >= 0; i--) {
|
||||||
pushLiteralArray(&arguments, args->literals[i]);
|
Toy_pushLiteralArray(&arguments, args->literals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(&arguments, n);
|
Toy_pushLiteralArray(&arguments, n);
|
||||||
|
|
||||||
callLiteralFn(interpreter, fn, &arguments, &returns);
|
Toy_callLiteralFn(interpreter, fn, &arguments, &returns);
|
||||||
|
|
||||||
ret = popLiteralArray(&returns);
|
ret = Toy_popLiteralArray(&returns);
|
||||||
|
|
||||||
freeLiteralArray(&arguments);
|
Toy_freeLiteralArray(&arguments);
|
||||||
freeLiteralArray(&returns);
|
Toy_freeLiteralArray(&returns);
|
||||||
|
|
||||||
freeLiteral(n);
|
Toy_freeLiteral(n);
|
||||||
freeLiteral(fn);
|
Toy_freeLiteral(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal callEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args) {
|
Toy_Literal Box_callEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, char* fnName, Toy_LiteralArray* args) {
|
||||||
//call "fnName" on this node, and all children, if it exists
|
//call "fnName" on this node, and all children, if it exists
|
||||||
Literal key = TO_IDENTIFIER_LITERAL(createRefString(fnName));
|
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(fnName));
|
||||||
|
|
||||||
Literal ret = callEngineNodeLiteral(node, interpreter, key, args);
|
Toy_Literal ret = Box_callEngineNodeLiteral(node, interpreter, key, args);
|
||||||
|
|
||||||
freeLiteral(key);
|
Toy_freeLiteral(key);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void callRecursiveEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args) {
|
void Box_callRecursiveEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) {
|
||||||
//if this fn exists
|
//if this fn exists
|
||||||
if (existsLiteralDictionary(node->functions, key)) {
|
if (Toy_existsLiteralDictionary(node->functions, key)) {
|
||||||
Literal fn = getLiteralDictionary(node->functions, key);
|
Toy_Literal fn = Toy_getLiteralDictionary(node->functions, key);
|
||||||
Literal n = TO_OPAQUE_LITERAL(node, node->tag);
|
Toy_Literal n = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||||
|
|
||||||
LiteralArray arguments;
|
Toy_LiteralArray arguments;
|
||||||
LiteralArray returns;
|
Toy_LiteralArray returns;
|
||||||
initLiteralArray(&arguments);
|
Toy_initLiteralArray(&arguments);
|
||||||
initLiteralArray(&returns);
|
Toy_initLiteralArray(&returns);
|
||||||
|
|
||||||
//feed the arguments in backwards!
|
//feed the arguments in backwards!
|
||||||
if (args) {
|
if (args) {
|
||||||
for (int i = args->count -1; i >= 0; i--) {
|
for (int i = args->count -1; i >= 0; i--) {
|
||||||
pushLiteralArray(&arguments, args->literals[i]);
|
Toy_pushLiteralArray(&arguments, args->literals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(&arguments, n);
|
Toy_pushLiteralArray(&arguments, n);
|
||||||
|
|
||||||
callLiteralFn(interpreter, fn, &arguments, &returns);
|
Toy_callLiteralFn(interpreter, fn, &arguments, &returns);
|
||||||
|
|
||||||
freeLiteralArray(&arguments);
|
Toy_freeLiteralArray(&arguments);
|
||||||
freeLiteralArray(&returns);
|
Toy_freeLiteralArray(&returns);
|
||||||
|
|
||||||
freeLiteral(n);
|
Toy_freeLiteral(n);
|
||||||
freeLiteral(fn);
|
Toy_freeLiteral(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//recurse to the (non-tombstone) children
|
//recurse to the (non-tombstone) children
|
||||||
for (int i = 0; i < node->count; i++) {
|
for (int i = 0; i < node->count; i++) {
|
||||||
if (node->children[i] != NULL) {
|
if (node->children[i] != NULL) {
|
||||||
callRecursiveEngineNodeLiteral(node->children[i], interpreter, key, args);
|
Box_callRecursiveEngineNodeLiteral(node->children[i], interpreter, key, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void callRecursiveEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args) {
|
void Box_callRecursiveEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, char* fnName, Toy_LiteralArray* args) {
|
||||||
//call "fnName" on this node, and all children, if it exists
|
//call "fnName" on this node, and all children, if it exists
|
||||||
Literal key = TO_IDENTIFIER_LITERAL(createRefString(fnName));
|
Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(fnName));
|
||||||
|
|
||||||
callRecursiveEngineNodeLiteral(node, interpreter, key, args);
|
Box_callRecursiveEngineNodeLiteral(node, interpreter, key, args);
|
||||||
|
|
||||||
freeLiteral(key);
|
Toy_freeLiteral(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int loadTextureEngineNode(EngineNode* node, char* fname) {
|
int Box_loadTextureEngineNode(Box_EngineNode* node, char* fname) {
|
||||||
SDL_Surface* surface = IMG_Load(fname);
|
SDL_Surface* surface = IMG_Load(fname);
|
||||||
|
|
||||||
if (surface == NULL) {
|
if (surface == NULL) {
|
||||||
@@ -211,22 +210,22 @@ int loadTextureEngineNode(EngineNode* node, char* fname) {
|
|||||||
int w, h;
|
int w, h;
|
||||||
SDL_QueryTexture(node->texture, NULL, NULL, &w, &h);
|
SDL_QueryTexture(node->texture, NULL, NULL, &w, &h);
|
||||||
SDL_Rect r = { 0, 0, w, h };
|
SDL_Rect r = { 0, 0, w, h };
|
||||||
setRectEngineNode(node, r);
|
Box_setRectEngineNode(node, r);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeTextureEngineNode(EngineNode* node) {
|
void Box_freeTextureEngineNode(Box_EngineNode* node) {
|
||||||
if (node->texture != NULL) {
|
if (node->texture != NULL) {
|
||||||
SDL_DestroyTexture(node->texture);
|
SDL_DestroyTexture(node->texture);
|
||||||
node->texture = NULL;
|
node->texture = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRectEngineNode(EngineNode* node, SDL_Rect rect) {
|
void Box_setRectEngineNode(Box_EngineNode* node, SDL_Rect rect) {
|
||||||
node->rect = rect;
|
node->rect = rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawEngineNode(EngineNode* node, SDL_Rect dest) {
|
void Box_drawEngineNode(Box_EngineNode* node, SDL_Rect dest) {
|
||||||
SDL_RenderCopy(engine.renderer, node->texture, &node->rect, &dest);
|
SDL_RenderCopy(engine.renderer, node->texture, &node->rect, &dest);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core_common.h"
|
#include "box_common.h"
|
||||||
|
|
||||||
#include "literal_dictionary.h"
|
#include "toy_literal_dictionary.h"
|
||||||
#include "interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
#define OPAQUE_TAG_ENGINE_NODE 1001
|
#define OPAQUE_TAG_ENGINE_NODE 1001
|
||||||
|
|
||||||
//forward declare
|
//forward declare
|
||||||
typedef struct _engineNode EngineNode;
|
typedef struct Box_private_engineNode Box_EngineNode;
|
||||||
// typedef void (*EngineNodeCallback)(void*);
|
// typedef void (*EngineNodeCallback)(void*);
|
||||||
|
|
||||||
//the node object, which forms a tree
|
//the node object, which forms a tree
|
||||||
typedef struct _engineNode {
|
typedef struct Box_private_engineNode {
|
||||||
//function for releasing memory NOTE: removed, because it's not needed with only 1 node type - I've left them commented out because I might need them soon
|
//function for releasing memory NOTE: removed, because it's not needed with only 1 node type - I've left them commented out because I might need them soon
|
||||||
// EngineNodeCallback freeMemory;
|
// EngineNodeCallback freeMemory;
|
||||||
|
|
||||||
//toy functions, stored in a dict for flexibility
|
//toy functions, stored in a dict for flexibility
|
||||||
LiteralDictionary* functions;
|
Toy_LiteralDictionary* functions;
|
||||||
|
|
||||||
//point to the parent
|
//point to the parent
|
||||||
EngineNode* parent;
|
Box_EngineNode* parent;
|
||||||
|
|
||||||
//my opaque type tag
|
//my opaque type tag
|
||||||
int tag;
|
int tag;
|
||||||
int _unused0;
|
int _unused0;
|
||||||
|
|
||||||
//use Toy's memory model
|
//use Toy's memory model
|
||||||
EngineNode** children;
|
Box_EngineNode** children;
|
||||||
int capacity;
|
int capacity;
|
||||||
int count; //includes tombstones
|
int count; //includes tombstones
|
||||||
|
|
||||||
@@ -35,21 +35,21 @@ typedef struct _engineNode {
|
|||||||
SDL_Texture* texture;
|
SDL_Texture* texture;
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
//TODO: depth
|
//TODO: depth
|
||||||
} EngineNode;
|
} Box_EngineNode;
|
||||||
|
|
||||||
CORE_API void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t size); //run bytecode, then grab all top-level function literals
|
BOX_API void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, void* tb, size_t size); //run bytecode, then grab all top-level function literals
|
||||||
CORE_API void pushEngineNode(EngineNode* node, EngineNode* child); //push to the array (prune tombstones when expanding/copying)
|
BOX_API void Box_pushEngineNode(Box_EngineNode* node, Box_EngineNode* child); //push to the array (prune tombstones when expanding/copying)
|
||||||
CORE_API void freeEngineNode(EngineNode* node); //free and tombstone this node
|
BOX_API void Box_freeEngineNode(Box_EngineNode* node); //free and tombstone this node
|
||||||
|
|
||||||
CORE_API Literal callEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args);
|
BOX_API Toy_Literal Box_callEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args);
|
||||||
CORE_API Literal callEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args); //call "fnName" on this node, and only this node, if it exists
|
BOX_API Toy_Literal Box_callEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and only this node, if it exists
|
||||||
|
|
||||||
CORE_API void callRecursiveEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args);
|
BOX_API void Box_callRecursiveEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args);
|
||||||
CORE_API void callRecursiveEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args); //call "fnName" on this node, and all children, if it exists
|
BOX_API void Box_callRecursiveEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and all children, if it exists
|
||||||
|
|
||||||
CORE_API int loadTextureEngineNode(EngineNode* node, char* fname);
|
BOX_API int Box_loadTextureEngineNode(Box_EngineNode* node, char* fname);
|
||||||
CORE_API void freeTextureEngineNode(EngineNode* node);
|
BOX_API void Box_freeTextureEngineNode(Box_EngineNode* node);
|
||||||
|
|
||||||
CORE_API void setRectEngineNode(EngineNode* node, SDL_Rect rect);
|
BOX_API void Box_setRectEngineNode(Box_EngineNode* node, SDL_Rect rect);
|
||||||
//TODO: getRect
|
//TODO: getRect
|
||||||
CORE_API void drawEngineNode(EngineNode* node, SDL_Rect dest);
|
BOX_API void Box_drawEngineNode(Box_EngineNode* node, SDL_Rect dest);
|
||||||
|
|||||||
138
box/lib_engine.c
138
box/lib_engine.c
@@ -1,19 +1,21 @@
|
|||||||
#include "lib_engine.h"
|
#include "lib_engine.h"
|
||||||
|
|
||||||
#include "engine.h"
|
#include "box_engine.h"
|
||||||
#include "repl_tools.h"
|
|
||||||
|
|
||||||
#include "memory.h"
|
#include "repl_tools.h"
|
||||||
#include "literal_array.h"
|
#include "toy_memory.h"
|
||||||
|
#include "toy_literal_array.h"
|
||||||
|
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
//errors here should be fatal
|
//errors here should be fatal
|
||||||
static void fatalError(char* message) {
|
static void fatalError(char* message) {
|
||||||
fprintf(stderr, "%s", message);
|
fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, message);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//native functions to be called
|
//native functions to be called
|
||||||
static int nativeInitWindow(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeInitWindow(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (engine.window != NULL) {
|
if (engine.window != NULL) {
|
||||||
fatalError("Can't re-initialize the window\n");
|
fatalError("Can't re-initialize the window\n");
|
||||||
}
|
}
|
||||||
@@ -23,24 +25,24 @@ static int nativeInitWindow(Interpreter* interpreter, LiteralArray* arguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal fscreen = popLiteralArray(arguments);
|
Toy_Literal fscreen = Toy_popLiteralArray(arguments);
|
||||||
Literal screenHeight = popLiteralArray(arguments);
|
Toy_Literal screenHeight = Toy_popLiteralArray(arguments);
|
||||||
Literal screenWidth = popLiteralArray(arguments);
|
Toy_Literal screenWidth = Toy_popLiteralArray(arguments);
|
||||||
Literal caption = popLiteralArray(arguments);
|
Toy_Literal caption = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_STRING(caption) || !IS_INTEGER(screenWidth) || !IS_INTEGER(screenHeight) || !IS_BOOLEAN(fscreen)) {
|
if (!TOY_IS_STRING(caption) || !TOY_IS_INTEGER(screenWidth) || !TOY_IS_INTEGER(screenHeight) || !TOY_IS_BOOLEAN(fscreen)) {
|
||||||
fatalError("Incorrect argument type passed to initEngine\n");
|
fatalError("Incorrect argument type passed to initEngine\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//init the window
|
//init the window
|
||||||
engine.window = SDL_CreateWindow(
|
engine.window = SDL_CreateWindow(
|
||||||
toCString(AS_STRING(caption)),
|
Toy_toCString(TOY_AS_STRING(caption)),
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
engine.screenWidth = AS_INTEGER(screenWidth),
|
engine.screenWidth = TOY_AS_INTEGER(screenWidth),
|
||||||
engine.screenHeight = AS_INTEGER(screenHeight),
|
engine.screenHeight = TOY_AS_INTEGER(screenHeight),
|
||||||
IS_TRUTHY(fscreen) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE
|
TOY_IS_TRUTHY(fscreen) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
if (engine.window == NULL) {
|
if (engine.window == NULL) {
|
||||||
@@ -66,81 +68,81 @@ static int nativeInitWindow(Interpreter* interpreter, LiteralArray* arguments) {
|
|||||||
//only run with a window
|
//only run with a window
|
||||||
engine.running = true;
|
engine.running = true;
|
||||||
|
|
||||||
freeLiteral(caption);
|
Toy_freeLiteral(caption);
|
||||||
freeLiteral(screenWidth);
|
Toy_freeLiteral(screenWidth);
|
||||||
freeLiteral(screenHeight);
|
Toy_freeLiteral(screenHeight);
|
||||||
freeLiteral(fscreen);
|
Toy_freeLiteral(fscreen);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: perhaps a returns argument would be better?
|
//TODO: perhaps a returns argument would be better?
|
||||||
static int nativeLoadRootNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeLoadRootNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to loadRootNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to loadRootNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal fname = popLiteralArray(arguments);
|
Toy_Literal fname = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal fnameIdn = fname;
|
Toy_Literal fnameIdn = fname;
|
||||||
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
|
if (TOY_IS_IDENTIFIER(fname) && Toy_parseIdentifierToValue(interpreter, &fname)) {
|
||||||
freeLiteral(fnameIdn);
|
Toy_freeLiteral(fnameIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_STRING(fname)) {
|
if (!TOY_IS_STRING(fname)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to loadRootNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to loadRootNode\n");
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear existing root node
|
//clear existing root node
|
||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
||||||
|
|
||||||
freeEngineNode(engine.rootNode);
|
Box_freeEngineNode(engine.rootNode);
|
||||||
FREE(EngineNode, engine.rootNode);
|
TOY_FREE(Box_EngineNode, engine.rootNode);
|
||||||
|
|
||||||
engine.rootNode = NULL;
|
engine.rootNode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//load the new root node
|
//load the new root node
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = readFile(toCString(AS_STRING(fname)), &size);
|
char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(fname)), &size);
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
engine.rootNode = ALLOCATE(EngineNode, 1);
|
engine.rootNode = TOY_ALLOCATE(Box_EngineNode, 1);
|
||||||
|
|
||||||
//BUGFIX: make an inner-interpreter
|
//BUGFIX: make an inner-interpreter
|
||||||
Interpreter inner;
|
Toy_Interpreter inner;
|
||||||
|
|
||||||
//init the inner interpreter manually
|
//init the inner interpreter manually
|
||||||
initLiteralArray(&inner.literalCache);
|
Toy_initLiteralArray(&inner.literalCache);
|
||||||
inner.scope = pushScope(NULL);
|
inner.scope = Toy_pushScope(NULL);
|
||||||
inner.bytecode = tb;
|
inner.bytecode = tb;
|
||||||
inner.length = size;
|
inner.length = size;
|
||||||
inner.count = 0;
|
inner.count = 0;
|
||||||
inner.codeStart = -1;
|
inner.codeStart = -1;
|
||||||
inner.depth = interpreter->depth + 1;
|
inner.depth = interpreter->depth + 1;
|
||||||
inner.panic = false;
|
inner.panic = false;
|
||||||
initLiteralArray(&inner.stack);
|
Toy_initLiteralArray(&inner.stack);
|
||||||
inner.hooks = interpreter->hooks;
|
inner.hooks = interpreter->hooks;
|
||||||
setInterpreterPrint(&inner, interpreter->printOutput);
|
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
||||||
setInterpreterAssert(&inner, interpreter->assertOutput);
|
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||||
setInterpreterError(&inner, interpreter->errorOutput);
|
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
||||||
|
|
||||||
initEngineNode(engine.rootNode, &inner, tb, size);
|
Box_initEngineNode(engine.rootNode, &inner, tb, size);
|
||||||
|
|
||||||
//init the new node (and ONLY this node)
|
//init the new node (and ONLY this node)
|
||||||
callEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL);
|
Box_callEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteralArray(&inner.stack);
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
freeLiteralArray(&inner.literalCache);
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -148,10 +150,10 @@ static int nativeLoadRootNode(Interpreter* interpreter, LiteralArray* arguments)
|
|||||||
//call the hook
|
//call the hook
|
||||||
typedef struct Natives {
|
typedef struct Natives {
|
||||||
char* name;
|
char* name;
|
||||||
NativeFn fn;
|
Toy_NativeFn fn;
|
||||||
} Natives;
|
} Natives;
|
||||||
|
|
||||||
int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias) {
|
int Box_hookEngine(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
{"initWindow", nativeInitWindow},
|
{"initWindow", nativeInitWindow},
|
||||||
@@ -160,51 +162,51 @@ int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//store the library in an aliased dictionary
|
//store the library in an aliased dictionary
|
||||||
if (!IS_NULL(alias)) {
|
if (!TOY_IS_NULL(alias)) {
|
||||||
//make sure the name isn't taken
|
//make sure the name isn't taken
|
||||||
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
interpreter->errorOutput("Can't override an existing variable\n");
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
freeLiteral(alias);
|
Toy_freeLiteral(alias);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the dictionary to load up with functions
|
//create the dictionary to load up with functions
|
||||||
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
initLiteralDictionary(dictionary);
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
//load the dict with functions
|
//load the dict with functions
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
func.type = LITERAL_FUNCTION_NATIVE;
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
setLiteralDictionary(dictionary, name, func);
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
freeLiteral(name);
|
Toy_freeLiteral(name);
|
||||||
freeLiteral(func);
|
Toy_freeLiteral(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
//build the type
|
//build the type
|
||||||
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
TYPE_PUSH_SUBTYPE(&type, strType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
TYPE_PUSH_SUBTYPE(&type, fnType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
//set scope
|
//set scope
|
||||||
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
declareScopeVariable(interpreter->scope, alias, type);
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
setScopeVariable(interpreter->scope, alias, dict, false);
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(dict);
|
Toy_freeLiteral(dict);
|
||||||
freeLiteral(type);
|
Toy_freeLiteral(type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//default
|
//default
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias);
|
int Box_hookEngine(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "lib_input.h"
|
#include "lib_input.h"
|
||||||
|
|
||||||
#include "memory.h"
|
#include "box_common.h"
|
||||||
|
#include "box_engine.h"
|
||||||
|
|
||||||
#include "engine.h"
|
#include "toy_memory.h"
|
||||||
#include "core_common.h"
|
|
||||||
|
|
||||||
static int nativeMapInputEventToKey(Interpreter* interpreter, LiteralArray* arguments, LiteralDictionary* symKeyEventsPtr, char* fnName) {
|
static int nativeMapInputEventToKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments, Toy_LiteralDictionary* symKeyEventsPtr, char* fnName) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to ");
|
interpreter->errorOutput("Incorrect number of arguments passed to ");
|
||||||
@@ -14,26 +14,26 @@ static int nativeMapInputEventToKey(Interpreter* interpreter, LiteralArray* argu
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal symLiteral = popLiteralArray(arguments);
|
Toy_Literal symLiteral = Toy_popLiteralArray(arguments);
|
||||||
Literal evtLiteral = popLiteralArray(arguments);
|
Toy_Literal evtLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal evtLiteralIdn = evtLiteral;
|
Toy_Literal evtLiteralIdn = evtLiteral;
|
||||||
if (IS_IDENTIFIER(evtLiteral) && parseIdentifierToValue(interpreter, &evtLiteral)) {
|
if (TOY_IS_IDENTIFIER(evtLiteral) && Toy_parseIdentifierToValue(interpreter, &evtLiteral)) {
|
||||||
freeLiteral(evtLiteralIdn);
|
Toy_freeLiteral(evtLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal symLiteralIdn = symLiteral;
|
Toy_Literal symLiteralIdn = symLiteral;
|
||||||
if (IS_IDENTIFIER(symLiteral) && parseIdentifierToValue(interpreter, &symLiteral)) {
|
if (TOY_IS_IDENTIFIER(symLiteral) && Toy_parseIdentifierToValue(interpreter, &symLiteral)) {
|
||||||
freeLiteral(symLiteralIdn);
|
Toy_freeLiteral(symLiteralIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_STRING(symLiteral) || !IS_STRING(evtLiteral)) {
|
if (!TOY_IS_STRING(symLiteral) || !TOY_IS_STRING(evtLiteral)) {
|
||||||
interpreter->errorOutput("Incorrect type of arguments passed to mapInputEventToKey\n");
|
interpreter->errorOutput("Incorrect type of arguments passed to mapInputEventToKey\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//use the keycode for faster lookups
|
//use the keycode for faster lookups
|
||||||
SDL_Keycode keycode = SDL_GetKeyFromName( toCString(AS_STRING(symLiteral)) );
|
SDL_Keycode keycode = SDL_GetKeyFromName( Toy_toCString(TOY_AS_STRING(symLiteral)) );
|
||||||
|
|
||||||
if (keycode == SDLK_UNKNOWN) {
|
if (keycode == SDLK_UNKNOWN) {
|
||||||
interpreter->errorOutput("Unknown key found: ");
|
interpreter->errorOutput("Unknown key found: ");
|
||||||
@@ -42,35 +42,35 @@ static int nativeMapInputEventToKey(Interpreter* interpreter, LiteralArray* argu
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)keycode );
|
Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)keycode );
|
||||||
|
|
||||||
//save the sym-event pair
|
//save the sym-event pair
|
||||||
setLiteralDictionary(symKeyEventsPtr, keycodeLiteral, evtLiteral); //I could possibly map multiple events to one sym
|
Toy_setLiteralDictionary(symKeyEventsPtr, keycodeLiteral, evtLiteral); //I could possibly map multiple events to one sym
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(symLiteral);
|
Toy_freeLiteral(symLiteral);
|
||||||
freeLiteral(evtLiteral);
|
Toy_freeLiteral(evtLiteral);
|
||||||
freeLiteral(keycodeLiteral);
|
Toy_freeLiteral(keycodeLiteral);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//dry wrappers
|
//dry wrappers
|
||||||
static int nativeMapInputEventToKeyDown(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeMapInputEventToKeyDown(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyDownEvents, "mapInputEventToKeyDown");
|
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyDownEvents, "mapInputEventToKeyDown");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeMapInputEventToKeyUp(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeMapInputEventToKeyUp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyUpEvents, "mapInputEventToKeyUp");
|
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyUpEvents, "mapInputEventToKeyUp");
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the hook
|
//call the hook
|
||||||
typedef struct Natives {
|
typedef struct Natives {
|
||||||
char* name;
|
char* name;
|
||||||
NativeFn fn;
|
Toy_NativeFn fn;
|
||||||
} Natives;
|
} Natives;
|
||||||
|
|
||||||
int hookInput(Interpreter* interpreter, Literal identifier, Literal alias) {
|
int Box_hookInput(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
{"mapInputEventToKeyDown", nativeMapInputEventToKeyDown},
|
{"mapInputEventToKeyDown", nativeMapInputEventToKeyDown},
|
||||||
@@ -80,51 +80,51 @@ int hookInput(Interpreter* interpreter, Literal identifier, Literal alias) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//store the library in an aliased dictionary
|
//store the library in an aliased dictionary
|
||||||
if (!IS_NULL(alias)) {
|
if (!TOY_IS_NULL(alias)) {
|
||||||
//make sure the name isn't taken
|
//make sure the name isn't taken
|
||||||
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
interpreter->errorOutput("Can't override an existing variable\n");
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
freeLiteral(alias);
|
Toy_freeLiteral(alias);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the dictionary to load up with functions
|
//create the dictionary to load up with functions
|
||||||
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
initLiteralDictionary(dictionary);
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
//load the dict with functions
|
//load the dict with functions
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
func.type = LITERAL_FUNCTION_NATIVE;
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
setLiteralDictionary(dictionary, name, func);
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
freeLiteral(name);
|
Toy_freeLiteral(name);
|
||||||
freeLiteral(func);
|
Toy_freeLiteral(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
//build the type
|
//build the type
|
||||||
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
TYPE_PUSH_SUBTYPE(&type, strType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
TYPE_PUSH_SUBTYPE(&type, fnType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
//set scope
|
//set scope
|
||||||
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
declareScopeVariable(interpreter->scope, alias, type);
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
setScopeVariable(interpreter->scope, alias, dict, false);
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(dict);
|
Toy_freeLiteral(dict);
|
||||||
freeLiteral(type);
|
Toy_freeLiteral(type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//default
|
//default
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
int hookInput(Interpreter* interpreter, Literal identifier, Literal alias);
|
int Box_hookInput(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
|
|||||||
554
box/lib_node.c
554
box/lib_node.c
@@ -1,604 +1,604 @@
|
|||||||
#include "lib_node.h"
|
#include "lib_node.h"
|
||||||
|
|
||||||
#include "engine.h"
|
#include "box_engine_node.h"
|
||||||
#include "engine_node.h"
|
#include "box_engine.h"
|
||||||
#include "repl_tools.h"
|
|
||||||
|
|
||||||
#include "memory.h"
|
#include "repl_tools.h"
|
||||||
#include "literal_array.h"
|
#include "toy_literal_array.h"
|
||||||
|
#include "toy_memory.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int nativeLoadNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal fname = popLiteralArray(arguments);
|
Toy_Literal fname = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal fnameIdn = fname;
|
Toy_Literal fnameIdn = fname;
|
||||||
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
|
if (TOY_IS_IDENTIFIER(fname) && Toy_parseIdentifierToValue(interpreter, &fname)) {
|
||||||
freeLiteral(fnameIdn);
|
Toy_freeLiteral(fnameIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_STRING(fname)) {
|
if (!TOY_IS_STRING(fname)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to loadNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to loadNode\n");
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//load the new node
|
//load the new node
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = readFile(toCString(AS_STRING(fname)), &size);
|
char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(fname)), &size);
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = Toy_compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
EngineNode* node = ALLOCATE(EngineNode, 1);
|
Box_EngineNode* node = TOY_ALLOCATE(Box_EngineNode, 1);
|
||||||
|
|
||||||
//BUGFIX: make an inner-interpreter
|
//BUGFIX: make an inner-interpreter
|
||||||
Interpreter inner;
|
Toy_Interpreter inner;
|
||||||
|
|
||||||
//init the inner interpreter manually
|
//init the inner interpreter manually
|
||||||
initLiteralArray(&inner.literalCache);
|
Toy_initLiteralArray(&inner.literalCache);
|
||||||
inner.scope = pushScope(NULL);
|
inner.scope = Toy_pushScope(NULL);
|
||||||
inner.bytecode = tb;
|
inner.bytecode = tb;
|
||||||
inner.length = size;
|
inner.length = size;
|
||||||
inner.count = 0;
|
inner.count = 0;
|
||||||
inner.codeStart = -1;
|
inner.codeStart = -1;
|
||||||
inner.depth = interpreter->depth + 1;
|
inner.depth = interpreter->depth + 1;
|
||||||
inner.panic = false;
|
inner.panic = false;
|
||||||
initLiteralArray(&inner.stack);
|
Toy_initLiteralArray(&inner.stack);
|
||||||
inner.hooks = interpreter->hooks;
|
inner.hooks = interpreter->hooks;
|
||||||
setInterpreterPrint(&inner, interpreter->printOutput);
|
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
||||||
setInterpreterAssert(&inner, interpreter->assertOutput);
|
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||||
setInterpreterError(&inner, interpreter->errorOutput);
|
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
||||||
|
|
||||||
initEngineNode(node, &inner, tb, size);
|
Box_initEngineNode(node, &inner, tb, size);
|
||||||
|
|
||||||
// return the node
|
// return the node
|
||||||
Literal nodeLiteral = TO_OPAQUE_LITERAL(node, node->tag);
|
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||||
pushLiteralArray(&interpreter->stack, nodeLiteral);
|
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteralArray(&inner.stack);
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
freeLiteralArray(&inner.literalCache);
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeInitNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeInitNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to initNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to initNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal node = popLiteralArray(arguments);
|
Toy_Literal node = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = node;
|
Toy_Literal nodeIdn = node;
|
||||||
if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) {
|
if (TOY_IS_IDENTIFIER(node) && Toy_parseIdentifierToValue(interpreter, &node)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_OPAQUE(node)) {
|
if (!TOY_IS_OPAQUE(node)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to initNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to initNode\n");
|
||||||
freeLiteral(node);
|
Toy_freeLiteral(node);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineNode* engineNode = AS_OPAQUE(node);
|
Box_EngineNode* engineNode = TOY_AS_OPAQUE(node);
|
||||||
|
|
||||||
//init the new node (and ONLY this node)
|
//init the new node (and ONLY this node)
|
||||||
callEngineNode(engineNode, &engine.interpreter, "onInit", NULL);
|
Box_callEngineNode(engineNode, &engine.interpreter, "onInit", NULL);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(node);
|
Toy_freeLiteral(node);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeFreeChildNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal index = popLiteralArray(arguments);
|
Toy_Literal index = Toy_popLiteralArray(arguments);
|
||||||
Literal node = popLiteralArray(arguments);
|
Toy_Literal node = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = node; //annoying
|
Toy_Literal nodeIdn = node; //annoying
|
||||||
if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) {
|
if (TOY_IS_IDENTIFIER(node) && Toy_parseIdentifierToValue(interpreter, &node)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_OPAQUE(node) || !IS_INTEGER(index)) {
|
if (!TOY_IS_OPAQUE(node) || !TOY_IS_INTEGER(index)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n");
|
||||||
freeLiteral(node);
|
Toy_freeLiteral(node);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineNode* parentNode = AS_OPAQUE(node);
|
Box_EngineNode* parentNode = TOY_AS_OPAQUE(node);
|
||||||
int idx = AS_INTEGER(index);
|
int idx = TOY_AS_INTEGER(index);
|
||||||
|
|
||||||
//check bounds
|
//check bounds
|
||||||
if (idx < 0 || idx >= parentNode->count) {
|
if (idx < 0 || idx >= parentNode->count) {
|
||||||
interpreter->errorOutput("Node index out of bounds in freeChildNode\n");
|
interpreter->errorOutput("Node index out of bounds in freeChildNode\n");
|
||||||
freeLiteral(node);
|
Toy_freeLiteral(node);
|
||||||
freeLiteral(index);
|
Toy_freeLiteral(index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the child node
|
//get the child node
|
||||||
EngineNode* childNode = parentNode->children[idx];
|
Box_EngineNode* childNode = parentNode->children[idx];
|
||||||
|
|
||||||
//free the node
|
//free the node
|
||||||
if (childNode != NULL) {
|
if (childNode != NULL) {
|
||||||
callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL);
|
Box_callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL);
|
||||||
freeEngineNode(childNode);
|
Box_freeEngineNode(childNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
parentNode->children[idx] = NULL;
|
parentNode->children[idx] = NULL;
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(node);
|
Toy_freeLiteral(node);
|
||||||
freeLiteral(index);
|
Toy_freeLiteral(index);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativePushNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativePushNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal child = popLiteralArray(arguments);
|
Toy_Literal child = Toy_popLiteralArray(arguments);
|
||||||
Literal parent = popLiteralArray(arguments);
|
Toy_Literal parent = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal parentIdn = parent;
|
Toy_Literal parentIdn = parent;
|
||||||
if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) {
|
if (TOY_IS_IDENTIFIER(parent) && Toy_parseIdentifierToValue(interpreter, &parent)) {
|
||||||
freeLiteral(parentIdn);
|
Toy_freeLiteral(parentIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal childIdn = child;
|
Toy_Literal childIdn = child;
|
||||||
if (IS_IDENTIFIER(child) && parseIdentifierToValue(interpreter, &child)) {
|
if (TOY_IS_IDENTIFIER(child) && Toy_parseIdentifierToValue(interpreter, &child)) {
|
||||||
freeLiteral(childIdn);
|
Toy_freeLiteral(childIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_OPAQUE(parent) || !IS_OPAQUE(child)) {
|
if (!TOY_IS_OPAQUE(parent) || !TOY_IS_OPAQUE(child)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to pushNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to pushNode\n");
|
||||||
freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
freeLiteral(child);
|
Toy_freeLiteral(child);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//push the node
|
//push the node
|
||||||
EngineNode* parentNode = AS_OPAQUE(parent);
|
Box_EngineNode* parentNode = TOY_AS_OPAQUE(parent);
|
||||||
EngineNode* childNode = AS_OPAQUE(child);
|
Box_EngineNode* childNode = TOY_AS_OPAQUE(child);
|
||||||
|
|
||||||
pushEngineNode(parentNode, childNode);
|
Box_pushEngineNode(parentNode, childNode);
|
||||||
|
|
||||||
//no return value
|
//no return value
|
||||||
freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
freeLiteral(child);
|
Toy_freeLiteral(child);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeGetNodeChild(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeGetNodeChild(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to getNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to getNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal index = popLiteralArray(arguments);
|
Toy_Literal index = Toy_popLiteralArray(arguments);
|
||||||
Literal parent = popLiteralArray(arguments);
|
Toy_Literal parent = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal parentIdn = parent;
|
Toy_Literal parentIdn = parent;
|
||||||
if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) {
|
if (TOY_IS_IDENTIFIER(parent) && Toy_parseIdentifierToValue(interpreter, &parent)) {
|
||||||
freeLiteral(parentIdn);
|
Toy_freeLiteral(parentIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_OPAQUE(parent) || !IS_INTEGER(index)) {
|
if (!TOY_IS_OPAQUE(parent) || !TOY_IS_INTEGER(index)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to getNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to getNode\n");
|
||||||
freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
freeLiteral(index);
|
Toy_freeLiteral(index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//push the node
|
//push the node
|
||||||
EngineNode* parentNode = AS_OPAQUE(parent);
|
Box_EngineNode* parentNode = TOY_AS_OPAQUE(parent);
|
||||||
int intIndex = AS_INTEGER(index);
|
int intIndex = TOY_AS_INTEGER(index);
|
||||||
|
|
||||||
if (intIndex < 0 || intIndex >= parentNode->count) {
|
if (intIndex < 0 || intIndex >= parentNode->count) {
|
||||||
interpreter->errorOutput("index out of bounds in getNode\n");
|
interpreter->errorOutput("index out of bounds in getNode\n");
|
||||||
freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
freeLiteral(index);
|
Toy_freeLiteral(index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineNode* childNode = parentNode->children[intIndex];
|
Box_EngineNode* childNode = parentNode->children[intIndex];
|
||||||
Literal child = TO_OPAQUE_LITERAL(childNode, childNode->tag);
|
Toy_Literal child = TOY_TO_OPAQUE_LITERAL(childNode, childNode->tag);
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, child);
|
Toy_pushLiteralArray(&interpreter->stack, child);
|
||||||
|
|
||||||
//no return value
|
//no return value
|
||||||
freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
freeLiteral(child);
|
Toy_freeLiteral(child);
|
||||||
freeLiteral(index);
|
Toy_freeLiteral(index);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeGetNodeParent(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeGetNodeParent(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to getNodeParent\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to getNodeParent\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_OPAQUE(nodeLiteral)) {
|
if (!TOY_IS_OPAQUE(nodeLiteral)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to getNodeParent\n");
|
interpreter->errorOutput("Incorrect argument type passed to getNodeParent\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//push the node
|
//push the node
|
||||||
EngineNode* node = AS_OPAQUE(nodeLiteral);
|
Box_EngineNode* node = TOY_AS_OPAQUE(nodeLiteral);
|
||||||
EngineNode* parent = node->parent;
|
Box_EngineNode* parent = node->parent;
|
||||||
|
|
||||||
Literal parentLiteral = TO_NULL_LITERAL;
|
Toy_Literal parentLiteral = TOY_TO_NULL_LITERAL;
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
parentLiteral = TO_OPAQUE_LITERAL(parent, parent->tag);
|
parentLiteral = TOY_TO_OPAQUE_LITERAL(parent, parent->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, parentLiteral);
|
Toy_pushLiteralArray(&interpreter->stack, parentLiteral);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(parentLiteral);
|
Toy_freeLiteral(parentLiteral);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeLoadTexture(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeLoadTexture(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to loadTextureEngineNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to loadTextureEngineNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal fname = popLiteralArray(arguments);
|
Toy_Literal fname = Toy_popLiteralArray(arguments);
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal fnameIdn = fname;
|
Toy_Literal fnameIdn = fname;
|
||||||
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
|
if (TOY_IS_IDENTIFIER(fname) && Toy_parseIdentifierToValue(interpreter, &fname)) {
|
||||||
freeLiteral(fnameIdn);
|
Toy_freeLiteral(fnameIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_STRING(fname) || !IS_OPAQUE(nodeLiteral)) {
|
if (!TOY_IS_STRING(fname) || !TOY_IS_OPAQUE(nodeLiteral)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to loadTextureEngineNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to loadTextureEngineNode\n");
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually load TODO: number the opaques, and check the numbers
|
//actually load TODO: number the opaques, and check the numbers
|
||||||
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
|
Box_EngineNode* node = (Box_EngineNode*)TOY_AS_OPAQUE(nodeLiteral);
|
||||||
|
|
||||||
if (node->texture != NULL) {
|
if (node->texture != NULL) {
|
||||||
freeTextureEngineNode(node);
|
Box_freeTextureEngineNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadTextureEngineNode(node, toCString(AS_STRING(fname))) != 0) {
|
if (Box_loadTextureEngineNode(node, Toy_toCString(TOY_AS_STRING(fname))) != 0) {
|
||||||
interpreter->errorOutput("Failed to load the texture into the EngineNode\n");
|
interpreter->errorOutput("Failed to load the texture into the EngineNode\n");
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(fname);
|
Toy_freeLiteral(fname);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeFreeTexture(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeFreeTexture(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to freeTextureEngineNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to freeTextureEngineNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_OPAQUE(nodeLiteral)) {
|
if (!TOY_IS_OPAQUE(nodeLiteral)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to freeTextureEngineNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to freeTextureEngineNode\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually load TODO: number the opaques, and check the numbers
|
//actually load TODO: number the opaques, and check the numbers
|
||||||
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
|
Box_EngineNode* node = (Box_EngineNode*)TOY_AS_OPAQUE(nodeLiteral);
|
||||||
|
|
||||||
if (node->texture != NULL) {
|
if (node->texture != NULL) {
|
||||||
freeTextureEngineNode(node);
|
Box_freeTextureEngineNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeSetRect(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeSetRect(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 5) {
|
if (arguments->count != 5) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to setRectEngineNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to setRectEngineNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal h = popLiteralArray(arguments);
|
Toy_Literal h = Toy_popLiteralArray(arguments);
|
||||||
Literal w = popLiteralArray(arguments);
|
Toy_Literal w = Toy_popLiteralArray(arguments);
|
||||||
Literal y = popLiteralArray(arguments);
|
Toy_Literal y = Toy_popLiteralArray(arguments);
|
||||||
Literal x = popLiteralArray(arguments);
|
Toy_Literal x = Toy_popLiteralArray(arguments);
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal xi = x;
|
Toy_Literal xi = x;
|
||||||
if (IS_IDENTIFIER(x) && parseIdentifierToValue(interpreter, &x)) {
|
if (TOY_IS_IDENTIFIER(x) && Toy_parseIdentifierToValue(interpreter, &x)) {
|
||||||
freeLiteral(xi);
|
Toy_freeLiteral(xi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal yi = y;
|
Toy_Literal yi = y;
|
||||||
if (IS_IDENTIFIER(y) && parseIdentifierToValue(interpreter, &y)) {
|
if (TOY_IS_IDENTIFIER(y) && Toy_parseIdentifierToValue(interpreter, &y)) {
|
||||||
freeLiteral(yi);
|
Toy_freeLiteral(yi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal wi = w;
|
Toy_Literal wi = w;
|
||||||
if (IS_IDENTIFIER(w) && parseIdentifierToValue(interpreter, &w)) {
|
if (TOY_IS_IDENTIFIER(w) && Toy_parseIdentifierToValue(interpreter, &w)) {
|
||||||
freeLiteral(wi);
|
Toy_freeLiteral(wi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal hi = h;
|
Toy_Literal hi = h;
|
||||||
if (IS_IDENTIFIER(h) && parseIdentifierToValue(interpreter, &h)) {
|
if (TOY_IS_IDENTIFIER(h) && Toy_parseIdentifierToValue(interpreter, &h)) {
|
||||||
freeLiteral(hi);
|
Toy_freeLiteral(hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_OPAQUE(nodeLiteral) || !IS_INTEGER(x) || !IS_INTEGER(y) || !IS_INTEGER(w) || !IS_INTEGER(h)) {
|
if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(x) || !TOY_IS_INTEGER(y) || !TOY_IS_INTEGER(w) || !TOY_IS_INTEGER(h)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to setRectEngineNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to setRectEngineNode\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(x);
|
Toy_freeLiteral(x);
|
||||||
freeLiteral(y);
|
Toy_freeLiteral(y);
|
||||||
freeLiteral(w);
|
Toy_freeLiteral(w);
|
||||||
freeLiteral(h);
|
Toy_freeLiteral(h);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually set
|
//actually set
|
||||||
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
|
Box_EngineNode* node = (Box_EngineNode*)TOY_AS_OPAQUE(nodeLiteral);
|
||||||
|
|
||||||
SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), AS_INTEGER(w), AS_INTEGER(h)};
|
SDL_Rect r = {TOY_AS_INTEGER(x), TOY_AS_INTEGER(y), TOY_AS_INTEGER(w), TOY_AS_INTEGER(h)};
|
||||||
setRectEngineNode(node, r);
|
Box_setRectEngineNode(node, r);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(x);
|
Toy_freeLiteral(x);
|
||||||
freeLiteral(y);
|
Toy_freeLiteral(y);
|
||||||
freeLiteral(w);
|
Toy_freeLiteral(w);
|
||||||
freeLiteral(h);
|
Toy_freeLiteral(h);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: get x, y, w, h
|
//TODO: get x, y, w, h
|
||||||
|
|
||||||
static int nativeDrawNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeDrawNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
if (arguments->count != 3 && arguments->count != 5) {
|
if (arguments->count != 3 && arguments->count != 5) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to drawEngineNode\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to drawEngineNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the arguments
|
//extract the arguments
|
||||||
Literal w = TO_NULL_LITERAL, h = TO_NULL_LITERAL;
|
Toy_Literal w = TOY_TO_NULL_LITERAL, h = TOY_TO_NULL_LITERAL;
|
||||||
if (arguments->count == 5) {
|
if (arguments->count == 5) {
|
||||||
h = popLiteralArray(arguments);
|
h = Toy_popLiteralArray(arguments);
|
||||||
w = popLiteralArray(arguments);
|
w = Toy_popLiteralArray(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal y = popLiteralArray(arguments);
|
Toy_Literal y = Toy_popLiteralArray(arguments);
|
||||||
Literal x = popLiteralArray(arguments);
|
Toy_Literal x = Toy_popLiteralArray(arguments);
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal xi = x;
|
Toy_Literal xi = x;
|
||||||
if (IS_IDENTIFIER(x) && parseIdentifierToValue(interpreter, &x)) {
|
if (TOY_IS_IDENTIFIER(x) && Toy_parseIdentifierToValue(interpreter, &x)) {
|
||||||
freeLiteral(xi);
|
Toy_freeLiteral(xi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal yi = y;
|
Toy_Literal yi = y;
|
||||||
if (IS_IDENTIFIER(y) && parseIdentifierToValue(interpreter, &y)) {
|
if (TOY_IS_IDENTIFIER(y) && Toy_parseIdentifierToValue(interpreter, &y)) {
|
||||||
freeLiteral(yi);
|
Toy_freeLiteral(yi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal wi = w;
|
Toy_Literal wi = w;
|
||||||
if (IS_IDENTIFIER(w) && parseIdentifierToValue(interpreter, &w)) {
|
if (TOY_IS_IDENTIFIER(w) && Toy_parseIdentifierToValue(interpreter, &w)) {
|
||||||
freeLiteral(wi);
|
Toy_freeLiteral(wi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal hi = h;
|
Toy_Literal hi = h;
|
||||||
if (IS_IDENTIFIER(h) && parseIdentifierToValue(interpreter, &h)) {
|
if (TOY_IS_IDENTIFIER(h) && Toy_parseIdentifierToValue(interpreter, &h)) {
|
||||||
freeLiteral(hi);
|
Toy_freeLiteral(hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check argument types
|
//check argument types
|
||||||
if (!IS_OPAQUE(nodeLiteral) || !IS_INTEGER(x) || !IS_INTEGER(y) || (!IS_INTEGER(w) && !IS_NULL(w)) || (!IS_INTEGER(h) && !IS_NULL(h))) {
|
if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(x) || !TOY_IS_INTEGER(y) || (!TOY_IS_INTEGER(w) && !TOY_IS_NULL(w)) || (!TOY_IS_INTEGER(h) && !TOY_IS_NULL(h))) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to drawEngineNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to drawEngineNode\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(x);
|
Toy_freeLiteral(x);
|
||||||
freeLiteral(y);
|
Toy_freeLiteral(y);
|
||||||
freeLiteral(w);
|
Toy_freeLiteral(w);
|
||||||
freeLiteral(h);
|
Toy_freeLiteral(h);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually render
|
//actually render
|
||||||
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
|
Box_EngineNode* node = (Box_EngineNode*)TOY_AS_OPAQUE(nodeLiteral);
|
||||||
|
|
||||||
SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), 0, 0};
|
SDL_Rect r = {TOY_AS_INTEGER(x), TOY_AS_INTEGER(y), 0, 0};
|
||||||
if (IS_INTEGER(w) && IS_INTEGER(h)) {
|
if (TOY_IS_INTEGER(w) && TOY_IS_INTEGER(h)) {
|
||||||
r.w = AS_INTEGER(w);
|
r.w = TOY_AS_INTEGER(w);
|
||||||
r.h = AS_INTEGER(h);
|
r.h = TOY_AS_INTEGER(h);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r.w = node->rect.w;
|
r.w = node->rect.w;
|
||||||
r.h = node->rect.h;
|
r.h = node->rect.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawEngineNode(node, r);
|
Box_drawEngineNode(node, r);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(x);
|
Toy_freeLiteral(x);
|
||||||
freeLiteral(y);
|
Toy_freeLiteral(y);
|
||||||
freeLiteral(w);
|
Toy_freeLiteral(w);
|
||||||
freeLiteral(h);
|
Toy_freeLiteral(h);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeGetNodeTag(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeGetNodeTag(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to getNodeTag\n");
|
interpreter->errorOutput("Incorrect number of arguments passed to getNodeTag\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_OPAQUE(nodeLiteral)) {
|
if (!TOY_IS_OPAQUE(nodeLiteral)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to getNodeTag\n");
|
interpreter->errorOutput("Incorrect argument type passed to getNodeTag\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//push the tag
|
//push the tag
|
||||||
Literal tagLiteral = TO_INTEGER_LITERAL( ((EngineNode*)AS_OPAQUE(nodeLiteral))->tag );
|
Toy_Literal tagLiteral = TOY_TO_INTEGER_LITERAL( ((Box_EngineNode*)TOY_AS_OPAQUE(nodeLiteral))->tag );
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, tagLiteral);
|
Toy_pushLiteralArray(&interpreter->stack, tagLiteral);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(tagLiteral);
|
Toy_freeLiteral(tagLiteral);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeCallNode(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeCallNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count < 2) {
|
if (arguments->count < 2) {
|
||||||
interpreter->errorOutput("Too few arguments passed to callEngineNode\n");
|
interpreter->errorOutput("Too few arguments passed to callEngineNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LiteralArray extraArgs;
|
Toy_LiteralArray extraArgs;
|
||||||
initLiteralArray(&extraArgs);
|
Toy_initLiteralArray(&extraArgs);
|
||||||
|
|
||||||
LiteralArray flippedExtraArgs;
|
Toy_LiteralArray flippedExtraArgs;
|
||||||
initLiteralArray(&flippedExtraArgs);
|
Toy_initLiteralArray(&flippedExtraArgs);
|
||||||
|
|
||||||
//extract the extra arg values
|
//extract the extra arg values
|
||||||
while (arguments->count > 2) {
|
while (arguments->count > 2) {
|
||||||
Literal tmp = popLiteralArray(arguments);
|
Toy_Literal tmp = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal idn = tmp; //there's almost certainly a better way of doing all of this stuff
|
Toy_Literal idn = tmp; //there's almost certainly a better way of doing all of this stuff
|
||||||
if (IS_IDENTIFIER(tmp) && parseIdentifierToValue(interpreter, &tmp)) {
|
if (TOY_IS_IDENTIFIER(tmp) && Toy_parseIdentifierToValue(interpreter, &tmp)) {
|
||||||
freeLiteral(idn);
|
Toy_freeLiteral(idn);
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(&flippedExtraArgs, tmp);
|
Toy_pushLiteralArray(&flippedExtraArgs, tmp);
|
||||||
freeLiteral(tmp);
|
Toy_freeLiteral(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//correct the order
|
//correct the order
|
||||||
while (flippedExtraArgs.count) {
|
while (flippedExtraArgs.count) {
|
||||||
Literal tmp = popLiteralArray(&flippedExtraArgs);
|
Toy_Literal tmp = Toy_popLiteralArray(&flippedExtraArgs);
|
||||||
pushLiteralArray(&extraArgs, tmp);
|
Toy_pushLiteralArray(&extraArgs, tmp);
|
||||||
freeLiteral(tmp);
|
Toy_freeLiteral(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeLiteralArray(&flippedExtraArgs);
|
Toy_freeLiteralArray(&flippedExtraArgs);
|
||||||
|
|
||||||
//back on track
|
//back on track
|
||||||
Literal fnName = popLiteralArray(arguments);
|
Toy_Literal fnName = Toy_popLiteralArray(arguments);
|
||||||
Literal nodeLiteral = popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
Literal nodeIdn = nodeLiteral;
|
Toy_Literal nodeIdn = nodeLiteral;
|
||||||
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||||
freeLiteral(nodeIdn);
|
Toy_freeLiteral(nodeIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal fnNameIdn = fnName;
|
Toy_Literal fnNameIdn = fnName;
|
||||||
if (IS_IDENTIFIER(fnName) && parseIdentifierToValue(interpreter, &fnName)) {
|
if (TOY_IS_IDENTIFIER(fnName) && Toy_parseIdentifierToValue(interpreter, &fnName)) {
|
||||||
freeLiteral(fnNameIdn);
|
Toy_freeLiteral(fnNameIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_OPAQUE(nodeLiteral) || !IS_STRING(fnName)) {
|
if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_STRING(fnName)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to callEngineNode\n");
|
interpreter->errorOutput("Incorrect argument type passed to callEngineNode\n");
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(fnName);
|
Toy_freeLiteral(fnName);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//allow refstring to do it's magic
|
//allow refstring to do it's magic
|
||||||
Literal fnNameIdentifier = TO_IDENTIFIER_LITERAL(copyRefString(AS_STRING(fnName)));
|
Toy_Literal fnNameIdentifier = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(fnName)));
|
||||||
|
|
||||||
//call the function
|
//call the function
|
||||||
Literal result = callEngineNodeLiteral(AS_OPAQUE(nodeLiteral), interpreter, fnNameIdentifier, &extraArgs);
|
Toy_Literal result = Box_callEngineNodeLiteral(TOY_AS_OPAQUE(nodeLiteral), interpreter, fnNameIdentifier, &extraArgs);
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, result);
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteralArray(&extraArgs);
|
Toy_freeLiteralArray(&extraArgs);
|
||||||
freeLiteral(nodeLiteral);
|
Toy_freeLiteral(nodeLiteral);
|
||||||
freeLiteral(fnName);
|
Toy_freeLiteral(fnName);
|
||||||
freeLiteral(result);
|
Toy_freeLiteral(result);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -606,10 +606,10 @@ static int nativeCallNode(Interpreter* interpreter, LiteralArray* arguments) {
|
|||||||
//call the hook
|
//call the hook
|
||||||
typedef struct Natives {
|
typedef struct Natives {
|
||||||
char* name;
|
char* name;
|
||||||
NativeFn fn;
|
Toy_NativeFn fn;
|
||||||
} Natives;
|
} Natives;
|
||||||
|
|
||||||
int hookNode(Interpreter* interpreter, Literal identifier, Literal alias) {
|
int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
{"loadNode", nativeLoadNode},
|
{"loadNode", nativeLoadNode},
|
||||||
@@ -628,51 +628,51 @@ int hookNode(Interpreter* interpreter, Literal identifier, Literal alias) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//store the library in an aliased dictionary
|
//store the library in an aliased dictionary
|
||||||
if (!IS_NULL(alias)) {
|
if (!TOY_IS_NULL(alias)) {
|
||||||
//make sure the name isn't taken
|
//make sure the name isn't taken
|
||||||
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
interpreter->errorOutput("Can't override an existing variable\n");
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
freeLiteral(alias);
|
Toy_freeLiteral(alias);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the dictionary to load up with functions
|
//create the dictionary to load up with functions
|
||||||
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
initLiteralDictionary(dictionary);
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
//load the dict with functions
|
//load the dict with functions
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
func.type = LITERAL_FUNCTION_NATIVE;
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
setLiteralDictionary(dictionary, name, func);
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
freeLiteral(name);
|
Toy_freeLiteral(name);
|
||||||
freeLiteral(func);
|
Toy_freeLiteral(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
//build the type
|
//build the type
|
||||||
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
TYPE_PUSH_SUBTYPE(&type, strType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
TYPE_PUSH_SUBTYPE(&type, fnType);
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
//set scope
|
//set scope
|
||||||
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
declareScopeVariable(interpreter->scope, alias, type);
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
setScopeVariable(interpreter->scope, alias, dict, false);
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
freeLiteral(dict);
|
Toy_freeLiteral(dict);
|
||||||
freeLiteral(type);
|
Toy_freeLiteral(type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//default
|
//default
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
int hookNode(Interpreter* interpreter, Literal identifier, Literal alias);
|
int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
|
|||||||
613
box/lib_runner.c
Normal file
613
box/lib_runner.c
Normal file
@@ -0,0 +1,613 @@
|
|||||||
|
#include "lib_runner.h"
|
||||||
|
|
||||||
|
#include "toy_memory.h"
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
#include "repl_tools.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct Toy_Runner {
|
||||||
|
Toy_Interpreter interpreter;
|
||||||
|
unsigned char* bytecode;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
bool dirty;
|
||||||
|
} Toy_Runner;
|
||||||
|
|
||||||
|
//Toy native functions
|
||||||
|
static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to loadScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the argument
|
||||||
|
Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral));
|
||||||
|
|
||||||
|
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
||||||
|
int driveLength = 0;
|
||||||
|
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
||||||
|
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
||||||
|
interpreter->errorOutput("Incorrect drive path format given to loadScript\n");
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_RefString* drive = Toy_createRefStringLength(Toy_toCString(drivePath), driveLength);
|
||||||
|
Toy_RefString* path = Toy_createRefStringLength( &Toy_toCString(drivePath)[driveLength + 1], Toy_lengthRefString(drivePath) - driveLength );
|
||||||
|
|
||||||
|
//get the real drive file path
|
||||||
|
Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString
|
||||||
|
Toy_Literal realDriveLiteral = Toy_getLiteralDictionary(Toy_getDriveDictionary(), driveLiteral);
|
||||||
|
|
||||||
|
if (!TOY_IS_STRING(realDriveLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect literal type found for drive: ");
|
||||||
|
Toy_printLiteralCustom(realDriveLiteral, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\n");
|
||||||
|
Toy_freeLiteral(realDriveLiteral);
|
||||||
|
Toy_freeLiteral(driveLiteral);
|
||||||
|
Toy_deleteRefString(path);
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the final real file path (concat) TODO: move this concat to refstring library
|
||||||
|
Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral));
|
||||||
|
int realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
|
||||||
|
|
||||||
|
char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null
|
||||||
|
snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path));
|
||||||
|
|
||||||
|
//clean up the drivepath stuff
|
||||||
|
Toy_deleteRefString(realDrive);
|
||||||
|
Toy_freeLiteral(realDriveLiteral);
|
||||||
|
Toy_freeLiteral(driveLiteral);
|
||||||
|
Toy_deleteRefString(path);
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
|
//check for file extensions
|
||||||
|
if (!(filePath[realLength - 5] == '.' && filePath[realLength - 4] == 't' && filePath[realLength - 3] == 'o' && filePath[realLength - 2] == 'y')) {
|
||||||
|
interpreter->errorOutput("Bad script file extension (expected .toy)\n");
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for break-out attempts
|
||||||
|
for (int i = 0; i < realLength - 1; i++) {
|
||||||
|
if (filePath[i] == '.' && filePath[i + 1] == '.') {
|
||||||
|
interpreter->errorOutput("Parent directory access not allowed\n");
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//load and compile the bytecode
|
||||||
|
size_t fileSize = 0;
|
||||||
|
char* source = Toy_readFile(filePath, &fileSize);
|
||||||
|
|
||||||
|
if (!source) {
|
||||||
|
interpreter->errorOutput("Failed to load source file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* bytecode = Toy_compileString(source, &fileSize);
|
||||||
|
free((void*)source);
|
||||||
|
|
||||||
|
if (!bytecode) {
|
||||||
|
interpreter->errorOutput("Failed to compile source file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the runner object
|
||||||
|
Toy_Runner* runner = TOY_ALLOCATE(Toy_Runner, 1);
|
||||||
|
Toy_setInterpreterPrint(&runner->interpreter, interpreter->printOutput);
|
||||||
|
Toy_setInterpreterAssert(&runner->interpreter, interpreter->assertOutput);
|
||||||
|
Toy_setInterpreterError(&runner->interpreter, interpreter->errorOutput);
|
||||||
|
runner->interpreter.hooks = interpreter->hooks;
|
||||||
|
runner->interpreter.scope = NULL;
|
||||||
|
Toy_resetInterpreter(&runner->interpreter);
|
||||||
|
runner->bytecode = bytecode;
|
||||||
|
runner->size = fileSize;
|
||||||
|
runner->dirty = false;
|
||||||
|
|
||||||
|
//build the opaque object, and push it to the stack
|
||||||
|
Toy_Literal runnerLiteral = TOY_TO_OPAQUE_LITERAL(runner, TOY_OPAQUE_TAG_RUNNER);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, runnerLiteral);
|
||||||
|
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to loadScriptBytecode\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the argument
|
||||||
|
Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral));
|
||||||
|
|
||||||
|
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
||||||
|
int driveLength = 0;
|
||||||
|
while (Toy_toCString(drivePath)[driveLength] != ':') {
|
||||||
|
if (driveLength >= Toy_lengthRefString(drivePath)) {
|
||||||
|
interpreter->errorOutput("Incorrect drive path format given to loadScriptBytecode\n");
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_RefString* drive = Toy_createRefStringLength(Toy_toCString(drivePath), driveLength);
|
||||||
|
Toy_RefString* path = Toy_createRefStringLength( &Toy_toCString(drivePath)[driveLength + 1], Toy_lengthRefString(drivePath) - driveLength );
|
||||||
|
|
||||||
|
//get the real drive file path
|
||||||
|
Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString
|
||||||
|
Toy_Literal realDriveLiteral = Toy_getLiteralDictionary(Toy_getDriveDictionary(), driveLiteral);
|
||||||
|
|
||||||
|
if (!TOY_IS_STRING(realDriveLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect literal type found for drive: ");
|
||||||
|
Toy_printLiteralCustom(realDriveLiteral, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\n");
|
||||||
|
Toy_freeLiteral(realDriveLiteral);
|
||||||
|
Toy_freeLiteral(driveLiteral);
|
||||||
|
Toy_deleteRefString(path);
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the final real file path (concat) TODO: move this concat to refstring library
|
||||||
|
Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral));
|
||||||
|
int realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path);
|
||||||
|
|
||||||
|
char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null
|
||||||
|
snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path));
|
||||||
|
|
||||||
|
//clean up the drivepath stuff
|
||||||
|
Toy_deleteRefString(realDrive);
|
||||||
|
Toy_freeLiteral(realDriveLiteral);
|
||||||
|
Toy_freeLiteral(driveLiteral);
|
||||||
|
Toy_deleteRefString(path);
|
||||||
|
Toy_deleteRefString(drivePath);
|
||||||
|
Toy_freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
|
//check for file extensions
|
||||||
|
if (!(filePath[realLength - 4] == '.' && filePath[realLength - 3] == 't' && filePath[realLength - 2] == 'b')) {
|
||||||
|
interpreter->errorOutput("Bad binary file extension (expected .tb)\n");
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for break-out attempts
|
||||||
|
for (int i = 0; i < realLength - 1; i++) {
|
||||||
|
if (filePath[i] == '.' && filePath[i + 1] == '.') {
|
||||||
|
interpreter->errorOutput("Parent directory access not allowed\n");
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//load the bytecode
|
||||||
|
size_t fileSize = 0;
|
||||||
|
unsigned char* bytecode = (unsigned char*)Toy_readFile(filePath, &fileSize);
|
||||||
|
|
||||||
|
if (!bytecode) {
|
||||||
|
interpreter->errorOutput("Failed to load bytecode file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the runner object
|
||||||
|
Toy_Runner* runner = TOY_ALLOCATE(Toy_Runner, 1);
|
||||||
|
Toy_setInterpreterPrint(&runner->interpreter, interpreter->printOutput);
|
||||||
|
Toy_setInterpreterAssert(&runner->interpreter, interpreter->assertOutput);
|
||||||
|
Toy_setInterpreterError(&runner->interpreter, interpreter->errorOutput);
|
||||||
|
runner->interpreter.hooks = interpreter->hooks;
|
||||||
|
runner->interpreter.scope = NULL;
|
||||||
|
Toy_resetInterpreter(&runner->interpreter);
|
||||||
|
runner->bytecode = bytecode;
|
||||||
|
runner->size = fileSize;
|
||||||
|
runner->dirty = false;
|
||||||
|
|
||||||
|
//build the opaque object, and push it to the stack
|
||||||
|
Toy_Literal runnerLiteral = TOY_TO_OPAQUE_LITERAL(runner, TOY_OPAQUE_TAG_RUNNER);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, runnerLiteral);
|
||||||
|
|
||||||
|
TOY_FREE_ARRAY(char, filePath, realLength);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//run
|
||||||
|
if (runner->dirty) {
|
||||||
|
interpreter->errorOutput("Can't re-run a dirty script (try resetting it first)\n");
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* bytecodeCopy = TOY_ALLOCATE(unsigned char, runner->size);
|
||||||
|
memcpy(bytecodeCopy, runner->bytecode, runner->size); //need a COPY of the bytecode, because the interpreter eats it
|
||||||
|
|
||||||
|
Toy_runInterpreter(&runner->interpreter, bytecodeCopy, runner->size);
|
||||||
|
runner->dirty = true;
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _getScriptVar\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal varName = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal varNameIdn = varName;
|
||||||
|
if (TOY_IS_IDENTIFIER(varName) && Toy_parseIdentifierToValue(interpreter, &varName)) {
|
||||||
|
Toy_freeLiteral(varNameIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//dirty check
|
||||||
|
if (!runner->dirty) {
|
||||||
|
interpreter->errorOutput("Can't access variable from a non-dirty script (try running it first)\n");
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the desired variable
|
||||||
|
Toy_Literal varIdn = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(varName)));
|
||||||
|
Toy_Literal result = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_getScopeVariable(runner->interpreter.scope, varIdn, &result);
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(varIdn);
|
||||||
|
Toy_freeLiteral(varName);
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count < 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _callScriptFn\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the rest args
|
||||||
|
Toy_LiteralArray tmp;
|
||||||
|
Toy_initLiteralArray(&tmp);
|
||||||
|
|
||||||
|
while (arguments->count > 2) {
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_pushLiteralArray(&tmp, lit);
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_LiteralArray rest;
|
||||||
|
Toy_initLiteralArray(&rest);
|
||||||
|
|
||||||
|
while (tmp.count) { //correct the order of the rest args
|
||||||
|
Toy_Literal lit = Toy_popLiteralArray(&tmp);
|
||||||
|
Toy_pushLiteralArray(&rest, lit);
|
||||||
|
Toy_freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&tmp);
|
||||||
|
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal varName = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal varNameIdn = varName;
|
||||||
|
if (TOY_IS_IDENTIFIER(varName) && Toy_parseIdentifierToValue(interpreter, &varName)) {
|
||||||
|
Toy_freeLiteral(varNameIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//dirty check
|
||||||
|
if (!runner->dirty) {
|
||||||
|
interpreter->errorOutput("Can't access fn from a non-dirty script (try running it first)\n");
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
Toy_freeLiteralArray(&rest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the desired variable
|
||||||
|
Toy_Literal varIdn = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(varName)));
|
||||||
|
Toy_Literal fn = TOY_TO_NULL_LITERAL;
|
||||||
|
Toy_getScopeVariable(runner->interpreter.scope, varIdn, &fn);
|
||||||
|
|
||||||
|
if (!TOY_IS_FUNCTION(fn)) {
|
||||||
|
interpreter->errorOutput("Can't run a non-function literal\n");
|
||||||
|
Toy_freeLiteral(fn);
|
||||||
|
Toy_freeLiteral(varIdn);
|
||||||
|
Toy_freeLiteral(varName);
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
Toy_freeLiteralArray(&rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
//call
|
||||||
|
Toy_LiteralArray resultArray;
|
||||||
|
Toy_initLiteralArray(&resultArray);
|
||||||
|
|
||||||
|
Toy_callLiteralFn(interpreter, fn, &rest, &resultArray);
|
||||||
|
|
||||||
|
Toy_Literal result = TOY_TO_NULL_LITERAL;
|
||||||
|
if (resultArray.count > 0) {
|
||||||
|
result = Toy_popLiteralArray(&resultArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteralArray(&resultArray);
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(fn);
|
||||||
|
Toy_freeLiteral(varIdn);
|
||||||
|
Toy_freeLiteral(varName);
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
Toy_freeLiteralArray(&rest);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _resetScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//reset
|
||||||
|
if (!runner->dirty) {
|
||||||
|
interpreter->errorOutput("Can't reset a non-dirty script (try running it first)\n");
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_resetInterpreter(&runner->interpreter);
|
||||||
|
runner->dirty = false;
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _freeScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _freeScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//clear out the runner object
|
||||||
|
runner->interpreter.hooks = NULL;
|
||||||
|
Toy_freeInterpreter(&runner->interpreter);
|
||||||
|
TOY_FREE_ARRAY(unsigned char, runner->bytecode, runner->size);
|
||||||
|
|
||||||
|
TOY_FREE(Toy_Runner, runner);
|
||||||
|
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal runnerIdn = runnerLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) {
|
||||||
|
Toy_freeLiteral(runnerIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_Literal result = TOY_TO_BOOLEAN_LITERAL(runner->dirty);
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the hook
|
||||||
|
typedef struct Natives {
|
||||||
|
char* name;
|
||||||
|
Toy_NativeFn fn;
|
||||||
|
} Natives;
|
||||||
|
|
||||||
|
int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
|
//build the natives list
|
||||||
|
Natives natives[] = {
|
||||||
|
{"loadScript", nativeLoadScript},
|
||||||
|
{"loadScriptBytecode", nativeLoadScriptBytecode},
|
||||||
|
{"_runScript", nativeRunScript},
|
||||||
|
{"_getScriptVar", nativeGetScriptVar},
|
||||||
|
{"_callScriptFn", nativeCallScriptFn},
|
||||||
|
{"_resetScript", nativeResetScript},
|
||||||
|
{"_freeScript", nativeFreeScript},
|
||||||
|
{"_checkScriptDirty", nativeCheckScriptDirty},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
//store the library in an aliased dictionary
|
||||||
|
if (!TOY_IS_NULL(alias)) {
|
||||||
|
//make sure the name isn't taken
|
||||||
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(alias);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the dictionary to load up with functions
|
||||||
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
|
//load the dict with functions
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
|
Toy_freeLiteral(name);
|
||||||
|
Toy_freeLiteral(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the type
|
||||||
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
|
//set scope
|
||||||
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(dict);
|
||||||
|
Toy_freeLiteral(type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//default
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//file system API
|
||||||
|
static Toy_LiteralDictionary Toy_driveDictionary;
|
||||||
|
|
||||||
|
void Toy_initDriveDictionary() {
|
||||||
|
Toy_initLiteralDictionary(&Toy_driveDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_freeDriveDictionary() {
|
||||||
|
Toy_freeLiteralDictionary(&Toy_driveDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_LiteralDictionary* Toy_getDriveDictionary() {
|
||||||
|
return &Toy_driveDictionary;
|
||||||
|
}
|
||||||
12
box/lib_runner.h
Normal file
12
box/lib_runner.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
|
//file system API - these need to be set by the host
|
||||||
|
void Toy_initDriveDictionary();
|
||||||
|
void Toy_freeDriveDictionary();
|
||||||
|
Toy_LiteralDictionary* Toy_getDriveDictionary();
|
||||||
|
|
||||||
|
#define TOY_OPAQUE_TAG_RUNNER 100
|
||||||
95
box/lib_standard.c
Normal file
95
box/lib_standard.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "lib_standard.h"
|
||||||
|
|
||||||
|
#include "toy_memory.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to clock\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the time from C (what a pain)
|
||||||
|
time_t rawtime = time(NULL);
|
||||||
|
struct tm* timeinfo = localtime( &rawtime );
|
||||||
|
char* timestr = asctime(timeinfo);
|
||||||
|
|
||||||
|
//push to the stack
|
||||||
|
int len = strlen(timestr) - 1; //-1 for the newline
|
||||||
|
Toy_Literal timeLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(timestr, len));
|
||||||
|
|
||||||
|
//push to the stack
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, timeLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the hook
|
||||||
|
typedef struct Natives {
|
||||||
|
char* name;
|
||||||
|
Toy_NativeFn fn;
|
||||||
|
} Natives;
|
||||||
|
|
||||||
|
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
|
//build the natives list
|
||||||
|
Natives natives[] = {
|
||||||
|
{"clock", nativeClock},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
//store the library in an aliased dictionary
|
||||||
|
if (!TOY_IS_NULL(alias)) {
|
||||||
|
//make sure the name isn't taken
|
||||||
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(alias);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the dictionary to load up with functions
|
||||||
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
|
//load the dict with functions
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
|
Toy_freeLiteral(name);
|
||||||
|
Toy_freeLiteral(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the type
|
||||||
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
|
//set scope
|
||||||
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(dict);
|
||||||
|
Toy_freeLiteral(type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//default
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
box/lib_standard.h
Normal file
6
box/lib_standard.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
412
box/lib_timer.c
Normal file
412
box/lib_timer.c
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
#include "lib_timer.h"
|
||||||
|
|
||||||
|
#include "toy_memory.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
//GOD DAMN IT: https://stackoverflow.com/questions/15846762/timeval-subtract-explanation
|
||||||
|
static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
|
||||||
|
//normallize
|
||||||
|
if (x->tv_usec > 999999) {
|
||||||
|
x->tv_sec += x->tv_usec / 1000000;
|
||||||
|
x->tv_usec %= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y->tv_usec > 999999) {
|
||||||
|
y->tv_sec += y->tv_usec / 1000000;
|
||||||
|
y->tv_usec %= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calc
|
||||||
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
||||||
|
|
||||||
|
if ((result->tv_usec = x->tv_usec - y->tv_usec) < 0) {
|
||||||
|
if (result->tv_sec != 0) { //only works far from 0
|
||||||
|
result->tv_usec += 1000000;
|
||||||
|
result->tv_sec--; // borrow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->tv_sec < 0 || (result->tv_sec == 0 && result->tv_usec < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//god damn it
|
||||||
|
static struct timeval* diff(struct timeval* lhs, struct timeval* rhs) {
|
||||||
|
struct timeval* d = TOY_ALLOCATE(struct timeval, 1);
|
||||||
|
|
||||||
|
//I gave up, copied from SO
|
||||||
|
timeval_subtract(d, rhs, lhs);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
//callbacks
|
||||||
|
static int nativeStartTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to startTimer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the timeinfo from C
|
||||||
|
struct timeval* timeinfo = TOY_ALLOCATE(struct timeval, 1);
|
||||||
|
gettimeofday(timeinfo, NULL);
|
||||||
|
|
||||||
|
//wrap in an opaque literal for Toy
|
||||||
|
Toy_Literal timeLiteral = TOY_TO_OPAQUE_LITERAL(timeinfo, -1);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, timeLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeStopTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _stopTimer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the timeinfo from C
|
||||||
|
struct timeval timerStop;
|
||||||
|
gettimeofday(&timerStop, NULL);
|
||||||
|
|
||||||
|
//unwrap the opaque literal
|
||||||
|
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal timeLiteralIdn = timeLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
|
||||||
|
Toy_freeLiteral(timeLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(timeLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _stopTimer\n");
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* timerStart = TOY_AS_OPAQUE(timeLiteral);
|
||||||
|
|
||||||
|
//determine the difference, and wrap it
|
||||||
|
struct timeval* d = diff(timerStart, &timerStop);
|
||||||
|
Toy_Literal diffLiteral = TOY_TO_OPAQUE_LITERAL(d, -1);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, diffLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
Toy_freeLiteral(diffLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeCreateTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to createTimer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the args
|
||||||
|
Toy_Literal microsecondLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal secondLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal secondLiteralIdn = secondLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(secondLiteral) && Toy_parseIdentifierToValue(interpreter, &secondLiteral)) {
|
||||||
|
Toy_freeLiteral(secondLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal microsecondLiteralIdn = microsecondLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(microsecondLiteral) && Toy_parseIdentifierToValue(interpreter, µsecondLiteral)) {
|
||||||
|
Toy_freeLiteral(microsecondLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_INTEGER(secondLiteral) || !TOY_IS_INTEGER(microsecondLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to createTimer\n");
|
||||||
|
Toy_freeLiteral(secondLiteral);
|
||||||
|
Toy_freeLiteral(microsecondLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_AS_INTEGER(microsecondLiteral) <= -1000 * 1000 || TOY_AS_INTEGER(microsecondLiteral) >= 1000 * 1000 || (TOY_AS_INTEGER(secondLiteral) != 0 && TOY_AS_INTEGER(microsecondLiteral) < 0) ) {
|
||||||
|
interpreter->errorOutput("Microseconds out of range in createTimer\n");
|
||||||
|
Toy_freeLiteral(secondLiteral);
|
||||||
|
Toy_freeLiteral(microsecondLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the timeinfo from toy
|
||||||
|
struct timeval* timeinfo = TOY_ALLOCATE(struct timeval, 1);
|
||||||
|
timeinfo->tv_sec = TOY_AS_INTEGER(secondLiteral);
|
||||||
|
timeinfo->tv_usec = TOY_AS_INTEGER(microsecondLiteral);
|
||||||
|
|
||||||
|
//wrap in an opaque literal for Toy
|
||||||
|
Toy_Literal timeLiteral = TOY_TO_OPAQUE_LITERAL(timeinfo, -1);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, timeLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
Toy_freeLiteral(secondLiteral);
|
||||||
|
Toy_freeLiteral(microsecondLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeGetTimerSeconds(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _getTimerSeconds\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unwrap the opaque literal
|
||||||
|
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal timeLiteralIdn = timeLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
|
||||||
|
Toy_freeLiteral(timeLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(timeLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _getTimerSeconds\n");
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
|
||||||
|
|
||||||
|
//create the result literal
|
||||||
|
Toy_Literal result = TOY_TO_INTEGER_LITERAL(timer->tv_sec);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeGetTimerMicroseconds(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _getTimerMicroseconds\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unwrap the opaque literal
|
||||||
|
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal timeLiteralIdn = timeLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
|
||||||
|
Toy_freeLiteral(timeLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(timeLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _getTimerMicroseconds\n");
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
|
||||||
|
|
||||||
|
//create the result literal
|
||||||
|
Toy_Literal result = TOY_TO_INTEGER_LITERAL(timer->tv_usec);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeCompareTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _compareTimer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unwrap the opaque literals
|
||||||
|
Toy_Literal rhsLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal lhsLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal lhsLiteralIdn = lhsLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(lhsLiteral) && Toy_parseIdentifierToValue(interpreter, &lhsLiteral)) {
|
||||||
|
Toy_freeLiteral(lhsLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal rhsLiteralIdn = rhsLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(rhsLiteral) && Toy_parseIdentifierToValue(interpreter, &rhsLiteral)) {
|
||||||
|
Toy_freeLiteral(rhsLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(lhsLiteral) || !TOY_IS_OPAQUE(rhsLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _compareTimer\n");
|
||||||
|
Toy_freeLiteral(lhsLiteral);
|
||||||
|
Toy_freeLiteral(rhsLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* lhsTimer = TOY_AS_OPAQUE(lhsLiteral);
|
||||||
|
struct timeval* rhsTimer = TOY_AS_OPAQUE(rhsLiteral);
|
||||||
|
|
||||||
|
//determine the difference, and wrap it
|
||||||
|
struct timeval* d = diff(lhsTimer, rhsTimer);
|
||||||
|
Toy_Literal diffLiteral = TOY_TO_OPAQUE_LITERAL(d, -1);
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, diffLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(lhsLiteral);
|
||||||
|
Toy_freeLiteral(rhsLiteral);
|
||||||
|
Toy_freeLiteral(diffLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeTimerToString(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _timerToString\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unwrap in an opaque literal
|
||||||
|
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal timeLiteralIdn = timeLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
|
||||||
|
Toy_freeLiteral(timeLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(timeLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _timerToString\n");
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
|
||||||
|
|
||||||
|
//create the string literal
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL;
|
||||||
|
if (timer->tv_sec == 0 && timer->tv_usec < 0) { //special case, for when the negative sign is encoded in the usec
|
||||||
|
char buffer[128];
|
||||||
|
snprintf(buffer, 128, "-%ld.%06ld", timer->tv_sec, -timer->tv_usec);
|
||||||
|
resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(buffer, strlen(buffer)));
|
||||||
|
}
|
||||||
|
else { //normal case
|
||||||
|
char buffer[128];
|
||||||
|
snprintf(buffer, 128, "%ld.%06ld", timer->tv_sec, timer->tv_usec);
|
||||||
|
resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(buffer, strlen(buffer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeDestroyTimer(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _destroyTimer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//unwrap in an opaque literal
|
||||||
|
Toy_Literal timeLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal timeLiteralIdn = timeLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(timeLiteral) && Toy_parseIdentifierToValue(interpreter, &timeLiteral)) {
|
||||||
|
Toy_freeLiteral(timeLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_OPAQUE(timeLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to _destroyTimer\n");
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval* timer = TOY_AS_OPAQUE(timeLiteral);
|
||||||
|
|
||||||
|
TOY_FREE(struct timeval, timer);
|
||||||
|
|
||||||
|
Toy_freeLiteral(timeLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the hook
|
||||||
|
typedef struct Natives {
|
||||||
|
char* name;
|
||||||
|
Toy_NativeFn fn;
|
||||||
|
} Natives;
|
||||||
|
|
||||||
|
int Toy_hookTimer(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
|
//build the natives list
|
||||||
|
Natives natives[] = {
|
||||||
|
{"startTimer", nativeStartTimer},
|
||||||
|
{"_stopTimer", nativeStopTimer},
|
||||||
|
{"createTimer", nativeCreateTimer},
|
||||||
|
{"_getTimerSeconds", nativeGetTimerSeconds},
|
||||||
|
{"_getTimerMicroseconds", nativeGetTimerMicroseconds},
|
||||||
|
{"_compareTimer", nativeCompareTimer},
|
||||||
|
{"_timerToString", nativeTimerToString},
|
||||||
|
{"_destroyTimer", nativeDestroyTimer},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
//store the library in an aliased dictionary
|
||||||
|
if (!TOY_IS_NULL(alias)) {
|
||||||
|
//make sure the name isn't taken
|
||||||
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(alias);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the dictionary to load up with functions
|
||||||
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
|
//load the dict with functions
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
|
Toy_Literal func = TOY_TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||||
|
func.type = TOY_LITERAL_FUNCTION_NATIVE;
|
||||||
|
|
||||||
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
|
Toy_freeLiteral(name);
|
||||||
|
Toy_freeLiteral(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the type
|
||||||
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
|
//set scope
|
||||||
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(dict);
|
||||||
|
Toy_freeLiteral(type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//default
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
box/lib_timer.h
Normal file
6
box/lib_timer.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
int Toy_hookTimer(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
146
box/repl_tools.c
Normal file
146
box/repl_tools.c
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include "repl_tools.h"
|
||||||
|
#include "lib_standard.h"
|
||||||
|
#include "lib_timer.h"
|
||||||
|
#include "lib_runner.h"
|
||||||
|
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
#include "toy_lexer.h"
|
||||||
|
#include "toy_parser.h"
|
||||||
|
#include "toy_compiler.h"
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
//IO functions
|
||||||
|
char* Toy_readFile(char* path, size_t* fileSize) {
|
||||||
|
FILE* file = fopen(path, "rb");
|
||||||
|
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "Could not open file \"%s\"\n" TOY_CC_RESET, path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0L, SEEK_END);
|
||||||
|
*fileSize = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
char* buffer = (char*)malloc(*fileSize + 1);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "Not enough memory to read \"%s\"\n" TOY_CC_RESET, path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
|
||||||
|
|
||||||
|
buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this
|
||||||
|
|
||||||
|
if (bytesRead < *fileSize) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "Could not read file \"%s\"\n" TOY_CC_RESET, path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Toy_writeFile(char* path, unsigned char* bytes, size_t size) {
|
||||||
|
FILE* file = fopen(path, "wb");
|
||||||
|
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "Could not open file \"%s\"\n" TOY_CC_RESET, path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int written = fwrite(bytes, size, 1, file);
|
||||||
|
|
||||||
|
if (written != 1) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "Could not write file \"%s\"\n" TOY_CC_RESET, path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//repl functions
|
||||||
|
unsigned char* Toy_compileString(char* source, size_t* size) {
|
||||||
|
Toy_Lexer lexer;
|
||||||
|
Toy_Parser parser;
|
||||||
|
Toy_Compiler compiler;
|
||||||
|
|
||||||
|
Toy_initLexer(&lexer, source);
|
||||||
|
Toy_initParser(&parser, &lexer);
|
||||||
|
Toy_initCompiler(&compiler);
|
||||||
|
|
||||||
|
//run the parser until the end of the source
|
||||||
|
Toy_ASTNode* node = Toy_scanParser(&parser);
|
||||||
|
while(node != NULL) {
|
||||||
|
//pack up and leave
|
||||||
|
if (node->type == TOY_AST_NODE_ERROR) {
|
||||||
|
Toy_freeASTNode(node);
|
||||||
|
Toy_freeCompiler(&compiler);
|
||||||
|
Toy_freeParser(&parser);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_writeCompiler(&compiler, node);
|
||||||
|
Toy_freeASTNode(node);
|
||||||
|
node = Toy_scanParser(&parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the bytecode dump
|
||||||
|
unsigned char* tb = Toy_collateCompiler(&compiler, (int*)(size));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeCompiler(&compiler);
|
||||||
|
Toy_freeParser(&parser);
|
||||||
|
//no lexer to clean up
|
||||||
|
|
||||||
|
//finally
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_runBinary(unsigned char* tb, size_t size) {
|
||||||
|
Toy_Interpreter interpreter;
|
||||||
|
Toy_initInterpreter(&interpreter);
|
||||||
|
|
||||||
|
//inject the libs
|
||||||
|
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
||||||
|
Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer);
|
||||||
|
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
||||||
|
|
||||||
|
Toy_runInterpreter(&interpreter, tb, size);
|
||||||
|
Toy_freeInterpreter(&interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_runBinaryFile(char* fname) {
|
||||||
|
size_t size = 0; //not used
|
||||||
|
unsigned char* tb = (unsigned char*)Toy_readFile(fname, &size);
|
||||||
|
if (!tb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Toy_runBinary(tb, size);
|
||||||
|
//interpreter takes ownership of the binary data
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_runSource(char* source) {
|
||||||
|
size_t size = 0;
|
||||||
|
unsigned char* tb = Toy_compileString(source, &size);
|
||||||
|
if (!tb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_runBinary(tb, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_runSourceFile(char* fname) {
|
||||||
|
size_t size = 0; //not used
|
||||||
|
char* source = Toy_readFile(fname, &size);
|
||||||
|
Toy_runSource(source);
|
||||||
|
free((void*)source);
|
||||||
|
}
|
||||||
14
box/repl_tools.h
Normal file
14
box/repl_tools.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_common.h"
|
||||||
|
|
||||||
|
char* Toy_readFile(char* path, size_t* fileSize);
|
||||||
|
int Toy_writeFile(char* path, unsigned char* bytes, size_t size);
|
||||||
|
|
||||||
|
unsigned char* Toy_compileString(char* source, size_t* size);
|
||||||
|
|
||||||
|
void Toy_runBinary(unsigned char* tb, size_t size);
|
||||||
|
void Toy_runBinaryFile(char* fname);
|
||||||
|
void Toy_runSource(char* source);
|
||||||
|
void Toy_runSourceFile(char* fname);
|
||||||
|
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
//moved here for android shenanigans
|
//moved here for android shenanigans
|
||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
|
|
||||||
#include "engine.h"
|
#include "box_engine.h"
|
||||||
|
|
||||||
//the runner library needs a little more setup since it accesses the disk
|
//the runner library needs a little more setup since it accesses the disk
|
||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
//the drive system uses a LiteralDictionary, which must be initialized with this
|
//the drive system uses a LiteralDictionary, which must be initialized with this
|
||||||
initDriveDictionary();
|
Toy_initDriveDictionary();
|
||||||
|
|
||||||
//create a pair of literals, the first for the drive name, the second for the path
|
//create a pair of literals, the first for the drive name, the second for the path
|
||||||
Literal driveLiteral = TO_STRING_LITERAL(createRefString("scripts"));
|
Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("scripts"));
|
||||||
Literal pathLiteral = TO_STRING_LITERAL(createRefString("assets/scripts"));
|
Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("assets/scripts"));
|
||||||
|
|
||||||
//set these within the drive dictionary
|
//set these within the drive dictionary
|
||||||
setLiteralDictionary(getDriveDictionary(), driveLiteral, pathLiteral);
|
Toy_setLiteralDictionary(Toy_getDriveDictionary(), driveLiteral, pathLiteral);
|
||||||
|
|
||||||
//these literals are no longer needed
|
//these literals are no longer needed
|
||||||
freeLiteral(driveLiteral);
|
Toy_freeLiteral(driveLiteral);
|
||||||
freeLiteral(pathLiteral);
|
Toy_freeLiteral(pathLiteral);
|
||||||
|
|
||||||
//run the rest of your program
|
//run the rest of your program
|
||||||
initEngine();
|
Box_initEngine();
|
||||||
execEngine();
|
Box_execEngine();
|
||||||
freeEngine();
|
Box_freeEngine();
|
||||||
|
|
||||||
//clean up the drive dictionary when you're done
|
//clean up the drive dictionary when you're done
|
||||||
freeDriveDictionary();
|
Toy_freeDriveDictionary();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user