Playing around with scripts
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "lib_input.h"
|
||||
#include "lib_node.h"
|
||||
#include "lib_standard.h"
|
||||
#include "lib_random.h"
|
||||
#include "lib_runner.h"
|
||||
#include "repl_tools.h"
|
||||
|
||||
@@ -50,6 +51,7 @@ void Box_initEngine() {
|
||||
//init Toy
|
||||
Toy_initInterpreter(&engine.interpreter);
|
||||
Toy_injectNativeHook(&engine.interpreter, "standard", Toy_hookStandard);
|
||||
Toy_injectNativeHook(&engine.interpreter, "random", Toy_hookRandom);
|
||||
Toy_injectNativeHook(&engine.interpreter, "runner", Toy_hookRunner);
|
||||
Toy_injectNativeHook(&engine.interpreter, "engine", Box_hookEngine);
|
||||
Toy_injectNativeHook(&engine.interpreter, "node", Box_hookNode);
|
||||
@@ -338,7 +340,7 @@ void Box_execEngine() {
|
||||
//set up time
|
||||
engine.realTime = clock();
|
||||
engine.simTime = engine.realTime;
|
||||
clock_t delta = (double) CLOCKS_PER_SEC / 240.0;
|
||||
clock_t delta = (double) CLOCKS_PER_SEC / 60.0;
|
||||
|
||||
while (engine.running) {
|
||||
execEvents();
|
||||
|
||||
@@ -55,6 +55,8 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
||||
|
||||
//init the inner interpreter manually
|
||||
Toy_initLiteralArray(&inner.literalCache);
|
||||
Toy_initLiteralArray(&inner.stack);
|
||||
inner.hooks = interpreter->hooks;
|
||||
inner.scope = Toy_pushScope(NULL);
|
||||
inner.bytecode = tb;
|
||||
inner.length = size;
|
||||
@@ -62,8 +64,6 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
||||
inner.codeStart = -1;
|
||||
inner.depth = interpreter->depth + 1;
|
||||
inner.panic = false;
|
||||
Toy_initLiteralArray(&inner.stack);
|
||||
inner.hooks = interpreter->hooks;
|
||||
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
||||
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
||||
@@ -74,11 +74,7 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
||||
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
||||
|
||||
//cleanup
|
||||
while (inner.scope) {
|
||||
inner.scope = Toy_popScope(inner.scope);
|
||||
}
|
||||
|
||||
//cleanup (NOT the scope - that needs to hang around)
|
||||
Toy_freeLiteralArray(&inner.stack);
|
||||
Toy_freeLiteralArray(&inner.literalCache);
|
||||
Toy_freeLiteral(filePathLiteral);
|
||||
@@ -221,6 +217,11 @@ static int nativeGetNodeChild(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
|
||||
Toy_freeLiteral(parentIdn);
|
||||
}
|
||||
|
||||
Toy_Literal indexIdn = index;
|
||||
if (TOY_IS_IDENTIFIER(index) && Toy_parseIdentifierToValue(interpreter, &index)) {
|
||||
Toy_freeLiteral(indexIdn);
|
||||
}
|
||||
|
||||
if (!TOY_IS_OPAQUE(parent) || !TOY_IS_INTEGER(index)) {
|
||||
interpreter->errorOutput("Incorrect argument type passed to getNodeChild\n");
|
||||
Toy_freeLiteral(parent);
|
||||
@@ -528,15 +529,15 @@ static int nativeDrawNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nativeCallNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
static int nativeCallNodeFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//checks
|
||||
if (arguments->count < 2) {
|
||||
interpreter->errorOutput("Too few arguments passed to callNode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_LiteralArray extraArgs;
|
||||
Toy_initLiteralArray(&extraArgs);
|
||||
Toy_LiteralArray extraArgsBackwards;
|
||||
Toy_initLiteralArray(&extraArgsBackwards);
|
||||
|
||||
//extract the extra arg values
|
||||
while (arguments->count > 2) {
|
||||
@@ -547,10 +548,22 @@ static int nativeCallNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
||||
Toy_freeLiteral(idn);
|
||||
}
|
||||
|
||||
Toy_pushLiteralArray(&extraArgsBackwards, tmp);
|
||||
Toy_freeLiteral(tmp);
|
||||
}
|
||||
|
||||
//reverse the extra args
|
||||
Toy_LiteralArray extraArgs;
|
||||
Toy_initLiteralArray(&extraArgs);
|
||||
|
||||
while (extraArgsBackwards.count > 0) {
|
||||
Toy_Literal tmp = Toy_popLiteralArray(&extraArgsBackwards);
|
||||
Toy_pushLiteralArray(&extraArgs, tmp);
|
||||
Toy_freeLiteral(tmp);
|
||||
}
|
||||
|
||||
Toy_freeLiteralArray(&extraArgsBackwards);
|
||||
|
||||
//back on track
|
||||
Toy_Literal fnName = Toy_popLiteralArray(arguments);
|
||||
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||
@@ -609,7 +622,9 @@ int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter
|
||||
{"freeTexture", nativeFreeTexture},
|
||||
{"setRect", nativeSetRect},
|
||||
{"drawNode", nativeDrawNode},
|
||||
{"callNode", nativeCallNode},
|
||||
{"callNodeFn", nativeCallNodeFn},
|
||||
|
||||
//get rect, get node var, create empty node, get child count, get root node
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
196
box/lib_random.c
Normal file
196
box/lib_random.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#include "lib_random.h"
|
||||
|
||||
#include "toy_memory.h"
|
||||
|
||||
static int hashInt(int x) {
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = (x >> 16) ^ x;
|
||||
return x;
|
||||
}
|
||||
|
||||
typedef struct Toy_RandomGenerator {
|
||||
int seed; //mutated with each call
|
||||
} Toy_RandomGenerator;
|
||||
|
||||
//Toy native functions
|
||||
static int nativeCreateRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//arguments
|
||||
if (arguments->count != 1) {
|
||||
interpreter->errorOutput("Incorrect number of arguments to createRandomGenerator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//get the seed argument
|
||||
Toy_Literal seedLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
Toy_Literal seedLiteralIdn = seedLiteral;
|
||||
if (TOY_IS_IDENTIFIER(seedLiteral) && Toy_parseIdentifierToValue(interpreter, &seedLiteral)) {
|
||||
Toy_freeLiteral(seedLiteralIdn);
|
||||
}
|
||||
|
||||
if (TOY_IS_IDENTIFIER(seedLiteral)) {
|
||||
Toy_freeLiteral(seedLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!TOY_IS_INTEGER(seedLiteral)) {
|
||||
interpreter->errorOutput("Incorrect literal type passed to createRandomGenerator");
|
||||
Toy_freeLiteral(seedLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//generate the generator object
|
||||
Toy_RandomGenerator* generator = TOY_ALLOCATE(Toy_RandomGenerator, 1);
|
||||
generator->seed = TOY_AS_INTEGER(seedLiteral);
|
||||
Toy_Literal generatorLiteral = TOY_TO_OPAQUE_LITERAL(generator, TOY_OPAQUE_TAG_RANDOM);
|
||||
|
||||
//return and cleanup
|
||||
Toy_pushLiteralArray(&interpreter->stack, generatorLiteral);
|
||||
|
||||
Toy_freeLiteral(seedLiteral);
|
||||
Toy_freeLiteral(generatorLiteral);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nativeGenerateRandomNumber(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//no arguments
|
||||
if (arguments->count != 1) {
|
||||
interpreter->errorOutput("Incorrect number of arguments to generateRandomNumber\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//get the runner object
|
||||
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
Toy_Literal generatorLiteralIdn = generatorLiteral;
|
||||
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
|
||||
Toy_freeLiteral(generatorLiteralIdn);
|
||||
}
|
||||
|
||||
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
|
||||
Toy_freeLiteral(generatorLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
|
||||
interpreter->errorOutput("Unrecognized opaque literal in generateRandomNumber\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
|
||||
|
||||
//generate the new value and package up the return
|
||||
generator->seed = hashInt(generator->seed);
|
||||
|
||||
Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(generator->seed);
|
||||
|
||||
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||
|
||||
//cleanup
|
||||
Toy_freeLiteral(generatorLiteral);
|
||||
Toy_freeLiteral(resultLiteral);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nativeFreeRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//no arguments
|
||||
if (arguments->count != 1) {
|
||||
interpreter->errorOutput("Incorrect number of arguments to freeRandomGenerator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//get the runner object
|
||||
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
Toy_Literal generatorLiteralIdn = generatorLiteral;
|
||||
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
|
||||
Toy_freeLiteral(generatorLiteralIdn);
|
||||
}
|
||||
|
||||
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
|
||||
Toy_freeLiteral(generatorLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
|
||||
interpreter->errorOutput("Unrecognized opaque literal in freeRandomGenerator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
|
||||
|
||||
//clear out the runner object
|
||||
TOY_FREE(Toy_RandomGenerator, generator);
|
||||
Toy_freeLiteral(generatorLiteral);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//call the hook
|
||||
typedef struct Natives {
|
||||
const char* name;
|
||||
Toy_NativeFn fn;
|
||||
} Natives;
|
||||
|
||||
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||
//build the natives list
|
||||
Natives natives[] = {
|
||||
{"createRandomGenerator", nativeCreateRandomGenerator},
|
||||
{"generateRandomNumber", nativeGenerateRandomNumber},
|
||||
{"freeRandomGenerator", nativeFreeRandomGenerator},
|
||||
{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 -1;
|
||||
}
|
||||
|
||||
//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_NATIVE_LITERAL(natives[i].fn);
|
||||
|
||||
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;
|
||||
}
|
||||
7
box/lib_random.h
Normal file
7
box/lib_random.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "toy_interpreter.h"
|
||||
|
||||
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||
|
||||
#define TOY_OPAQUE_TAG_RANDOM 200
|
||||
@@ -7,6 +7,49 @@
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
if (arguments->count != 1) {
|
||||
interpreter->errorOutput("Incorrect number of arguments to abs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//get the self
|
||||
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
//parse to value if needed
|
||||
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||
Toy_freeLiteral(selfLiteralIdn);
|
||||
}
|
||||
|
||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
||||
Toy_freeLiteral(selfLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||
interpreter->errorOutput("Incorrect argument type passed to abs\n");
|
||||
Toy_freeLiteral(selfLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_Literal result;
|
||||
|
||||
if (TOY_IS_INTEGER(selfLiteral)) {
|
||||
result = TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(selfLiteral) > 0 ? TOY_AS_INTEGER(selfLiteral) : -TOY_AS_INTEGER(selfLiteral) );
|
||||
}
|
||||
if (TOY_IS_FLOAT(selfLiteral)) {
|
||||
result = TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(selfLiteral) > 0 ? TOY_AS_FLOAT(selfLiteral) : -TOY_AS_FLOAT(selfLiteral) );
|
||||
}
|
||||
|
||||
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||
|
||||
Toy_freeLiteral(result);
|
||||
Toy_freeLiteral(selfLiteral);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//no arguments
|
||||
if (arguments->count != 0) {
|
||||
@@ -702,6 +745,36 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
if (arguments->count != 1) {
|
||||
interpreter->errorOutput("Incorrect number of arguments to hash\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//get the self
|
||||
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
//parse to value if needed
|
||||
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||
Toy_freeLiteral(selfLiteralIdn);
|
||||
}
|
||||
|
||||
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
||||
Toy_freeLiteral(selfLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral));
|
||||
|
||||
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||
|
||||
Toy_freeLiteral(result);
|
||||
Toy_freeLiteral(selfLiteral);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//no arguments
|
||||
if (arguments->count != 2) {
|
||||
@@ -1667,6 +1740,7 @@ typedef struct Natives {
|
||||
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||
//build the natives list
|
||||
Natives natives[] = {
|
||||
{"abs", nativeAbs},
|
||||
{"clock", nativeClock},
|
||||
{"concat", nativeConcat}, //array, dictionary, string
|
||||
{"containsKey", nativeContainsKey}, //dictionary
|
||||
@@ -1676,6 +1750,7 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
||||
{"forEach", nativeForEach}, //array, dictionary
|
||||
{"getKeys", nativeGetKeys}, //dictionary
|
||||
{"getValues", nativeGetValues}, //dictionary
|
||||
{"hash", nativeHash},
|
||||
{"indexOf", nativeIndexOf}, //array
|
||||
{"map", nativeMap}, //array, dictionary
|
||||
{"reduce", nativeReduce}, //array, dictionary
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "repl_tools.h"
|
||||
#include "lib_about.h"
|
||||
#include "lib_standard.h"
|
||||
#include "lib_random.h"
|
||||
#include "lib_runner.h"
|
||||
|
||||
#include "toy_console_colors.h"
|
||||
@@ -112,6 +113,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
|
||||
//inject the libs
|
||||
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
|
||||
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
||||
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
||||
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
||||
|
||||
Toy_runInterpreter(&interpreter, tb, (int)size);
|
||||
|
||||
Reference in New Issue
Block a user