Packaged toy as a dll

This commit is contained in:
2022-09-11 07:56:06 +01:00
parent 5b420e0799
commit 95ba865cab
14 changed files with 136 additions and 43 deletions

View File

@@ -3,6 +3,12 @@ export OUTDIR = out
all: $(OUTDIR) all: $(OUTDIR)
$(MAKE) -C source $(MAKE) -C source
library: clean $(OUTDIR)
$(MAKE) -C source library
static: clean $(OUTDIR)
$(MAKE) -C source static
test: clean $(OUTDIR) test: clean $(OUTDIR)
$(MAKE) -C test $(MAKE) -C test

View File

@@ -2,6 +2,20 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h>
//test variable sizes based on platform
#define STATIC_ASSERT(test_for_true) static_assert((test_for_true), "(" #test_for_true ") failed")
STATIC_ASSERT(sizeof(char) == 1);
STATIC_ASSERT(sizeof(short) == 2);
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(float) == 4);
STATIC_ASSERT(sizeof(unsigned char) == 1);
STATIC_ASSERT(sizeof(unsigned short) == 2);
STATIC_ASSERT(sizeof(unsigned int) == 4);
#ifndef TOY_EXPORT
//declare the singleton //declare the singleton
Command command; Command command;
@@ -106,4 +120,6 @@ void copyrightCommand(int argc, const char* argv[]) {
printf("1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n\n"); printf("1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n\n");
printf("2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n\n"); printf("2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n\n");
printf("3. This notice may not be removed or altered from any source distribution.\n\n"); printf("3. This notice may not be removed or altered from any source distribution.\n\n");
} }
#endif

View File

@@ -9,6 +9,26 @@
#define TOY_VERSION_PATCH 0 #define TOY_VERSION_PATCH 0
#define TOY_VERSION_BUILD __DATE__ " " __TIME__ #define TOY_VERSION_BUILD __DATE__ " " __TIME__
//platform exports/imports
#if defined(WIN32) || defined(_WIN32)
#if defined(TOY_EXPORT)
#define TOY_API __declspec(dllexport)
#else
#define TOY_API __declspec(dllimport)
#endif
#elif defined(linux)
#define TOY_API extern
#else
#define TOY_API
#endif
#ifndef TOY_EXPORT
//for processing the command line arguments //for processing the command line arguments
typedef struct { typedef struct {
bool error; bool error;
@@ -29,6 +49,7 @@ void initCommand(int argc, const char* argv[]);
void usageCommand(int argc, const char* argv[]); void usageCommand(int argc, const char* argv[]);
void helpCommand(int argc, const char* argv[]); void helpCommand(int argc, const char* argv[]);
void copyrightCommand(int argc, const char* argv[]); void copyrightCommand(int argc, const char* argv[]);
#endif
//NOTE: assigning to a byte from a short loses data //NOTE: assigning to a byte from a short loses data
#define AS_USHORT(value) (*(unsigned short*)(&(value))) #define AS_USHORT(value) (*(unsigned short*)(&(value)))

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "common.h"
#include "opcodes.h" #include "opcodes.h"
#include "node.h" #include "node.h"
#include "literal_array.h" #include "literal_array.h"
@@ -13,9 +13,9 @@ typedef struct Compiler {
int count; int count;
} Compiler; } Compiler;
void initCompiler(Compiler* compiler); TOY_API void initCompiler(Compiler* compiler);
void writeCompiler(Compiler* compiler, Node* node); TOY_API void writeCompiler(Compiler* compiler, Node* node);
void freeCompiler(Compiler* compiler); TOY_API void freeCompiler(Compiler* compiler);
//embed the header with version information, data section, code section, etc. //embed the header, data section, code section, function section, etc.
unsigned char* collateCompiler(Compiler* compiler, int* size); TOY_API unsigned char* collateCompiler(Compiler* compiler, int* size);

View File

@@ -2032,9 +2032,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
//data section //data section
const unsigned short literalCount = readShort(interpreter->bytecode, &interpreter->count); const unsigned short literalCount = readShort(interpreter->bytecode, &interpreter->count);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf(NOTICE "Reading %d literals\n" RESET, literalCount); printf(NOTICE "Reading %d literals\n" RESET, literalCount);
} }
#endif
for (int i = 0; i < literalCount; i++) { for (int i = 0; i < literalCount; i++) {
const unsigned char literalType = readByte(interpreter->bytecode, &interpreter->count); const unsigned char literalType = readByte(interpreter->bytecode, &interpreter->count);
@@ -2044,9 +2046,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
//read the null //read the null
pushLiteralArray(&interpreter->literalCache, TO_NULL_LITERAL); pushLiteralArray(&interpreter->literalCache, TO_NULL_LITERAL);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(null)\n"); printf("(null)\n");
} }
#endif
break; break;
case LITERAL_BOOLEAN: { case LITERAL_BOOLEAN: {
@@ -2056,9 +2060,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(&interpreter->literalCache, literal); pushLiteralArray(&interpreter->literalCache, literal);
freeLiteral(literal); freeLiteral(literal);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(boolean %s)\n", b ? "true" : "false"); printf("(boolean %s)\n", b ? "true" : "false");
} }
#endif
} }
break; break;
@@ -2068,9 +2074,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(&interpreter->literalCache, literal); pushLiteralArray(&interpreter->literalCache, literal);
freeLiteral(literal); freeLiteral(literal);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(integer %d)\n", d); printf("(integer %d)\n", d);
} }
#endif
} }
break; break;
@@ -2080,9 +2088,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(&interpreter->literalCache, literal); pushLiteralArray(&interpreter->literalCache, literal);
freeLiteral(literal); freeLiteral(literal);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(float %f)\n", f); printf("(float %f)\n", f);
} }
#endif
} }
break; break;
@@ -2093,9 +2103,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(&interpreter->literalCache, literal); pushLiteralArray(&interpreter->literalCache, literal);
freeLiteral(literal); freeLiteral(literal);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(string \"%s\")\n", s); printf("(string \"%s\")\n", s);
} }
#endif
} }
break; break;
@@ -2111,12 +2123,14 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(array, interpreter->literalCache.literals[index]); pushLiteralArray(array, interpreter->literalCache.literals[index]);
} }
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(array "); printf("(array ");
Literal literal = TO_ARRAY_LITERAL(array); Literal literal = TO_ARRAY_LITERAL(array);
printLiteral(literal); printLiteral(literal);
printf(")\n"); printf(")\n");
} }
#endif
//finally, push the array proper //finally, push the array proper
Literal literal = TO_ARRAY_LITERAL(array); Literal literal = TO_ARRAY_LITERAL(array);
@@ -2140,12 +2154,14 @@ static void readInterpreterSections(Interpreter* interpreter) {
setLiteralDictionary(dictionary, interpreter->literalCache.literals[key], interpreter->literalCache.literals[val]); setLiteralDictionary(dictionary, interpreter->literalCache.literals[key], interpreter->literalCache.literals[val]);
} }
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(dictionary "); printf("(dictionary ");
Literal literal = TO_DICTIONARY_LITERAL(dictionary); Literal literal = TO_DICTIONARY_LITERAL(dictionary);
printLiteral(literal); printLiteral(literal);
printf(")\n"); printf(")\n");
} }
#endif
//finally, push the dictionary proper //finally, push the dictionary proper
Literal literal = TO_DICTIONARY_LITERAL(dictionary); Literal literal = TO_DICTIONARY_LITERAL(dictionary);
@@ -2167,9 +2183,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
//push to the literal cache //push to the literal cache
pushLiteralArray(&interpreter->literalCache, literal); pushLiteralArray(&interpreter->literalCache, literal);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(function)\n"); printf("(function)\n");
} }
#endif
} }
break; break;
@@ -2181,9 +2199,11 @@ static void readInterpreterSections(Interpreter* interpreter) {
pushLiteralArray(&interpreter->literalCache, identifier); pushLiteralArray(&interpreter->literalCache, identifier);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(identifier %s (hash: %x))\n", AS_IDENTIFIER(identifier), identifier.as.identifier.hash); printf("(identifier %s (hash: %x))\n", AS_IDENTIFIER(identifier), identifier.as.identifier.hash);
} }
#endif
freeLiteral(identifier); freeLiteral(identifier);
} }
@@ -2199,13 +2219,13 @@ static void readInterpreterSections(Interpreter* interpreter) {
//save the type //save the type
pushLiteralArray(&interpreter->literalCache, typeLiteral); pushLiteralArray(&interpreter->literalCache, typeLiteral);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(type "); printf("(type ");
printLiteral(typeLiteral); printLiteral(typeLiteral);
printf(")\n"); printf(")\n");
} }
#endif
// freeLiteral(typeLiteral);
} }
break; break;
@@ -2234,11 +2254,13 @@ static void readInterpreterSections(Interpreter* interpreter) {
//save the type //save the type
pushLiteralArray(&interpreter->literalCache, typeLiteral); //copied pushLiteralArray(&interpreter->literalCache, typeLiteral); //copied
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("(type "); printf("(type ");
printLiteral(typeLiteral); printLiteral(typeLiteral);
printf(")\n"); printf(")\n");
} }
#endif
freeLiteral(typeLiteral); freeLiteral(typeLiteral);
} }
@@ -2336,11 +2358,13 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt
const char* build = readString(interpreter->bytecode, &interpreter->count); const char* build = readString(interpreter->bytecode, &interpreter->count);
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
if (strncmp(build, TOY_VERSION_BUILD, strlen(TOY_VERSION_BUILD))) { if (strncmp(build, TOY_VERSION_BUILD, strlen(TOY_VERSION_BUILD))) {
printf(WARN "Warning: interpreter/bytecode build mismatch\n" RESET); printf(WARN "Warning: interpreter/bytecode build mismatch\n" RESET);
} }
} }
#endif
consumeByte(interpreter, OP_SECTION_END, interpreter->bytecode, &interpreter->count); consumeByte(interpreter, OP_SECTION_END, interpreter->bytecode, &interpreter->count);
@@ -2348,9 +2372,11 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt
readInterpreterSections(interpreter); readInterpreterSections(interpreter);
//code section //code section
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf(NOTICE "executing bytecode\n" RESET); printf(NOTICE "executing bytecode\n" RESET);
} }
#endif
//execute the interpreter //execute the interpreter
execInterpreter(interpreter); execInterpreter(interpreter);

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common.h"
#include "literal.h" #include "literal.h"
#include "literal_array.h" #include "literal_array.h"
#include "literal_dictionary.h" #include "literal_dictionary.h"
@@ -33,17 +34,17 @@ typedef struct Interpreter {
//native function API //native function API
typedef int (*NativeFn)(Interpreter* interpreter, LiteralArray* arguments); typedef int (*NativeFn)(Interpreter* interpreter, LiteralArray* arguments);
bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func); TOY_API bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func);
//TODO: injectNativeHook //TODO: injectNativeHook
//utilities for the host program //utilities for the host program
bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr); TOY_API bool parseIdentifierToValue(Interpreter* interpreter, Literal* literalPtr);
void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput); TOY_API void setInterpreterPrint(Interpreter* interpreter, PrintFn printOutput);
void setInterpreterAssert(Interpreter* interpreter, PrintFn assertOutput); TOY_API void setInterpreterAssert(Interpreter* interpreter, PrintFn assertOutput);
void setInterpreterError(Interpreter* interpreter, PrintFn errorOutput); TOY_API void setInterpreterError(Interpreter* interpreter, PrintFn errorOutput);
//main access //main access
void initInterpreter(Interpreter* interpreter); //start of program TOY_API void initInterpreter(Interpreter* interpreter); //start of program
void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length); //run the code TOY_API void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length); //run the code
void resetInterpreter(Interpreter* interpreter); //use this to reset the interpreter's environment between runs TOY_API void resetInterpreter(Interpreter* interpreter); //use this to reset the interpreter's environment between runs
void freeInterpreter(Interpreter* interpreter); //end of program TOY_API void freeInterpreter(Interpreter* interpreter); //end of program

View File

@@ -109,10 +109,12 @@ static Token makeErrorToken(Lexer* lexer, char* msg) {
token.length = strlen(msg); token.length = strlen(msg);
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("err:"); printf("err:");
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }
@@ -125,11 +127,13 @@ static Token makeToken(Lexer* lexer, TokenType type) {
token.lexeme = &lexer->source[lexer->current - token.length]; token.lexeme = &lexer->source[lexer->current - token.length];
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
//BUG #10: this shows TOKEN_EOF twice due to the overarching structure of the program - can't be fixed //BUG #10: this shows TOKEN_EOF twice due to the overarching structure of the program - can't be fixed
if (command.verbose) { if (command.verbose) {
printf("tok:"); printf("tok:");
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }
@@ -152,6 +156,7 @@ static Token makeIntegerOrFloat(Lexer* lexer) {
token.length = lexer->current - lexer->start; token.length = lexer->current - lexer->start;
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
if (type == TOKEN_LITERAL_INTEGER) { if (type == TOKEN_LITERAL_INTEGER) {
printf("int:"); printf("int:");
@@ -160,6 +165,7 @@ static Token makeIntegerOrFloat(Lexer* lexer) {
} }
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }
@@ -182,10 +188,12 @@ static Token makeString(Lexer* lexer, char terminator) {
token.length = lexer->current - lexer->start - 2; token.length = lexer->current - lexer->start - 2;
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("str:"); printf("str:");
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }
@@ -207,10 +215,12 @@ static Token makeKeywordOrIdentifier(Lexer* lexer) {
token.length = lexer->current - lexer->start; token.length = lexer->current - lexer->start;
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("kwd:"); printf("kwd:");
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }
@@ -224,10 +234,12 @@ static Token makeKeywordOrIdentifier(Lexer* lexer) {
token.length = lexer->current - lexer->start; token.length = lexer->current - lexer->start;
token.line = lexer->line; token.line = lexer->line;
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
printf("idf:"); printf("idf:");
printToken(&token); printToken(&token);
} }
#endif
return token; return token;
} }

View File

@@ -19,7 +19,7 @@ typedef struct {
int line; int line;
} Token; } Token;
void initLexer(Lexer* lexer, char* source); TOY_API void initLexer(Lexer* lexer, char* source);
Token scanLexer(Lexer* lexer); Token scanLexer(Lexer* lexer);
//for debugging //for debugging

View File

@@ -94,7 +94,7 @@ typedef struct {
#define TO_IDENTIFIER_LITERAL(value, l) _toIdentifierLiteral(value, l) #define TO_IDENTIFIER_LITERAL(value, l) _toIdentifierLiteral(value, l)
#define TO_TYPE_LITERAL(value, c) ((Literal){ LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }}) #define TO_TYPE_LITERAL(value, c) ((Literal){ LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }})
void freeLiteral(Literal literal); TOY_API void freeLiteral(Literal literal);
#define IS_TRUTHY(x) _isTruthy(x) #define IS_TRUTHY(x) _isTruthy(x)
@@ -103,17 +103,16 @@ void freeLiteral(Literal literal);
#define TYPE_PUSH_SUBTYPE(lit, subtype) _typePushSubtype(lit, subtype) #define TYPE_PUSH_SUBTYPE(lit, subtype) _typePushSubtype(lit, subtype)
//BUGFIX: macros are not functions //BUGFIX: macros are not functions
bool _isTruthy(Literal x); TOY_API bool _isTruthy(Literal x);
Literal _toStringLiteral(char* str, int length); TOY_API Literal _toStringLiteral(char* str, int length);
Literal _toIdentifierLiteral(char* str, int length); TOY_API Literal _toIdentifierLiteral(char* str, int length);
Literal* _typePushSubtype(Literal* lit, Literal subtype); TOY_API Literal* _typePushSubtype(Literal* lit, Literal subtype);
//utils //utils
Literal copyLiteral(Literal original); TOY_API Literal copyLiteral(Literal original);
char* copyString(char* original, int length); TOY_API char* copyString(char* original, int length);
bool literalsAreEqual(Literal lhs, Literal rhs); TOY_API bool literalsAreEqual(Literal lhs, Literal rhs);
int hashLiteral(Literal lit); TOY_API int hashLiteral(Literal lit);
void printLiteral(Literal literal);
void printLiteralCustom(Literal literal, void (printFn)(const char*));
TOY_API void printLiteral(Literal literal);
TOY_API void printLiteralCustom(Literal literal, void (printFn)(const char*));

View File

@@ -5,13 +5,24 @@ CFLAGS +=$(addprefix -I,$(IDIR)) -g -Wall -W -pedantic -Wno-unused-parameter -Wn
LIBS += LIBS +=
ODIR = obj ODIR = obj
SRC = $(wildcard *.c) SRC = $(filter-out $(wildcard *main.c),$(wildcard *.c))
OBJ = $(addprefix $(ODIR)/,$(SRC:.c=.o)) OBJ = $(addprefix $(ODIR)/,$(SRC:.c=.o))
OUT = ../$(OUTDIR)/toy OUTNAME = toy
OUT = ../$(OUTDIR)/$(OUTNAME).dll
LIBLINE =-Wl,--out-implib=../$(OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive
all: $(OBJ) REPLSRC = $(wildcard repl_main.c)
$(CC) -o $(OUT) $^ $(CFLAGS) $(LIBS) REPLOUT = $(OUTNAME)repl.exe
all: library $(addprefix $(ODIR)/,$(REPLSRC:.c=.o))
$(CC) -DTOY_IMPORT $(CFLAGS) -o ../$(OUTDIR)/$(REPLOUT) $(addprefix $(ODIR)/,$(REPLSRC:.c=.o)) $(LIBS) -L$(realpath $(shell pwd)/../$(OUTDIR)) -l$(OUTNAME)
library: $(OBJ)
$(CC) -DTOY_EXPORT $(CFLAGS) -shared -o $(OUT) $(LIBLINE)
static: $(OBJ) $(addprefix $(ODIR)/,$(REPLSRC:.c=.o))
$(CC) $(CFLAGS) -o ../$(OUTDIR)/$(REPLOUT) $(addprefix $(ODIR)/,$(REPLSRC:.c=.o)) $(OBJ) $(LIBS)
$(OBJ): | $(ODIR) $(OBJ): | $(ODIR)

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common.h"
#include "literal.h" #include "literal.h"
#include "opcodes.h" #include "opcodes.h"
#include "token_types.h" #include "token_types.h"
@@ -153,7 +154,8 @@ union _node {
NodeIndex index; NodeIndex index;
}; };
void freeNode(Node* node); TOY_API void freeNode(Node* node);
void emitNodeLiteral(Node** nodeHandle, Literal literal); void emitNodeLiteral(Node** nodeHandle, Literal literal);
void emitNodeUnary(Node** nodeHandle, Opcode opcode, Node* child); void emitNodeUnary(Node** nodeHandle, Opcode opcode, Node* child);
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode); //handled node becomes lhs void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode); //handled node becomes lhs

View File

@@ -59,9 +59,11 @@ static void consume(Parser* parser, TokenType tokenType, const char* msg) {
} }
static void synchronize(Parser* parser) { static void synchronize(Parser* parser) {
#ifndef TOY_EXPORT
if (command.verbose) { if (command.verbose) {
fprintf(stderr, ERROR "synchronizing\n" RESET); fprintf(stderr, ERROR "synchronizing\n" RESET);
} }
#endif
while (parser->current.type != TOKEN_EOF) { while (parser->current.type != TOKEN_EOF) {
switch(parser->current.type) { switch(parser->current.type) {

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include "parser.h" #include "common.h"
#include "lexer.h" #include "lexer.h"
#include "node.h" #include "node.h"
@@ -16,6 +15,6 @@ typedef struct {
Token previous; Token previous;
} Parser; } Parser;
void initParser(Parser* parser, Lexer* lexer); TOY_API void initParser(Parser* parser, Lexer* lexer);
void freeParser(Parser* parser); TOY_API void freeParser(Parser* parser);
Node* scanParser(Parser* parser); TOY_API Node* scanParser(Parser* parser);

View File

@@ -5,8 +5,6 @@
#include "compiler.h" #include "compiler.h"
#include "interpreter.h" #include "interpreter.h"
#include "memory.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>