mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Began working on runner library
This commit is contained in:
275
repl/lib_runner.c
Normal file
275
repl/lib_runner.c
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
#include "lib_runner.h"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
#include "repl_tools.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct Runner {
|
||||||
|
Interpreter interpreter;
|
||||||
|
unsigned char* bytecode;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
//
|
||||||
|
} Runner;
|
||||||
|
|
||||||
|
//Toy native functions
|
||||||
|
static int nativeLoadScript(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to loadScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the argument
|
||||||
|
Literal drivePathLiteral = popLiteralArray(arguments);
|
||||||
|
RefString* drivePath = copyRefString(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 (toCString(drivePath)[driveLength] != ':') {
|
||||||
|
if (driveLength >= lengthRefString(drivePath)) {
|
||||||
|
interpreter->errorOutput("Incorrect drive path format given to loadScript\n");
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefString* drive = createRefStringLength(toCString(drivePath), driveLength);
|
||||||
|
RefString* path = createRefStringLength( &toCString(drivePath)[driveLength + 1], lengthRefString(drivePath) - driveLength );
|
||||||
|
|
||||||
|
//get the real drive file path
|
||||||
|
Literal driveLiteral = TO_STRING_LITERAL(drive);
|
||||||
|
Literal realDriveLiteral = getLiteralDictionary(getDriveDictionary(), driveLiteral);
|
||||||
|
|
||||||
|
if (!IS_STRING(realDriveLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect literal type found for drive: ");
|
||||||
|
printLiteralCustom(realDriveLiteral, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\n");
|
||||||
|
freeLiteral(realDriveLiteral);
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
deleteRefString(drive);
|
||||||
|
deleteRefString(path);
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the final real file path (concat) TODO: move this concat to refstring library
|
||||||
|
RefString* realDrive = copyRefString(AS_STRING(realDriveLiteral));
|
||||||
|
int realLength = lengthRefString(realDrive) + lengthRefString(path);
|
||||||
|
|
||||||
|
char* filePath = ALLOCATE(char, realLength) +1 + 1; //+1 for null
|
||||||
|
snprintf(filePath, realLength, "%s%s", toCString(realDrive), toCString(path));
|
||||||
|
|
||||||
|
//clean up the drivepath stuff
|
||||||
|
FREE_ARRAY(char, filePath, realLength);
|
||||||
|
deleteRefString(realDrive);
|
||||||
|
freeLiteral(realDriveLiteral);
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
deleteRefString(drive);
|
||||||
|
deleteRefString(path);
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
|
//load and compile the bytecode
|
||||||
|
size_t fileSize = 0;
|
||||||
|
char* source = readFile(filePath, &fileSize);
|
||||||
|
|
||||||
|
if (!source) {
|
||||||
|
interpreter->errorOutput("Failed to load source file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* bytecode = compileString(source, &fileSize);
|
||||||
|
free((void*)source);
|
||||||
|
|
||||||
|
if (!bytecode) {
|
||||||
|
interpreter->errorOutput("Failed to compile source file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the runner object
|
||||||
|
Runner* runner = ALLOCATE(Runner, 1);
|
||||||
|
initInterpreter(&runner->interpreter);
|
||||||
|
runner->bytecode = bytecode;
|
||||||
|
runner->size = fileSize;
|
||||||
|
|
||||||
|
//build the opaque object, and push it to the stack
|
||||||
|
Literal runnerLiteral = TO_OPAQUE_LITERAL(runner, OPAQUE_TAG_RUNNER);
|
||||||
|
pushLiteralArray(&interpreter->stack, runnerLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeRunScript(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _runScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeGetScriptVar(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _getScriptVar\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeCallScriptFn(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _callScriptFn\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeResetScript(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 0) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _resetScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeFreeScript(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to _freeScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Literal runnerLiteral = popLiteralArray(arguments);
|
||||||
|
|
||||||
|
if (IS_IDENTIFIER(runnerLiteral)) {
|
||||||
|
Literal idn = runnerLiteral;
|
||||||
|
parseIdentifierToValue(interpreter, &runnerLiteral);
|
||||||
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OPAQUE_TAG(runnerLiteral) != OPAQUE_TAG_RUNNER) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in _freeScript\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Runner* runner = AS_OPAQUE(runnerLiteral);
|
||||||
|
|
||||||
|
//clear out the runner object
|
||||||
|
freeInterpreter(&runner->interpreter);
|
||||||
|
FREE_ARRAY(unsigned char, runner->bytecode, runner->size);
|
||||||
|
|
||||||
|
FREE(Runner, runner);
|
||||||
|
|
||||||
|
freeLiteral(runnerLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the hook
|
||||||
|
typedef struct Natives {
|
||||||
|
char* name;
|
||||||
|
NativeFn fn;
|
||||||
|
} Natives;
|
||||||
|
|
||||||
|
int hookRunner(Interpreter* interpreter, Literal identifier, Literal alias) {
|
||||||
|
//build the natives list
|
||||||
|
Natives natives[] = {
|
||||||
|
{"loadScript", nativeLoadScript},
|
||||||
|
{"_runScript", nativeRunScript},
|
||||||
|
{"_getScriptVar", nativeGetScriptVar},
|
||||||
|
{"_callScriptFn", nativeCallScriptFn},
|
||||||
|
{"_resetScript", nativeResetScript},
|
||||||
|
{"_freeScript", nativeFreeScript},
|
||||||
|
{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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//file system API
|
||||||
|
static LiteralDictionary driveDictionary;
|
||||||
|
|
||||||
|
void initDriveDictionary() {
|
||||||
|
initLiteralDictionary(&driveDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeDriveDictionary() {
|
||||||
|
freeLiteralDictionary(&driveDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteralDictionary* getDriveDictionary() {
|
||||||
|
return &driveDictionary;
|
||||||
|
}
|
||||||
12
repl/lib_runner.h
Normal file
12
repl/lib_runner.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
int hookRunner(Interpreter* interpreter, Literal identifier, Literal alias);
|
||||||
|
|
||||||
|
//file system API - these need to be set by the host
|
||||||
|
void initDriveDictionary();
|
||||||
|
void freeDriveDictionary();
|
||||||
|
LiteralDictionary* getDriveDictionary();
|
||||||
|
|
||||||
|
#define OPAQUE_TAG_RUNNER 100
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
#include "lib_timer.h"
|
#include "lib_timer.h"
|
||||||
|
#include "lib_runner.h"
|
||||||
|
|
||||||
#include "console_colors.h"
|
#include "console_colors.h"
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ void repl() {
|
|||||||
//inject the libs
|
//inject the libs
|
||||||
injectNativeHook(&interpreter, "standard", hookStandard);
|
injectNativeHook(&interpreter, "standard", hookStandard);
|
||||||
injectNativeHook(&interpreter, "timer", hookTimer);
|
injectNativeHook(&interpreter, "timer", hookTimer);
|
||||||
|
injectNativeHook(&interpreter, "runner", hookRunner);
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
printf("> ");
|
printf("> ");
|
||||||
@@ -88,6 +90,17 @@ void repl() {
|
|||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
initCommand(argc, argv);
|
initCommand(argc, argv);
|
||||||
|
|
||||||
|
//lib setup (hacky - only really for this program)
|
||||||
|
initDriveDictionary();
|
||||||
|
|
||||||
|
Literal driveLiteral = TO_STRING_LITERAL(createRefString("scripts"));
|
||||||
|
Literal pathLiteral = TO_STRING_LITERAL(createRefString("scripts"));
|
||||||
|
|
||||||
|
setLiteralDictionary(getDriveDictionary(), driveLiteral, pathLiteral);
|
||||||
|
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
freeLiteral(pathLiteral);
|
||||||
|
|
||||||
//command specific actions
|
//command specific actions
|
||||||
if (command.error) {
|
if (command.error) {
|
||||||
usageCommand(argc, argv);
|
usageCommand(argc, argv);
|
||||||
@@ -112,12 +125,20 @@ int main(int argc, const char* argv[]) {
|
|||||||
//run source file
|
//run source file
|
||||||
if (command.sourcefile) {
|
if (command.sourcefile) {
|
||||||
runSourceFile(command.sourcefile);
|
runSourceFile(command.sourcefile);
|
||||||
|
|
||||||
|
//lib cleanup
|
||||||
|
freeDriveDictionary();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//run from stdin
|
//run from stdin
|
||||||
if (command.source) {
|
if (command.source) {
|
||||||
runSource(command.source);
|
runSource(command.source);
|
||||||
|
|
||||||
|
//lib cleanup
|
||||||
|
freeDriveDictionary();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +157,17 @@ int main(int argc, const char* argv[]) {
|
|||||||
//run binary
|
//run binary
|
||||||
if (command.binaryfile) {
|
if (command.binaryfile) {
|
||||||
runBinaryFile(command.binaryfile);
|
runBinaryFile(command.binaryfile);
|
||||||
|
|
||||||
|
//lib cleanup
|
||||||
|
freeDriveDictionary();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
repl();
|
repl();
|
||||||
|
|
||||||
|
//lib cleanup
|
||||||
|
freeDriveDictionary();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
#include "lib_timer.h"
|
#include "lib_timer.h"
|
||||||
|
#include "lib_runner.h"
|
||||||
|
|
||||||
#include "console_colors.h"
|
#include "console_colors.h"
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ char* readFile(char* path, size_t* fileSize) {
|
|||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path);
|
fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path);
|
||||||
exit(-1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(file, 0L, SEEK_END);
|
fseek(file, 0L, SEEK_END);
|
||||||
@@ -29,7 +30,7 @@ char* readFile(char* path, size_t* fileSize) {
|
|||||||
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
fprintf(stderr, ERROR "Not enough memory to read \"%s\"\n" RESET, path);
|
fprintf(stderr, ERROR "Not enough memory to read \"%s\"\n" RESET, path);
|
||||||
exit(-1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
|
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
|
||||||
@@ -38,7 +39,7 @@ char* readFile(char* path, size_t* fileSize) {
|
|||||||
|
|
||||||
if (bytesRead < *fileSize) {
|
if (bytesRead < *fileSize) {
|
||||||
fprintf(stderr, ERROR "Could not read file \"%s\"\n" RESET, path);
|
fprintf(stderr, ERROR "Could not read file \"%s\"\n" RESET, path);
|
||||||
exit(-1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -46,22 +47,24 @@ char* readFile(char* path, size_t* fileSize) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFile(char* path, unsigned char* bytes, size_t size) {
|
int writeFile(char* path, unsigned char* bytes, size_t size) {
|
||||||
FILE* file = fopen(path, "wb");
|
FILE* file = fopen(path, "wb");
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path);
|
fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path);
|
||||||
exit(-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int written = fwrite(bytes, size, 1, file);
|
int written = fwrite(bytes, size, 1, file);
|
||||||
|
|
||||||
if (written != 1) {
|
if (written != 1) {
|
||||||
fprintf(stderr, ERROR "Could not write file \"%s\"\n" RESET, path);
|
fprintf(stderr, ERROR "Could not write file \"%s\"\n" RESET, path);
|
||||||
exit(-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//repl functions
|
//repl functions
|
||||||
@@ -79,7 +82,6 @@ unsigned char* compileString(char* source, size_t* size) {
|
|||||||
while(node != NULL) {
|
while(node != NULL) {
|
||||||
//pack up and leave
|
//pack up and leave
|
||||||
if (node->type == AST_NODE_ERROR) {
|
if (node->type == AST_NODE_ERROR) {
|
||||||
printf(ERROR "error node detected\n" RESET);
|
|
||||||
freeASTNode(node);
|
freeASTNode(node);
|
||||||
freeCompiler(&compiler);
|
freeCompiler(&compiler);
|
||||||
freeParser(&parser);
|
freeParser(&parser);
|
||||||
@@ -110,6 +112,7 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
//inject the libs
|
//inject the libs
|
||||||
injectNativeHook(&interpreter, "standard", hookStandard);
|
injectNativeHook(&interpreter, "standard", hookStandard);
|
||||||
injectNativeHook(&interpreter, "timer", hookTimer);
|
injectNativeHook(&interpreter, "timer", hookTimer);
|
||||||
|
injectNativeHook(&interpreter, "runner", hookRunner);
|
||||||
|
|
||||||
runInterpreter(&interpreter, tb, size);
|
runInterpreter(&interpreter, tb, size);
|
||||||
freeInterpreter(&interpreter);
|
freeInterpreter(&interpreter);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
|
|
||||||
char* readFile(char* path, size_t* fileSize);
|
char* readFile(char* path, size_t* fileSize);
|
||||||
void writeFile(char* path, unsigned char* bytes, size_t size);
|
int writeFile(char* path, unsigned char* bytes, size_t size);
|
||||||
|
|
||||||
unsigned char* compileString(char* source, size_t* size);
|
unsigned char* compileString(char* source, size_t* size);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ IDIR +=. ../source ../repl
|
|||||||
CFLAGS +=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
|
CFLAGS +=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
|
||||||
LIBS +=
|
LIBS +=
|
||||||
ODIR = obj
|
ODIR = obj
|
||||||
TARGETS = $(wildcard ../source/*.c) $(wildcard ../repl/lib_*.c)
|
TARGETS = $(wildcard ../source/*.c) $(wildcard ../repl/lib_*.c) ../repl/repl_tools.c
|
||||||
TESTS = $(wildcard test_*.c)
|
TESTS = $(wildcard test_*.c)
|
||||||
OBJ = $(addprefix $(ODIR)/,$(TARGETS:../source/%.c=%.o)) $(addprefix $(ODIR)/,$(TESTS:.c=.o))
|
OBJ = $(addprefix $(ODIR)/,$(TARGETS:../source/%.c=%.o)) $(addprefix $(ODIR)/,$(TESTS:.c=.o))
|
||||||
|
|
||||||
|
|||||||
12
test/scripts/compiler_sample_code.toy
Normal file
12
test/scripts/compiler_sample_code.toy
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
fn fib(n : int) {
|
||||||
|
if (n < 2) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fib(n-1) + fib(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
var res = fib(i);
|
||||||
|
print string i + ": " + string res;
|
||||||
|
}
|
||||||
16
test/scripts/lib/runner.toy
Normal file
16
test/scripts/lib/runner.toy
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import runner;
|
||||||
|
|
||||||
|
//test basic loading and freeing of code
|
||||||
|
{
|
||||||
|
var s = loadScript("scripts:/runner_sample_code.toy");
|
||||||
|
|
||||||
|
s.freeScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: test running an external script
|
||||||
|
//TODO: test resetting an external script
|
||||||
|
//TODO: test retrieving a script variable
|
||||||
|
//TODO: test calling a script function
|
||||||
|
|
||||||
|
|
||||||
|
print "All good";
|
||||||
12
test/scripts/parser_sample_code.toy
Normal file
12
test/scripts/parser_sample_code.toy
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
fn fib(n : int) {
|
||||||
|
if (n < 2) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fib(n-1) + fib(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
var res = fib(i);
|
||||||
|
print string i + ": " + string res;
|
||||||
|
}
|
||||||
12
test/scripts/runner_sample_code.toy
Normal file
12
test/scripts/runner_sample_code.toy
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
fn fib(n : int) {
|
||||||
|
if (n < 2) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fib(n-1) + fib(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
var res = fib(i);
|
||||||
|
print string i + ": " + string res;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var complex: type = astype [string: [int]];
|
|
||||||
var deep: type = astype [[[ int ]]];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -17,78 +19,6 @@ static void noPrintFn(const char* output) {
|
|||||||
//NO OP
|
//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_NODE_ERROR) {
|
|
||||||
printf(ERROR "error node detected\n" RESET);
|
|
||||||
freeASTNode(node);
|
|
||||||
freeCompiler(&compiler);
|
|
||||||
freeParser(&parser);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeCompiler(&compiler, node);
|
|
||||||
freeASTNode(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) {
|
void error(char* msg) {
|
||||||
printf("%s", msg);
|
printf("%s", msg);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
@@ -6,44 +6,12 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//IO 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
//test init & free
|
//test init & free
|
||||||
@@ -84,7 +52,7 @@ int main() {
|
|||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
size_t sourceLength = 0;
|
size_t sourceLength = 0;
|
||||||
char* source = readFile("scripts/sample_code.toy", &sourceLength);
|
char* source = readFile("scripts/compiler_sample_code.toy", &sourceLength);
|
||||||
|
|
||||||
//test basic compilation & collation
|
//test basic compilation & collation
|
||||||
Lexer lexer;
|
Lexer lexer;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -28,79 +30,7 @@ static void noAssertFn(const char* output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//compilation functions
|
void runBinaryCustom(unsigned char* tb, size_t size) {
|
||||||
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_NODE_ERROR) {
|
|
||||||
printf(ERROR "error node detected\n" RESET);
|
|
||||||
freeASTNode(node);
|
|
||||||
freeCompiler(&compiler);
|
|
||||||
freeParser(&parser);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeCompiler(&compiler, node);
|
|
||||||
freeASTNode(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 runBinary(unsigned char* tb, size_t size) {
|
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
initInterpreter(&interpreter);
|
initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -112,19 +42,19 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
freeInterpreter(&interpreter);
|
freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSource(char* source) {
|
void runSourceCustom(char* source) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = compileString(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runBinary(tb, size);
|
runBinaryCustom(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceFile(char* fname) {
|
void runSourceFileCustom(char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
char* source = readFile(fname, &size);
|
char* source = readFile(fname, &size);
|
||||||
runSource(source);
|
runSourceCustom(source);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +138,7 @@ int main() {
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
snprintf(buffer, 128, "scripts/%s", filenames[i]);
|
snprintf(buffer, 128, "scripts/%s", filenames[i]);
|
||||||
|
|
||||||
runSourceFile(buffer);
|
runSourceFileCustom(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include "../repl/lib_standard.h"
|
#include "../repl/lib_standard.h"
|
||||||
#include "../repl/lib_timer.h"
|
#include "../repl/lib_timer.h"
|
||||||
|
#include "../repl/lib_runner.h"
|
||||||
|
|
||||||
//supress the print output
|
//supress the print output
|
||||||
static void noPrintFn(const char* output) {
|
static void noPrintFn(const char* output) {
|
||||||
@@ -32,78 +35,6 @@ static void errorWrapper(const char* output) {
|
|||||||
fprintf(stderr, ERROR "%s" RESET, output);
|
fprintf(stderr, ERROR "%s" RESET, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
//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_NODE_ERROR) {
|
|
||||||
printf(ERROR "error node detected\n" RESET);
|
|
||||||
freeASTNode(node);
|
|
||||||
freeCompiler(&compiler);
|
|
||||||
freeParser(&parser);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeCompiler(&compiler, node);
|
|
||||||
freeASTNode(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 runBinaryWithLibrary(unsigned char* tb, size_t size, char* library, HookFn hook) {
|
void runBinaryWithLibrary(unsigned char* tb, size_t size, char* library, HookFn hook) {
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
initInterpreter(&interpreter);
|
initInterpreter(&interpreter);
|
||||||
@@ -127,12 +58,24 @@ typedef struct Payload {
|
|||||||
} Payload;
|
} Payload;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
//setup the runner filesystem (hacky)
|
||||||
|
initDriveDictionary();
|
||||||
|
|
||||||
|
Literal driveLiteral = TO_STRING_LITERAL(createRefString("scripts"));
|
||||||
|
Literal pathLiteral = TO_STRING_LITERAL(createRefString("scripts"));
|
||||||
|
|
||||||
|
setLiteralDictionary(getDriveDictionary(), driveLiteral, pathLiteral);
|
||||||
|
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
freeLiteral(pathLiteral);
|
||||||
|
|
||||||
{
|
{
|
||||||
//run each file in test/scripts
|
//run each file in test/scripts
|
||||||
Payload payloads[] = {
|
Payload payloads[] = {
|
||||||
{"interactions.toy", "standard", hookStandard}, //interactions needs standard
|
{"interactions.toy", "standard", hookStandard}, //interactions needs standard
|
||||||
{"standard.toy", "standard", hookStandard},
|
{"standard.toy", "standard", hookStandard},
|
||||||
{"timer.toy", "timer", hookTimer},
|
{"timer.toy", "timer", hookTimer},
|
||||||
|
{"runner.toy", "runner", hookRunner},
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,17 +88,28 @@ int main() {
|
|||||||
//compile the source
|
//compile the source
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = readFile(fname, &size);
|
char* source = readFile(fname, &size);
|
||||||
|
if (!source) {
|
||||||
|
printf(ERROR "Failed to load file: %s\n" RESET, fname);
|
||||||
|
failedAsserts++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = compileString(source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
printf(ERROR "Failed to compile file: %s" RESET, fname);
|
printf(ERROR "Failed to compile file: %s\n" RESET, fname);
|
||||||
|
failedAsserts++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
runBinaryWithLibrary(tb, size, payloads[i].libname, payloads[i].hook);
|
runBinaryWithLibrary(tb, size, payloads[i].libname, payloads[i].hook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//lib cleanup
|
||||||
|
freeDriveDictionary();
|
||||||
|
|
||||||
if (!failedAsserts) {
|
if (!failedAsserts) {
|
||||||
printf(NOTICE "All good\n" RESET);
|
printf(NOTICE "All good\n" RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -21,41 +23,7 @@ static void noErrorFn(const char* output) {
|
|||||||
errorsTriggered++;
|
errorsTriggered++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//compilation functions
|
unsigned char* compileStringCustom(char* source, size_t* size) {
|
||||||
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;
|
Lexer lexer;
|
||||||
Parser parser;
|
Parser parser;
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
@@ -69,7 +37,7 @@ unsigned char* compileString(char* source, size_t* size) {
|
|||||||
while(node != NULL) {
|
while(node != NULL) {
|
||||||
//pack up and leave
|
//pack up and leave
|
||||||
if (node->type == AST_NODE_ERROR) {
|
if (node->type == AST_NODE_ERROR) {
|
||||||
errorsTriggered++;
|
errorsTriggered++; //custom error catch
|
||||||
freeASTNode(node);
|
freeASTNode(node);
|
||||||
freeCompiler(&compiler);
|
freeCompiler(&compiler);
|
||||||
freeParser(&parser);
|
freeParser(&parser);
|
||||||
@@ -93,7 +61,7 @@ unsigned char* compileString(char* source, size_t* size) {
|
|||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void runBinary(unsigned char* tb, size_t size) {
|
void runBinaryCustom(unsigned char* tb, size_t size) {
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
initInterpreter(&interpreter);
|
initInterpreter(&interpreter);
|
||||||
|
|
||||||
@@ -105,19 +73,19 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
freeInterpreter(&interpreter);
|
freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSource(char* source) {
|
void runSourceCustom(char* source) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = compileStringCustom(source, &size);
|
||||||
if (!tb) {
|
if (!tb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runBinary(tb, size);
|
runBinaryCustom(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSourceFile(char* fname) {
|
void runSourceFileCustom(char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
char* source = readFile(fname, &size);
|
char* source = readFile(fname, &size);
|
||||||
runSource(source);
|
runSourceCustom(source);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +110,7 @@ int main() {
|
|||||||
char buffer[128];
|
char buffer[128];
|
||||||
snprintf(buffer, 128, "scripts/mustfail/%s", filenames[i]);
|
snprintf(buffer, 128, "scripts/mustfail/%s", filenames[i]);
|
||||||
|
|
||||||
runSourceFile(buffer);
|
runSourceFileCustom(buffer);
|
||||||
|
|
||||||
if (errorsTriggered == 0) {
|
if (errorsTriggered == 0) {
|
||||||
printf(ERROR "Expected error did not occur in %s\n" RESET, filenames[i]);
|
printf(ERROR "Expected error did not occur in %s\n" RESET, filenames[i]);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -15,78 +17,6 @@ static void noPrintFn(const char* output) {
|
|||||||
//NO OP
|
//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_NODE_ERROR) {
|
|
||||||
printf(ERROR "error node detected\n" RESET);
|
|
||||||
freeASTNode(node);
|
|
||||||
freeCompiler(&compiler);
|
|
||||||
freeParser(&parser);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeCompiler(&compiler, node);
|
|
||||||
freeASTNode(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) {
|
void error(char* msg) {
|
||||||
printf("%s", msg);
|
printf("%s", msg);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
@@ -2,44 +2,12 @@
|
|||||||
|
|
||||||
#include "console_colors.h"
|
#include "console_colors.h"
|
||||||
|
|
||||||
|
#include "../repl/repl_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//IO 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
{
|
{
|
||||||
//source
|
//source
|
||||||
@@ -90,7 +58,7 @@ int main() {
|
|||||||
{
|
{
|
||||||
//get the source file
|
//get the source file
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char* source = readFile("scripts/sample_code.toy", &size);
|
char* source = readFile("scripts/parser_sample_code.toy", &size);
|
||||||
|
|
||||||
//test parsing a chunk of junk (valgrind will find leaks)
|
//test parsing a chunk of junk (valgrind will find leaks)
|
||||||
Lexer lexer;
|
Lexer lexer;
|
||||||
|
|||||||
Reference in New Issue
Block a user