mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Added a utility to call toy functions from C
This commit is contained in:
23
scripts/test/call-from-host.toy
Normal file
23
scripts/test/call-from-host.toy
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//create a bunch of toy functions as literals to be called from C
|
||||||
|
|
||||||
|
fn answer() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn identity(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn makeCounter() {
|
||||||
|
var total = 0;
|
||||||
|
|
||||||
|
fn counter() {
|
||||||
|
return ++total;
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fail() {
|
||||||
|
assert false, "Failed correctly";
|
||||||
|
}
|
||||||
@@ -1189,8 +1189,27 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ret = callLiteralFn(interpreter, func, &arguments, &interpreter->stack);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
interpreter->errorOutput("Error encountered in function \"");
|
||||||
|
printLiteralCustom(identifier, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteral(func);
|
||||||
freeLiteral(identifier);
|
freeLiteral(identifier);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool callLiteralFn(Interpreter* interpreter, Literal func, LiteralArray* arguments, LiteralArray* returns) {
|
||||||
|
if (!IS_FUNCTION(func)) {
|
||||||
|
interpreter->errorOutput("Function required in callLiteralFn()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//set up a new interpreter
|
//set up a new interpreter
|
||||||
Interpreter inner;
|
Interpreter inner;
|
||||||
|
|
||||||
@@ -1225,13 +1244,10 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check the param total is correct
|
//check the param total is correct
|
||||||
if ((IS_NULL(restParam) && paramArray->count != arguments.count * 2) || (!IS_NULL(restParam) && paramArray->count -2 > arguments.count * 2)) {
|
if ((IS_NULL(restParam) && paramArray->count != arguments->count * 2) || (!IS_NULL(restParam) && paramArray->count -2 > arguments->count * 2)) {
|
||||||
interpreter->errorOutput("Incorrect number of arguments passed to function \"");
|
interpreter->errorOutput("Incorrect number of arguments passed to a function\n");
|
||||||
printLiteralCustom(identifier, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\"\n");
|
|
||||||
|
|
||||||
//free, and skip out
|
//free, and skip out
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
popScope(inner.scope);
|
popScope(inner.scope);
|
||||||
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
@@ -1247,7 +1263,6 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
interpreter->errorOutput("[internal] Could not re-declare parameter\n");
|
interpreter->errorOutput("[internal] Could not re-declare parameter\n");
|
||||||
|
|
||||||
//free, and skip out
|
//free, and skip out
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
popScope(inner.scope);
|
popScope(inner.scope);
|
||||||
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
@@ -1256,7 +1271,7 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal arg = popLiteralArray(&arguments);
|
Literal arg = popLiteralArray(arguments);
|
||||||
|
|
||||||
if (IS_IDENTIFIER(arg)) {
|
if (IS_IDENTIFIER(arg)) {
|
||||||
Literal idn = arg;
|
Literal idn = arg;
|
||||||
@@ -1269,10 +1284,8 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
|
|
||||||
//free, and skip out
|
//free, and skip out
|
||||||
freeLiteral(arg);
|
freeLiteral(arg);
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
popScope(inner.scope);
|
popScope(inner.scope);
|
||||||
|
|
||||||
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
freeLiteralArray(&inner.literalCache);
|
freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
@@ -1286,8 +1299,8 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
LiteralArray rest;
|
LiteralArray rest;
|
||||||
initLiteralArray(&rest);
|
initLiteralArray(&rest);
|
||||||
|
|
||||||
while (arguments.count > 0) {
|
while (arguments->count > 0) {
|
||||||
Literal lit = popLiteralArray(&arguments);
|
Literal lit = popLiteralArray(arguments);
|
||||||
pushLiteralArray(&rest, lit);
|
pushLiteralArray(&rest, lit);
|
||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
}
|
}
|
||||||
@@ -1303,7 +1316,6 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
//free, and skip out
|
//free, and skip out
|
||||||
freeLiteral(restType);
|
freeLiteral(restType);
|
||||||
freeLiteralArray(&rest);
|
freeLiteralArray(&rest);
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
popScope(inner.scope);
|
popScope(inner.scope);
|
||||||
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
@@ -1319,7 +1331,6 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
//free, and skip out
|
//free, and skip out
|
||||||
freeLiteral(restType);
|
freeLiteral(restType);
|
||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
popScope(inner.scope);
|
popScope(inner.scope);
|
||||||
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
@@ -1339,27 +1350,27 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
interpreter->panic = inner.panic;
|
interpreter->panic = inner.panic;
|
||||||
|
|
||||||
//accept the stack as the results
|
//accept the stack as the results
|
||||||
LiteralArray returns;
|
LiteralArray returnsFromInner;
|
||||||
initLiteralArray(&returns);
|
initLiteralArray(&returnsFromInner);
|
||||||
|
|
||||||
//unpack the results
|
//unpack the results
|
||||||
for (int i = 0; i < (returnArray->count || 1); i++) {
|
for (int i = 0; i < (returnArray->count || 1); i++) {
|
||||||
Literal lit = popLiteralArray(&inner.stack);
|
Literal lit = popLiteralArray(&inner.stack);
|
||||||
pushLiteralArray(&returns, lit); //NOTE: also reverses the order
|
pushLiteralArray(&returnsFromInner, lit); //NOTE: also reverses the order
|
||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool returnValue = true;
|
bool returnValue = true;
|
||||||
|
|
||||||
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
||||||
if (returns.count > 1) {
|
if (returnsFromInner.count > 1) {
|
||||||
interpreter->errorOutput("Too many values returned (multiple returns not yet supported)\n");
|
interpreter->errorOutput("Too many values returned (multiple returns not yet supported)\n");
|
||||||
|
|
||||||
returnValue = false;
|
returnValue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < returns.count && returnValue; i++) {
|
for (int i = 0; i < returnsFromInner.count && returnValue; i++) {
|
||||||
Literal ret = popLiteralArray(&returns);
|
Literal ret = popLiteralArray(&returnsFromInner);
|
||||||
|
|
||||||
//check the return types
|
//check the return types
|
||||||
if (returnArray->count > 0 && AS_TYPE(returnArray->literals[i]).typeOf != ret.type) {
|
if (returnArray->count > 0 && AS_TYPE(returnArray->literals[i]).typeOf != ret.type) {
|
||||||
@@ -1370,7 +1381,7 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, ret); //NOTE: reverses again
|
pushLiteralArray(returns, ret); //NOTE: reverses again
|
||||||
freeLiteral(ret);
|
freeLiteral(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1392,16 +1403,33 @@ static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
|
|||||||
|
|
||||||
inner.scope = popScope(inner.scope);
|
inner.scope = popScope(inner.scope);
|
||||||
}
|
}
|
||||||
freeLiteralArray(&returns);
|
freeLiteralArray(&returnsFromInner);
|
||||||
freeLiteralArray(&arguments);
|
|
||||||
freeLiteralArray(&inner.stack);
|
freeLiteralArray(&inner.stack);
|
||||||
freeLiteralArray(&inner.literalCache);
|
freeLiteralArray(&inner.literalCache);
|
||||||
freeLiteral(func);
|
|
||||||
|
|
||||||
//actual bytecode persists until next call
|
//actual bytecode persists until next call
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool callFn(Interpreter* interpreter, char* name, LiteralArray* arguments, LiteralArray* returns) {
|
||||||
|
Literal key = TO_IDENTIFIER_LITERAL(copyString(name, strlen(name)), strlen(name));
|
||||||
|
Literal val = TO_NULL_LITERAL;
|
||||||
|
|
||||||
|
if (!isDelcaredScopeVariable(interpreter->scope, key)) {
|
||||||
|
interpreter->errorOutput("No function with that name\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getScopeVariable(interpreter->scope, key, &val);
|
||||||
|
|
||||||
|
bool ret = callLiteralFn(interpreter, val, arguments, returns);
|
||||||
|
|
||||||
|
freeLiteral(key);
|
||||||
|
freeLiteral(val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static bool execFnReturn(Interpreter* interpreter) {
|
static bool execFnReturn(Interpreter* interpreter) {
|
||||||
LiteralArray returns;
|
LiteralArray returns;
|
||||||
initLiteralArray(&returns);
|
initLiteralArray(&returns);
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ TOY_API bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func)
|
|||||||
typedef int (*HookFn)(Interpreter* interpreter, Literal identifier, Literal alias);
|
typedef int (*HookFn)(Interpreter* interpreter, Literal identifier, Literal alias);
|
||||||
TOY_API bool injectNativeHook(Interpreter* interpreter, char* name, HookFn hook);
|
TOY_API bool injectNativeHook(Interpreter* interpreter, char* name, HookFn hook);
|
||||||
|
|
||||||
|
TOY_API bool callLiteralFn(Interpreter* interpreter, Literal func, LiteralArray* arguments, LiteralArray* returns);
|
||||||
|
TOY_API bool callFn(Interpreter* interpreter, char* name, LiteralArray* arguments, LiteralArray* returns);
|
||||||
|
|
||||||
//utilities for the host program
|
//utilities for the host program
|
||||||
TOY_API bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr);
|
TOY_API bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr);
|
||||||
TOY_API void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput);
|
TOY_API void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput);
|
||||||
|
|||||||
312
test/test_call_from_host.c
Normal file
312
test/test_call_from_host.c
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
#include "lexer.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
#include "console_colors.h"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
//supress the print output
|
||||||
|
static void noPrintFn(const char* output) {
|
||||||
|
//NO OP
|
||||||
|
}
|
||||||
|
|
||||||
|
//compilation functions
|
||||||
|
char* readFile(char* path, size_t* fileSize) {
|
||||||
|
FILE* file = fopen(path, "rb");
|
||||||
|
|
||||||
|
if (file == NULL) {
|
||||||
|
fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0L, SEEK_END);
|
||||||
|
*fileSize = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
char* buffer = (char*)malloc(*fileSize + 1);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, ERROR "Not enough memory to read \"%s\"\n" RESET, path);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
|
||||||
|
|
||||||
|
buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this
|
||||||
|
|
||||||
|
if (bytesRead < *fileSize) {
|
||||||
|
fprintf(stderr, ERROR "Could not read file \"%s\"\n" RESET, path);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* compileString(char* source, size_t* size) {
|
||||||
|
Lexer lexer;
|
||||||
|
Parser parser;
|
||||||
|
Compiler compiler;
|
||||||
|
|
||||||
|
initLexer(&lexer, source);
|
||||||
|
initParser(&parser, &lexer);
|
||||||
|
initCompiler(&compiler);
|
||||||
|
|
||||||
|
//run the parser until the end of the source
|
||||||
|
ASTNode* node = scanParser(&parser);
|
||||||
|
while(node != NULL) {
|
||||||
|
//pack up and leave
|
||||||
|
if (node->type == AST_NODEERROR) {
|
||||||
|
printf(ERROR "error node detected\n" RESET);
|
||||||
|
freeNode(node);
|
||||||
|
freeCompiler(&compiler);
|
||||||
|
freeParser(&parser);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCompiler(&compiler, node);
|
||||||
|
freeNode(node);
|
||||||
|
node = scanParser(&parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the bytecode dump
|
||||||
|
unsigned char* tb = collateCompiler(&compiler, (int*)(size));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
freeCompiler(&compiler);
|
||||||
|
freeParser(&parser);
|
||||||
|
//no lexer to clean up
|
||||||
|
|
||||||
|
//finally
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void error(char* msg) {
|
||||||
|
printf(msg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
char* source = readFile("../scripts//test/call-from-host.toy", &size);
|
||||||
|
unsigned char* tb = compileString(source, &size);
|
||||||
|
|
||||||
|
if (!tb) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter interpreter;
|
||||||
|
initInterpreter(&interpreter);
|
||||||
|
runInterpreter(&interpreter, tb, size);
|
||||||
|
|
||||||
|
//test answer
|
||||||
|
{
|
||||||
|
interpreter.printOutput("Testing answer");
|
||||||
|
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
callFn(&interpreter, "answer", &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_INTEGER(returns.literals[0]) || AS_INTEGER(returns.literals[0]) != 42) {
|
||||||
|
error("Returned value is incorrect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test identity
|
||||||
|
{
|
||||||
|
interpreter.printOutput("Testing identity");
|
||||||
|
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
//push an argument
|
||||||
|
float pi = 3.14;
|
||||||
|
Literal arg = TO_FLOAT_LITERAL(pi);
|
||||||
|
pushLiteralArray(&arguments, arg);
|
||||||
|
|
||||||
|
callFn(&interpreter, "identity", &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
float epsilon = 0.1; //because floats are evil
|
||||||
|
|
||||||
|
if (!IS_FLOAT(returns.literals[0]) || fabs(AS_FLOAT(returns.literals[0]) - pi) > epsilon) {
|
||||||
|
error("Returned value is incorrect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test makeCounter (closures)
|
||||||
|
{
|
||||||
|
interpreter.printOutput("Testing makeCounter (closures)");
|
||||||
|
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
callFn(&interpreter, "makeCounter", &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//grab the resulting literal
|
||||||
|
Literal counter = popLiteralArray(&returns);
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
|
||||||
|
//call counter repeatedly
|
||||||
|
{
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
callLiteralFn(&interpreter, counter, &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments (1) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns (1) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_INTEGER(returns.literals[0]) || AS_INTEGER(returns.literals[0]) != 1) {
|
||||||
|
error("Returned value (1) is incorrect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
callLiteralFn(&interpreter, counter, &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments (2) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns (2) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_INTEGER(returns.literals[0]) || AS_INTEGER(returns.literals[0]) != 2) {
|
||||||
|
error("Returned value (2) is incorrect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
callLiteralFn(&interpreter, counter, &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments (3) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1) {
|
||||||
|
error("Returns (3) has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_INTEGER(returns.literals[0]) || AS_INTEGER(returns.literals[0]) != 3) {
|
||||||
|
error("Returned value (3) is incorrect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//test assertion failure
|
||||||
|
{
|
||||||
|
interpreter.printOutput("Testing assertion failure");
|
||||||
|
|
||||||
|
LiteralArray arguments;
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
LiteralArray returns;
|
||||||
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
|
bool ret = callFn(&interpreter, "fail", &arguments, &returns);
|
||||||
|
|
||||||
|
//check the results
|
||||||
|
if (arguments.count != 0) {
|
||||||
|
error("Arguments has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returns.count != 1 || !IS_NULL(returns.literals[0])) {
|
||||||
|
error("Returns has the wrong number of members\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
error("Assertion gives the wrong return value\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeLiteralArray(&returns);
|
||||||
|
}
|
||||||
|
|
||||||
|
//clean up
|
||||||
|
freeInterpreter(&interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(NOTICE "All good\n" RESET);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
initInterpreter(&interpreter);
|
initInterpreter(&interpreter);
|
||||||
|
|
||||||
//NOTE: supress print output for testing
|
//NOTE: suppress print output for testing
|
||||||
setInterpreterPrint(&interpreter, noPrintFn);
|
setInterpreterPrint(&interpreter, noPrintFn);
|
||||||
|
|
||||||
runInterpreter(&interpreter, tb, size);
|
runInterpreter(&interpreter, tb, size);
|
||||||
|
|||||||
Reference in New Issue
Block a user