Renamed files

This commit is contained in:
2023-01-26 20:41:23 +00:00
parent 54d417b3fc
commit 3e18baeec0
25 changed files with 28 additions and 1339 deletions

10
box/box_common.c Normal file
View File

@@ -0,0 +1,10 @@
#include "core_common.h"
STATIC_ASSERT(sizeof(char) == 1);
STATIC_ASSERT(sizeof(short) == 2);
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(float) == 4);
STATIC_ASSERT(sizeof(unsigned char) == 1);
STATIC_ASSERT(sizeof(unsigned short) == 2);
STATIC_ASSERT(sizeof(unsigned int) == 4);

22
box/box_common.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
//platform exports/imports
#if defined(__linux__)
#define CORE_API extern
#else
#define CORE_API
#endif
#include <assert.h>
//test variable sizes based on platform
#define STATIC_ASSERT(test_for_true) static_assert((test_for_true), "(" #test_for_true ") failed")

243
box/box_engine.c Normal file
View File

@@ -0,0 +1,243 @@
#include "engine.h"
#include "lib_engine.h"
#include "lib_input.h"
#include "lib_node.h"
#include "lib_standard.h"
#include "lib_timer.h"
#include "lib_runner.h"
#include "repl_tools.h"
#include "memory.h"
#include "lexer.h"
#include "parser.h"
#include "compiler.h"
#include "interpreter.h"
#include "literal_array.h"
#include "literal_dictionary.h"
#include "console_colors.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//define the extern engine object
Engine engine;
//errors here should be fatal
static void fatalError(char* message) {
fprintf(stderr, "%s", message);
exit(-1);
}
//exposed functions
void initEngine() {
//clear
engine.rootNode = NULL;
engine.running = false;
engine.window = NULL;
engine.renderer = NULL;
//init SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fatalError("Failed to initialize SDL2");
}
//init events
initLiteralArray(&engine.keyDownEvents);
initLiteralDictionary(&engine.symKeyDownEvents);
initLiteralArray(&engine.keyUpEvents);
initLiteralDictionary(&engine.symKeyUpEvents);
//init Toy
initInterpreter(&engine.interpreter);
injectNativeHook(&engine.interpreter, "engine", hookEngine);
injectNativeHook(&engine.interpreter, "node", hookNode);
injectNativeHook(&engine.interpreter, "input", hookInput);
injectNativeHook(&engine.interpreter, "standard", hookStandard);
injectNativeHook(&engine.interpreter, "timer", hookTimer);
injectNativeHook(&engine.interpreter, "runner", hookRunner);
size_t size = 0;
char* source = readFile("./assets/scripts/init.toy", &size);
unsigned char* tb = compileString(source, &size);
free((void*)source);
runInterpreter(&engine.interpreter, tb, size);
}
void freeEngine() {
//clear existing root node
if (engine.rootNode != NULL) {
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
freeEngineNode(engine.rootNode);
engine.rootNode = NULL;
}
freeInterpreter(&engine.interpreter);
//free events
freeLiteralArray(&engine.keyDownEvents);
freeLiteralDictionary(&engine.symKeyDownEvents);
freeLiteralArray(&engine.keyUpEvents);
freeLiteralDictionary(&engine.symKeyUpEvents);
//free SDL
SDL_DestroyRenderer(engine.renderer);
SDL_DestroyWindow(engine.window);
SDL_Quit();
engine.renderer = NULL;
engine.window = NULL;
}
static void execEvents() {
//clear event lists
if (engine.keyDownEvents.count > 0) {
freeLiteralArray(&engine.keyDownEvents);
//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
}
if (engine.keyUpEvents.count > 0) {
freeLiteralArray(&engine.keyUpEvents);
}
//poll all events
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
//quit
case SDL_QUIT: {
engine.running = false;
}
break;
//window events are handled internally
case SDL_WINDOWEVENT: {
switch(event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
engine.screenWidth = event.window.data1;
engine.screenHeight = event.window.data2;
SDL_RenderSetLogicalSize(engine.renderer, engine.screenWidth, engine.screenHeight);
break;
}
}
break;
//input
case SDL_KEYDOWN: {
//bugfix: ignore repeat messages
if (event.key.repeat) {
break;
}
//determine the given keycode
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
if (!existsLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral)) {
break;
}
//get the event name
Literal eventLiteral = getLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral);
//push to the event list
pushLiteralArray(&engine.keyDownEvents, eventLiteral);
}
break;
case SDL_KEYUP: {
//bugfix: ignore repeat messages
if (event.key.repeat) {
break;
}
//determine the given keycode
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) );
if (!existsLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral)) {
break;
}
//get the event name
Literal eventLiteral = getLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral);
//push to the event list
pushLiteralArray(&engine.keyUpEvents, eventLiteral);
}
break;
}
}
//process input events
if (engine.rootNode != NULL) {
//key down events
for (int i = 0; i < engine.keyDownEvents.count; i++) { //TODO: could pass in the whole array?
LiteralArray args;
initLiteralArray(&args);
pushLiteralArray(&args, engine.keyDownEvents.literals[i]);
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyDown", &args);
freeLiteralArray(&args);
}
//key up events
for (int i = 0; i < engine.keyUpEvents.count; i++) {
LiteralArray args;
initLiteralArray(&args);
pushLiteralArray(&args, engine.keyUpEvents.literals[i]);
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onKeyUp", &args);
freeLiteralArray(&args);
}
}
}
void execStep() {
if (engine.rootNode != NULL) {
//steps
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL);
}
}
//the heart of the engine
void execEngine() {
if (!engine.running) {
fatalError("Can't execute the engine (did you forget to initialize the screen?)");
}
//set up time
gettimeofday(&engine.realTime, NULL);
engine.simTime = engine.realTime;
struct timeval delta = { .tv_sec = 0, .tv_usec = 1000 * 1000 / 60 }; //60 frames per second
while (engine.running) {
execEvents();
//calc the time passed
gettimeofday(&engine.realTime, NULL);
//if not enough time has passed
if (timercmp(&engine.simTime, &engine.realTime, <)) {
//while not enough time has passed
while(timercmp(&engine.simTime, &engine.realTime, <)) {
//simulate the world
execStep();
//calc the time simulation
timeradd(&delta, &engine.simTime, &engine.simTime);
}
}
else {
SDL_Delay(10); //let the machine sleep, 10ms
}
//render the world
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
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onDraw", NULL);
SDL_RenderPresent(engine.renderer);
}
}

46
box/box_engine.h Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include "core_common.h"
#include "engine_node.h"
#include "interpreter.h"
#include "literal_array.h"
#include "literal_dictionary.h"
#include "core_common.h"
#include <sys/time.h>
//the base engine object, which represents the state of the game
typedef struct _engine {
//engine stuff
EngineNode* rootNode;
struct timeval simTime;
struct timeval realTime;
bool running;
//Toy stuff
Interpreter interpreter;
//SDL stuff
SDL_Window* window;
SDL_Renderer* renderer;
int screenWidth;
int screenHeight;
//input syms mapped to events
LiteralArray keyDownEvents; //list of events that occurred this frame
LiteralDictionary symKeyDownEvents; //keysym -> event names
LiteralArray keyUpEvents; //list of events that occurred this frame
LiteralDictionary symKeyUpEvents; //keysym -> event names
} Engine;
//extern singleton - used by various libraries
extern Engine engine;
//APIs for running the engine in main()
CORE_API void initEngine();
CORE_API void execEngine();
CORE_API void freeEngine();

232
box/box_engine_node.c Normal file
View File

@@ -0,0 +1,232 @@
#include "engine_node.h"
#include "engine.h"
#include "memory.h"
static void freeMemory(void* ptr) {
EngineNode* node = (EngineNode*)ptr;
//SDL stuff
SDL_DestroyTexture(node->texture);
//free this node type's memory
FREE(EngineNode, ptr);
}
void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t size) {
//init
// node->freeMemory = freeMemory;
node->functions = ALLOCATE(LiteralDictionary, 1);
node->parent = NULL;
node->tag = OPAQUE_TAG_ENGINE_NODE;
node->children = NULL;
node->capacity = 0;
node->count = 0;
node->texture = NULL;
initLiteralDictionary(node->functions);
//run bytecode
runInterpreter(interpreter, tb, size);
//grab all top-level functions from the dirty interpreter
LiteralDictionary* variablesPtr = &interpreter->scope->variables;
for (int i = 0; i < variablesPtr->capacity; i++) {
//skip empties and tombstones
if (IS_NULL(variablesPtr->entries[i].key)) {
continue;
}
//if this variable is a function (this outmodes import and export)
_entry* entry = &variablesPtr->entries[i];
if (IS_FUNCTION(entry->value)) {
//save a copy
setLiteralDictionary(node->functions, entry->key, entry->value);
}
}
}
void pushEngineNode(EngineNode* node, EngineNode* child) {
//push to the array (prune tombstones when expanding/copying)
if (node->count + 1 > node->capacity) {
int oldCapacity = node->capacity;
node->capacity = GROW_CAPACITY(oldCapacity);
node->children = GROW_ARRAY(EngineNode*, node->children, oldCapacity, node->capacity);
}
//prune tombstones (experimental)
int counter = 0;
for (int i = 0; i < node->capacity; i++) {
if (i >= node->count) {
node->count = counter;
break;
}
//move down
if (node->children[i] != NULL) {
node->children[counter++] = node->children[i];
}
}
//assign
node->children[node->count++] = child;
//reverse-assign
child->parent = node;
}
void freeEngineNode(EngineNode* node) {
if (node == NULL) {
return; //NO-OP
}
//free and tombstone this node
for (int i = 0; i < node->count; i++) {
freeEngineNode(node->children[i]);
}
//free the pointer array to the children
FREE_ARRAY(EngineNode*, node->children, node->capacity);
if (node->functions != NULL) {
freeLiteralDictionary(node->functions);
FREE(LiteralDictionary, node->functions);
}
//free this node's memory
// node->freeMemory(node);
freeMemory(node);
}
Literal callEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args) {
Literal ret = TO_NULL_LITERAL;
//if this fn exists
if (existsLiteralDictionary(node->functions, key)) {
Literal fn = getLiteralDictionary(node->functions, key);
Literal n = TO_OPAQUE_LITERAL(node, node->tag);
LiteralArray arguments;
LiteralArray returns;
initLiteralArray(&arguments);
initLiteralArray(&returns);
//feed the arguments in backwards!
if (args) {
for (int i = args->count -1; i >= 0; i--) {
pushLiteralArray(&arguments, args->literals[i]);
}
}
pushLiteralArray(&arguments, n);
callLiteralFn(interpreter, fn, &arguments, &returns);
ret = popLiteralArray(&returns);
freeLiteralArray(&arguments);
freeLiteralArray(&returns);
freeLiteral(n);
freeLiteral(fn);
}
return ret;
}
Literal callEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args) {
//call "fnName" on this node, and all children, if it exists
Literal key = TO_IDENTIFIER_LITERAL(createRefString(fnName));
Literal ret = callEngineNodeLiteral(node, interpreter, key, args);
freeLiteral(key);
return ret;
}
void callRecursiveEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, LiteralArray* args) {
//if this fn exists
if (existsLiteralDictionary(node->functions, key)) {
Literal fn = getLiteralDictionary(node->functions, key);
Literal n = TO_OPAQUE_LITERAL(node, node->tag);
LiteralArray arguments;
LiteralArray returns;
initLiteralArray(&arguments);
initLiteralArray(&returns);
//feed the arguments in backwards!
if (args) {
for (int i = args->count -1; i >= 0; i--) {
pushLiteralArray(&arguments, args->literals[i]);
}
}
pushLiteralArray(&arguments, n);
callLiteralFn(interpreter, fn, &arguments, &returns);
freeLiteralArray(&arguments);
freeLiteralArray(&returns);
freeLiteral(n);
freeLiteral(fn);
}
//recurse to the (non-tombstone) children
for (int i = 0; i < node->count; i++) {
if (node->children[i] != NULL) {
callRecursiveEngineNodeLiteral(node->children[i], interpreter, key, args);
}
}
}
void callRecursiveEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName, LiteralArray* args) {
//call "fnName" on this node, and all children, if it exists
Literal key = TO_IDENTIFIER_LITERAL(createRefString(fnName));
callRecursiveEngineNodeLiteral(node, interpreter, key, args);
freeLiteral(key);
}
int loadTextureEngineNode(EngineNode* node, char* fname) {
SDL_Surface* surface = IMG_Load(fname);
if (surface == NULL) {
return -1;
}
node->texture = SDL_CreateTextureFromSurface(engine.renderer, surface);
if (node->texture == NULL) {
return -2;
}
SDL_FreeSurface(surface);
int w, h;
SDL_QueryTexture(node->texture, NULL, NULL, &w, &h);
SDL_Rect r = { 0, 0, w, h };
setRectEngineNode(node, r);
return 0;
}
void freeTextureEngineNode(EngineNode* node) {
if (node->texture != NULL) {
SDL_DestroyTexture(node->texture);
node->texture = NULL;
}
}
void setRectEngineNode(EngineNode* node, SDL_Rect rect) {
node->rect = rect;
}
void drawEngineNode(EngineNode* node, SDL_Rect dest) {
SDL_RenderCopy(engine.renderer, node->texture, &node->rect, &dest);
}

55
box/box_engine_node.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "core_common.h"
#include "literal_dictionary.h"
#include "interpreter.h"
#define OPAQUE_TAG_ENGINE_NODE 1001
//forward declare
typedef struct _engineNode EngineNode;
// typedef void (*EngineNodeCallback)(void*);
//the node object, which forms a tree
typedef struct _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
// EngineNodeCallback freeMemory;
//toy functions, stored in a dict for flexibility
LiteralDictionary* functions;
//point to the parent
EngineNode* parent;
//my opaque type tag
int tag;
int _unused0;
//use Toy's memory model
EngineNode** children;
int capacity;
int count; //includes tombstones
//rendering-specific features
SDL_Texture* texture;
SDL_Rect rect;
//TODO: depth
} EngineNode;
CORE_API void initEngineNode(EngineNode* node, 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)
CORE_API void freeEngineNode(EngineNode* node); //free and tombstone this node
CORE_API Literal callEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, 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
CORE_API void callRecursiveEngineNodeLiteral(EngineNode* node, Interpreter* interpreter, Literal key, 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
CORE_API int loadTextureEngineNode(EngineNode* node, char* fname);
CORE_API void freeTextureEngineNode(EngineNode* node);
CORE_API void setRectEngineNode(EngineNode* node, SDL_Rect rect);
//TODO: getRect
CORE_API void drawEngineNode(EngineNode* node, SDL_Rect dest);

211
box/lib_engine.c Normal file
View File

@@ -0,0 +1,211 @@
#include "lib_engine.h"
#include "engine.h"
#include "repl_tools.h"
#include "memory.h"
#include "literal_array.h"
//errors here should be fatal
static void fatalError(char* message) {
fprintf(stderr, "%s", message);
exit(-1);
}
//native functions to be called
static int nativeInitWindow(Interpreter* interpreter, LiteralArray* arguments) {
if (engine.window != NULL) {
fatalError("Can't re-initialize the window\n");
}
if (arguments->count != 4) {
fatalError("Incorrect number of arguments passed to initEngine\n");
}
//extract the arguments
Literal fscreen = popLiteralArray(arguments);
Literal screenHeight = popLiteralArray(arguments);
Literal screenWidth = popLiteralArray(arguments);
Literal caption = popLiteralArray(arguments);
//check argument types
if (!IS_STRING(caption) || !IS_INTEGER(screenWidth) || !IS_INTEGER(screenHeight) || !IS_BOOLEAN(fscreen)) {
fatalError("Incorrect argument type passed to initEngine\n");
}
//init the window
engine.window = SDL_CreateWindow(
toCString(AS_STRING(caption)),
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
engine.screenWidth = AS_INTEGER(screenWidth),
engine.screenHeight = AS_INTEGER(screenHeight),
IS_TRUTHY(fscreen) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE
);
if (engine.window == NULL) {
fatalError("Failed to initialize the window\n");
}
//init the renderer
// SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
engine.renderer = SDL_CreateRenderer(engine.window, -1, 0);
if (engine.renderer == NULL) {
fatalError("Failed to initialize the renderer\n");
}
SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(engine.renderer, &rendererInfo);
printf("Renderer: %s\n", rendererInfo.name);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
SDL_RenderSetLogicalSize(engine.renderer, engine.screenWidth, engine.screenHeight);
//only run with a window
engine.running = true;
freeLiteral(caption);
freeLiteral(screenWidth);
freeLiteral(screenHeight);
freeLiteral(fscreen);
return 0;
}
//TODO: perhaps a returns argument would be better?
static int nativeLoadRootNode(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to loadRootNode\n");
return -1;
}
//extract the arguments
Literal fname = popLiteralArray(arguments);
Literal fnameIdn = fname;
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
freeLiteral(fnameIdn);
}
//check argument types
if (!IS_STRING(fname)) {
interpreter->errorOutput("Incorrect argument type passed to loadRootNode\n");
freeLiteral(fname);
return -1;
}
//clear existing root node
if (engine.rootNode != NULL) {
callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
freeEngineNode(engine.rootNode);
FREE(EngineNode, engine.rootNode);
engine.rootNode = NULL;
}
//load the new root node
size_t size = 0;
char* source = readFile(toCString(AS_STRING(fname)), &size);
unsigned char* tb = compileString(source, &size);
free((void*)source);
engine.rootNode = ALLOCATE(EngineNode, 1);
//BUGFIX: make an inner-interpreter
Interpreter inner;
//init the inner interpreter manually
initLiteralArray(&inner.literalCache);
inner.scope = pushScope(NULL);
inner.bytecode = tb;
inner.length = size;
inner.count = 0;
inner.codeStart = -1;
inner.depth = interpreter->depth + 1;
inner.panic = false;
initLiteralArray(&inner.stack);
inner.hooks = interpreter->hooks;
setInterpreterPrint(&inner, interpreter->printOutput);
setInterpreterAssert(&inner, interpreter->assertOutput);
setInterpreterError(&inner, interpreter->errorOutput);
initEngineNode(engine.rootNode, &inner, tb, size);
//init the new node (and ONLY this node)
callEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL);
//cleanup
freeLiteralArray(&inner.stack);
freeLiteralArray(&inner.literalCache);
freeLiteral(fname);
return 0;
}
//call the hook
typedef struct Natives {
char* name;
NativeFn fn;
} Natives;
int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias) {
//build the natives list
Natives natives[] = {
{"initWindow", nativeInitWindow},
{"loadRootNode", nativeLoadRootNode},
{NULL, NULL}
};
//store the library in an aliased dictionary
if (!IS_NULL(alias)) {
//make sure the name isn't taken
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
freeLiteral(alias);
return false;
}
//create the dictionary to load up with functions
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
initLiteralDictionary(dictionary);
//load the dict with functions
for (int i = 0; natives[i].name; i++) {
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
func.type = LITERAL_FUNCTION_NATIVE;
setLiteralDictionary(dictionary, name, func);
freeLiteral(name);
freeLiteral(func);
}
//build the type
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
TYPE_PUSH_SUBTYPE(&type, strType);
TYPE_PUSH_SUBTYPE(&type, fnType);
//set scope
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
declareScopeVariable(interpreter->scope, alias, type);
setScopeVariable(interpreter->scope, alias, dict, false);
//cleanup
freeLiteral(dict);
freeLiteral(type);
return 0;
}
//default
for (int i = 0; natives[i].name; i++) {
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
return 0;
}

6
box/lib_engine.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "interpreter.h"
int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias);

131
box/lib_input.c Normal file
View File

@@ -0,0 +1,131 @@
#include "lib_input.h"
#include "memory.h"
#include "engine.h"
#include "core_common.h"
static int nativeMapInputEventToKey(Interpreter* interpreter, LiteralArray* arguments, LiteralDictionary* symKeyEventsPtr, char* fnName) {
//checks
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments passed to ");
interpreter->errorOutput(fnName);
interpreter->errorOutput("\n");
return -1;
}
Literal symLiteral = popLiteralArray(arguments);
Literal evtLiteral = popLiteralArray(arguments);
Literal evtLiteralIdn = evtLiteral;
if (IS_IDENTIFIER(evtLiteral) && parseIdentifierToValue(interpreter, &evtLiteral)) {
freeLiteral(evtLiteralIdn);
}
Literal symLiteralIdn = symLiteral;
if (IS_IDENTIFIER(symLiteral) && parseIdentifierToValue(interpreter, &symLiteral)) {
freeLiteral(symLiteralIdn);
}
if (!IS_STRING(symLiteral) || !IS_STRING(evtLiteral)) {
interpreter->errorOutput("Incorrect type of arguments passed to mapInputEventToKey\n");
return -1;
}
//use the keycode for faster lookups
SDL_Keycode keycode = SDL_GetKeyFromName( toCString(AS_STRING(symLiteral)) );
if (keycode == SDLK_UNKNOWN) {
interpreter->errorOutput("Unknown key found: ");
interpreter->errorOutput(SDL_GetError());
interpreter->errorOutput("\n");
return -1;
}
Literal keycodeLiteral = TO_INTEGER_LITERAL( (int)keycode );
//save the sym-event pair
setLiteralDictionary(symKeyEventsPtr, keycodeLiteral, evtLiteral); //I could possibly map multiple events to one sym
//cleanup
freeLiteral(symLiteral);
freeLiteral(evtLiteral);
freeLiteral(keycodeLiteral);
return 0;
}
//dry wrappers
static int nativeMapInputEventToKeyDown(Interpreter* interpreter, LiteralArray* arguments) {
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyDownEvents, "mapInputEventToKeyDown");
}
static int nativeMapInputEventToKeyUp(Interpreter* interpreter, LiteralArray* arguments) {
return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyUpEvents, "mapInputEventToKeyUp");
}
//call the hook
typedef struct Natives {
char* name;
NativeFn fn;
} Natives;
int hookInput(Interpreter* interpreter, Literal identifier, Literal alias) {
//build the natives list
Natives natives[] = {
{"mapInputEventToKeyDown", nativeMapInputEventToKeyDown},
{"mapInputEventToKeyUp", nativeMapInputEventToKeyUp},
// {"mapInputEventToMouse", nativeMapInputEventToMouse},
{NULL, NULL}
};
//store the library in an aliased dictionary
if (!IS_NULL(alias)) {
//make sure the name isn't taken
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
freeLiteral(alias);
return false;
}
//create the dictionary to load up with functions
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
initLiteralDictionary(dictionary);
//load the dict with functions
for (int i = 0; natives[i].name; i++) {
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
func.type = LITERAL_FUNCTION_NATIVE;
setLiteralDictionary(dictionary, name, func);
freeLiteral(name);
freeLiteral(func);
}
//build the type
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
TYPE_PUSH_SUBTYPE(&type, strType);
TYPE_PUSH_SUBTYPE(&type, fnType);
//set scope
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
declareScopeVariable(interpreter->scope, alias, type);
setScopeVariable(interpreter->scope, alias, dict, false);
//cleanup
freeLiteral(dict);
freeLiteral(type);
return 0;
}
//default
for (int i = 0; natives[i].name; i++) {
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
return 0;
}

6
box/lib_input.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "interpreter.h"
int hookInput(Interpreter* interpreter, Literal identifier, Literal alias);

679
box/lib_node.c Normal file
View File

@@ -0,0 +1,679 @@
#include "lib_node.h"
#include "engine.h"
#include "engine_node.h"
#include "repl_tools.h"
#include "memory.h"
#include "literal_array.h"
#include <stdlib.h>
static int nativeLoadNode(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n");
return -1;
}
//extract the arguments
Literal fname = popLiteralArray(arguments);
Literal fnameIdn = fname;
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
freeLiteral(fnameIdn);
}
//check argument types
if (!IS_STRING(fname)) {
interpreter->errorOutput("Incorrect argument type passed to loadNode\n");
freeLiteral(fname);
return -1;
}
//load the new node
size_t size = 0;
char* source = readFile(toCString(AS_STRING(fname)), &size);
unsigned char* tb = compileString(source, &size);
free((void*)source);
EngineNode* node = ALLOCATE(EngineNode, 1);
//BUGFIX: make an inner-interpreter
Interpreter inner;
//init the inner interpreter manually
initLiteralArray(&inner.literalCache);
inner.scope = pushScope(NULL);
inner.bytecode = tb;
inner.length = size;
inner.count = 0;
inner.codeStart = -1;
inner.depth = interpreter->depth + 1;
inner.panic = false;
initLiteralArray(&inner.stack);
inner.hooks = interpreter->hooks;
setInterpreterPrint(&inner, interpreter->printOutput);
setInterpreterAssert(&inner, interpreter->assertOutput);
setInterpreterError(&inner, interpreter->errorOutput);
initEngineNode(node, &inner, tb, size);
// return the node
Literal nodeLiteral = TO_OPAQUE_LITERAL(node, node->tag);
pushLiteralArray(&interpreter->stack, nodeLiteral);
//cleanup
freeLiteralArray(&inner.stack);
freeLiteralArray(&inner.literalCache);
freeLiteral(fname);
freeLiteral(nodeLiteral);
return 1;
}
static int nativeInitNode(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to initNode\n");
return -1;
}
Literal node = popLiteralArray(arguments);
Literal nodeIdn = node;
if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) {
freeLiteral(nodeIdn);
}
//check argument types
if (!IS_OPAQUE(node)) {
interpreter->errorOutput("Incorrect argument type passed to initNode\n");
freeLiteral(node);
return -1;
}
EngineNode* engineNode = AS_OPAQUE(node);
//init the new node (and ONLY this node)
callEngineNode(engineNode, &engine.interpreter, "onInit", NULL);
//cleanup
freeLiteral(node);
return 0;
}
static int nativeFreeChildNode(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n");
return -1;
}
Literal index = popLiteralArray(arguments);
Literal node = popLiteralArray(arguments);
Literal nodeIdn = node; //annoying
if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) {
freeLiteral(nodeIdn);
}
//check argument types
if (!IS_OPAQUE(node) || !IS_INTEGER(index)) {
interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n");
freeLiteral(node);
return -1;
}
EngineNode* parentNode = AS_OPAQUE(node);
int idx = AS_INTEGER(index);
//check bounds
if (idx < 0 || idx >= parentNode->count) {
interpreter->errorOutput("Node index out of bounds in freeChildNode\n");
freeLiteral(node);
freeLiteral(index);
return -1;
}
//get the child node
EngineNode* childNode = parentNode->children[idx];
//free the node
if (childNode != NULL) {
callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL);
freeEngineNode(childNode);
}
parentNode->children[idx] = NULL;
//cleanup
freeLiteral(node);
freeLiteral(index);
return 0;
}
static int nativePushNode(Interpreter* interpreter, LiteralArray* arguments) {
//checks
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n");
return -1;
}
Literal child = popLiteralArray(arguments);
Literal parent = popLiteralArray(arguments);
Literal parentIdn = parent;
if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) {
freeLiteral(parentIdn);
}
Literal childIdn = child;
if (IS_IDENTIFIER(child) && parseIdentifierToValue(interpreter, &child)) {
freeLiteral(childIdn);
}
if (!IS_OPAQUE(parent) || !IS_OPAQUE(child)) {
interpreter->errorOutput("Incorrect argument type passed to pushNode\n");
freeLiteral(parent);
freeLiteral(child);
return -1;
}
//push the node
EngineNode* parentNode = AS_OPAQUE(parent);
EngineNode* childNode = AS_OPAQUE(child);
pushEngineNode(parentNode, childNode);
//no return value
freeLiteral(parent);
freeLiteral(child);
return 0;
}
static int nativeGetNodeChild(Interpreter* interpreter, LiteralArray* arguments) {
//checks
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments passed to getNode\n");
return -1;
}
Literal index = popLiteralArray(arguments);
Literal parent = popLiteralArray(arguments);
Literal parentIdn = parent;
if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) {
freeLiteral(parentIdn);
}
if (!IS_OPAQUE(parent) || !IS_INTEGER(index)) {
interpreter->errorOutput("Incorrect argument type passed to getNode\n");
freeLiteral(parent);
freeLiteral(index);
return -1;
}
//push the node
EngineNode* parentNode = AS_OPAQUE(parent);
int intIndex = AS_INTEGER(index);
if (intIndex < 0 || intIndex >= parentNode->count) {
interpreter->errorOutput("index out of bounds in getNode\n");
freeLiteral(parent);
freeLiteral(index);
return -1;
}
EngineNode* childNode = parentNode->children[intIndex];
Literal child = TO_OPAQUE_LITERAL(childNode, childNode->tag);
pushLiteralArray(&interpreter->stack, child);
//no return value
freeLiteral(parent);
freeLiteral(child);
freeLiteral(index);
return 1;
}
static int nativeGetNodeParent(Interpreter* interpreter, LiteralArray* arguments) {
//checks
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to getNodeParent\n");
return -1;
}
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
if (!IS_OPAQUE(nodeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to getNodeParent\n");
freeLiteral(nodeLiteral);
return -1;
}
//push the node
EngineNode* node = AS_OPAQUE(nodeLiteral);
EngineNode* parent = node->parent;
Literal parentLiteral = TO_NULL_LITERAL;
if (parent != NULL) {
parentLiteral = TO_OPAQUE_LITERAL(parent, parent->tag);
}
pushLiteralArray(&interpreter->stack, parentLiteral);
//cleanup
freeLiteral(parentLiteral);
freeLiteral(nodeLiteral);
return 1;
}
static int nativeLoadTexture(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments passed to loadTextureEngineNode\n");
return -1;
}
//extract the arguments
Literal fname = popLiteralArray(arguments);
Literal nodeLiteral = popLiteralArray(arguments);
Literal fnameIdn = fname;
if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) {
freeLiteral(fnameIdn);
}
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
//check argument types
if (!IS_STRING(fname) || !IS_OPAQUE(nodeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to loadTextureEngineNode\n");
freeLiteral(fname);
freeLiteral(nodeLiteral);
return -1;
}
//actually load TODO: number the opaques, and check the numbers
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
if (node->texture != NULL) {
freeTextureEngineNode(node);
}
if (loadTextureEngineNode(node, toCString(AS_STRING(fname))) != 0) {
interpreter->errorOutput("Failed to load the texture into the EngineNode\n");
freeLiteral(fname);
freeLiteral(nodeLiteral);
return -1;
}
//cleanup
freeLiteral(fname);
freeLiteral(nodeLiteral);
return 0;
}
static int nativeFreeTexture(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to freeTextureEngineNode\n");
return -1;
}
//extract the arguments
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
//check argument types
if (!IS_OPAQUE(nodeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to freeTextureEngineNode\n");
freeLiteral(nodeLiteral);
return -1;
}
//actually load TODO: number the opaques, and check the numbers
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
if (node->texture != NULL) {
freeTextureEngineNode(node);
}
//cleanup
freeLiteral(nodeLiteral);
return 0;
}
static int nativeSetRect(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 5) {
interpreter->errorOutput("Incorrect number of arguments passed to setRectEngineNode\n");
return -1;
}
//extract the arguments
Literal h = popLiteralArray(arguments);
Literal w = popLiteralArray(arguments);
Literal y = popLiteralArray(arguments);
Literal x = popLiteralArray(arguments);
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
Literal xi = x;
if (IS_IDENTIFIER(x) && parseIdentifierToValue(interpreter, &x)) {
freeLiteral(xi);
}
Literal yi = y;
if (IS_IDENTIFIER(y) && parseIdentifierToValue(interpreter, &y)) {
freeLiteral(yi);
}
Literal wi = w;
if (IS_IDENTIFIER(w) && parseIdentifierToValue(interpreter, &w)) {
freeLiteral(wi);
}
Literal hi = h;
if (IS_IDENTIFIER(h) && parseIdentifierToValue(interpreter, &h)) {
freeLiteral(hi);
}
//check argument types
if (!IS_OPAQUE(nodeLiteral) || !IS_INTEGER(x) || !IS_INTEGER(y) || !IS_INTEGER(w) || !IS_INTEGER(h)) {
interpreter->errorOutput("Incorrect argument type passed to setRectEngineNode\n");
freeLiteral(nodeLiteral);
freeLiteral(x);
freeLiteral(y);
freeLiteral(w);
freeLiteral(h);
return -1;
}
//actually set
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), AS_INTEGER(w), AS_INTEGER(h)};
setRectEngineNode(node, r);
//cleanup
freeLiteral(nodeLiteral);
freeLiteral(x);
freeLiteral(y);
freeLiteral(w);
freeLiteral(h);
return 0;
}
//TODO: get x, y, w, h
static int nativeDrawNode(Interpreter* interpreter, LiteralArray* arguments) {
if (arguments->count != 3 && arguments->count != 5) {
interpreter->errorOutput("Incorrect number of arguments passed to drawEngineNode\n");
return -1;
}
//extract the arguments
Literal w = TO_NULL_LITERAL, h = TO_NULL_LITERAL;
if (arguments->count == 5) {
h = popLiteralArray(arguments);
w = popLiteralArray(arguments);
}
Literal y = popLiteralArray(arguments);
Literal x = popLiteralArray(arguments);
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
Literal xi = x;
if (IS_IDENTIFIER(x) && parseIdentifierToValue(interpreter, &x)) {
freeLiteral(xi);
}
Literal yi = y;
if (IS_IDENTIFIER(y) && parseIdentifierToValue(interpreter, &y)) {
freeLiteral(yi);
}
Literal wi = w;
if (IS_IDENTIFIER(w) && parseIdentifierToValue(interpreter, &w)) {
freeLiteral(wi);
}
Literal hi = h;
if (IS_IDENTIFIER(h) && parseIdentifierToValue(interpreter, &h)) {
freeLiteral(hi);
}
//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))) {
interpreter->errorOutput("Incorrect argument type passed to drawEngineNode\n");
freeLiteral(nodeLiteral);
freeLiteral(x);
freeLiteral(y);
freeLiteral(w);
freeLiteral(h);
return -1;
}
//actually render
EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral);
SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), 0, 0};
if (IS_INTEGER(w) && IS_INTEGER(h)) {
r.w = AS_INTEGER(w);
r.h = AS_INTEGER(h);
}
else {
r.w = node->rect.w;
r.h = node->rect.h;
}
drawEngineNode(node, r);
//cleanup
freeLiteral(nodeLiteral);
freeLiteral(x);
freeLiteral(y);
freeLiteral(w);
freeLiteral(h);
return 0;
}
static int nativeGetNodeTag(Interpreter* interpreter, LiteralArray* arguments) {
//checks
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments passed to getNodeTag\n");
return -1;
}
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
if (!IS_OPAQUE(nodeLiteral)) {
interpreter->errorOutput("Incorrect argument type passed to getNodeTag\n");
freeLiteral(nodeLiteral);
return -1;
}
//push the tag
Literal tagLiteral = TO_INTEGER_LITERAL( ((EngineNode*)AS_OPAQUE(nodeLiteral))->tag );
pushLiteralArray(&interpreter->stack, tagLiteral);
//cleanup
freeLiteral(nodeLiteral);
freeLiteral(tagLiteral);
return 1;
}
static int nativeCallNode(Interpreter* interpreter, LiteralArray* arguments) {
//checks
if (arguments->count < 2) {
interpreter->errorOutput("Too few arguments passed to callEngineNode\n");
return -1;
}
LiteralArray extraArgs;
initLiteralArray(&extraArgs);
LiteralArray flippedExtraArgs;
initLiteralArray(&flippedExtraArgs);
//extract the extra arg values
while (arguments->count > 2) {
Literal tmp = popLiteralArray(arguments);
Literal idn = tmp; //there's almost certainly a better way of doing all of this stuff
if (IS_IDENTIFIER(tmp) && parseIdentifierToValue(interpreter, &tmp)) {
freeLiteral(idn);
}
pushLiteralArray(&flippedExtraArgs, tmp);
freeLiteral(tmp);
}
//correct the order
while (flippedExtraArgs.count) {
Literal tmp = popLiteralArray(&flippedExtraArgs);
pushLiteralArray(&extraArgs, tmp);
freeLiteral(tmp);
}
freeLiteralArray(&flippedExtraArgs);
//back on track
Literal fnName = popLiteralArray(arguments);
Literal nodeLiteral = popLiteralArray(arguments);
Literal nodeIdn = nodeLiteral;
if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) {
freeLiteral(nodeIdn);
}
Literal fnNameIdn = fnName;
if (IS_IDENTIFIER(fnName) && parseIdentifierToValue(interpreter, &fnName)) {
freeLiteral(fnNameIdn);
}
if (!IS_OPAQUE(nodeLiteral) || !IS_STRING(fnName)) {
interpreter->errorOutput("Incorrect argument type passed to callEngineNode\n");
freeLiteral(nodeLiteral);
freeLiteral(fnName);
return -1;
}
//allow refstring to do it's magic
Literal fnNameIdentifier = TO_IDENTIFIER_LITERAL(copyRefString(AS_STRING(fnName)));
//call the function
Literal result = callEngineNodeLiteral(AS_OPAQUE(nodeLiteral), interpreter, fnNameIdentifier, &extraArgs);
pushLiteralArray(&interpreter->stack, result);
//cleanup
freeLiteralArray(&extraArgs);
freeLiteral(nodeLiteral);
freeLiteral(fnName);
freeLiteral(result);
return 1;
}
//call the hook
typedef struct Natives {
char* name;
NativeFn fn;
} Natives;
int hookNode(Interpreter* interpreter, Literal identifier, Literal alias) {
//build the natives list
Natives natives[] = {
{"loadNode", nativeLoadNode},
{"_initNode", nativeInitNode},
{"_freeChildNode", nativeFreeChildNode},
{"_pushNode", nativePushNode},
{"_getNodeChild", nativeGetNodeChild},
{"_getNodeParent", nativeGetNodeParent},
{"_loadTexture", nativeLoadTexture},
{"_freeTexture", nativeFreeTexture},
{"_setRect", nativeSetRect},
{"_drawNode", nativeDrawNode},
{"_callNode", nativeCallNode},
// {"getNodeTag", nativeGetNodeTag}, //not needed if there's only one node type
{NULL, NULL},
};
//store the library in an aliased dictionary
if (!IS_NULL(alias)) {
//make sure the name isn't taken
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
freeLiteral(alias);
return false;
}
//create the dictionary to load up with functions
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
initLiteralDictionary(dictionary);
//load the dict with functions
for (int i = 0; natives[i].name; i++) {
Literal name = TO_STRING_LITERAL(createRefString(natives[i].name));
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
func.type = LITERAL_FUNCTION_NATIVE;
setLiteralDictionary(dictionary, name, func);
freeLiteral(name);
freeLiteral(func);
}
//build the type
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
TYPE_PUSH_SUBTYPE(&type, strType);
TYPE_PUSH_SUBTYPE(&type, fnType);
//set scope
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
declareScopeVariable(interpreter->scope, alias, type);
setScopeVariable(interpreter->scope, alias, dict, false);
//cleanup
freeLiteral(dict);
freeLiteral(type);
return 0;
}
//default
for (int i = 0; natives[i].name; i++) {
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
return 0;
}

6
box/lib_node.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "interpreter.h"
int hookNode(Interpreter* interpreter, Literal identifier, Literal alias);

51
box/makefile Normal file
View File

@@ -0,0 +1,51 @@
CC=gcc
IDIR+=. ../Toy/source
CFLAGS+=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
LIBS+=-lSDL2 -lSDL2_image -ltoy
ODIR = obj
SRC = $(wildcard *.c)
OBJ = $(addprefix $(ODIR)/,$(SRC:.c=.o))
TOYLIBS = $(wildcard ../Toy/repl/lib*) $(wildcard ../Toy/repl/repl_tools.*)
OUTNAME=box
ifeq ($(findstring CYGWIN, $(shell uname)),CYGWIN)
LIBLINE =-Wl,--out-implib=$(BOX_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
OUT=$(BOX_OUTDIR)/$(OUTNAME).dll
else ifeq ($(shell uname),Linux)
LIBLINE=-Wl,--out-implib=./$(BOX_OUTDIR)/lib$(OUTNAME).a -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
OUT=./$(BOX_OUTDIR)/lib$(OUTNAME).so
CFLAGS += -fPIC
else ifeq ($(OS),Windows_NT)
LIBLINE =-Wl,--out-implib=$(BOX_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
OUT=$(BOX_OUTDIR)/$(OUTNAME).dll
else
@echo "Platform test failed - what platform is this?"
exit 1
endif
library: libs $(OBJ)
$(CC) -DBOX_EXPORT $(CFLAGS) -shared -o $(OUT) $(LIBLINE) -L../$(LIBDIR) $(LIBS)
static: libs $(OBJ)
ar crs $(BOX_OUTDIR)/lib$(OUTNAME).a $(OBJ) -L../$(LIBDIR) $(LIBS)
#copy the stuff from Toy/repl that is needed
libs:
cp $(TOYLIBS) .
$(OBJ): | $(ODIR)
$(ODIR):
mkdir $(ODIR)
$(ODIR)/%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
.PHONY: clean
clean-libs:
$(RM) $(notdir $(TOYLIBS))