Began working on runner library

This commit is contained in:
2023-01-20 13:42:45 +00:00
parent 390f60e0ce
commit e6e24ca19f
18 changed files with 435 additions and 426 deletions

275
repl/lib_runner.c Normal file
View 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
View 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

View File

@@ -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;
} }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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))

View 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;
}

View 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";

View 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;
}

View 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;
}

View File

@@ -1,9 +0,0 @@
var complex: type = astype [string: [int]];
var deep: type = astype [[[ int ]]];

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
} }
} }

View File

@@ -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);
} }

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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;