Arrays and dictionaries have been implemented, read more

The arrays and dictionaries are currently being printed out correctly,
afaik. This means I should be able to go back and work on the type
system, assuming nothing happens.
This commit is contained in:
2022-08-10 17:42:04 +01:00
parent 6a883bde96
commit 67f7b3e436
13 changed files with 819 additions and 36 deletions

View File

@@ -23,14 +23,17 @@ print 2 + (3 * 3);
}
print "Back to the outer scope.";
//test asserts
assert true, "This won't be seen";
assert false, "This is an error";
print [1, 2, 3];
print [4, 5];
print ["key":"value"];
//var arr : [int] = [1, 2, 3, 42];
//var dict : [string, int] = ["hello": 1, "world":2];
//test asserts at the end of the file
assert true, "This won't be seen";
assert false, "This is a failed assert, and will end execution";

337
scripts/long-array.toy Normal file
View File

@@ -0,0 +1,337 @@
print [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
//-------------------------
"100",
"101",
"102",
"103",
"104",
"105",
"106",
"107",
"108",
"109",
"110",
"111",
"112",
"113",
"114",
"115",
"116",
"117",
"118",
"119",
"120",
"121",
"122",
"123",
"124",
"125",
"126",
"127",
"128",
"129",
"130",
"131",
"132",
"133",
"134",
"135",
"136",
"137",
"138",
"139",
"140",
"141",
"142",
"143",
"144",
"145",
"146",
"147",
"148",
"149",
"150",
"151",
"152",
"153",
"154",
"155",
"156",
"157",
"158",
"159",
"160",
"161",
"162",
"163",
"164",
"165",
"166",
"167",
"168",
"169",
"170",
"171",
"172",
"173",
"174",
"175",
"176",
"177",
"178",
"179",
"180",
"181",
"182",
"183",
"184",
"185",
"186",
"187",
"188",
"189",
"190",
"191",
"192",
"193",
"194",
"195",
"196",
"197",
"198",
"199",
//-------------------------
"200",
"201",
"202",
"203",
"204",
"205",
"206",
"207",
"208",
"209",
"210",
"211",
"212",
"213",
"214",
"215",
"216",
"217",
"218",
"219",
"220",
"221",
"222",
"223",
"224",
"225",
"226",
"227",
"228",
"229",
"230",
"231",
"232",
"233",
"234",
"235",
"236",
"237",
"238",
"239",
"240",
"241",
"242",
"243",
"244",
"245",
"246",
"247",
"248",
"249",
"250",
"251",
"252",
"253",
"254",
"255",
"256",
"257",
"258",
"259",
"260",
"261",
"262",
"263",
"264",
"265",
"266",
"267",
"268",
"269",
"270",
"271",
"272",
"273",
"274",
"275",
"276",
"277",
"278",
"279",
"280",
"281",
"282",
"283",
"284",
"285",
"286",
"287",
"288",
"289",
"290",
"291",
"292",
"293",
"294",
"295",
"296",
"297",
"298",
"299"
];

View File

@@ -0,0 +1,2 @@
//NOTE: dictionaries are NOT stored in order
print ["0":"0","1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8","9":"9","10":"10","11":"11","12":"12","13":"13","14":"14","15":"15","16":"16","17":"17","18":"18","19":"19","20":"20","21":"21","22":"22","23":"23","24":"24","25":"25","26":"26","27":"27","28":"28","29":"29","30":"30","31":"31","32":"32","33":"33","34":"34","35":"35","36":"36","37":"37","38":"38","39":"39","40":"40","41":"41","42":"42","43":"43","44":"44","45":"45","46":"46","47":"47","48":"48","49":"49","50":"50","51":"51","52":"52","53":"53","54":"54","55":"55","56":"56","57":"57","58":"58","59":"59","60":"60","61":"61","62":"62","63":"63","64":"64","65":"65","66":"66","67":"67","68":"68","69":"69","70":"70","71":"71","72":"72","73":"73","74":"74","75":"75","76":"76","77":"77","78":"78","79":"79","80":"80","81":"81","82":"82","83":"83","84":"84","85":"85","86":"86","87":"87","88":"88","89":"89","90":"90","91":"91","92":"92","93":"93","94":"94","95":"95","96":"96","97":"97","98":"98","99":"99","100":"100","101":"101","102":"102","103":"103","104":"104","105":"105","106":"106","107":"107","108":"108","109":"109","110":"110","111":"111","112":"112","113":"113","114":"114","115":"115","116":"116","117":"117","118":"118","119":"119","120":"120","121":"121","122":"122","123":"123","124":"124","125":"125","126":"126","127":"127","128":"128","129":"129","130":"130","131":"131","132":"132","133":"133","134":"134","135":"135","136":"136","137":"137","138":"138","139":"139","140":"140","141":"141","142":"142","143":"143","144":"144","145":"145","146":"146","147":"147","148":"148","149":"149","150":"150","151":"151","152":"152","153":"153","154":"154","155":"155","156":"156","157":"157","158":"158","159":"159","160":"160","161":"161","162":"162","163":"163","164":"164","165":"165","166":"166","167":"167","168":"168","169":"169","170":"170","171":"171","172":"172","173":"173","174":"174","175":"175","176":"176","177":"177","178":"178","179":"179","180":"180","181":"181","182":"182","183":"183","184":"184","185":"185","186":"186","187":"187","188":"188","189":"189","190":"190","191":"191","192":"192","193":"193","194":"194","195":"195","196":"196","197":"197","198":"198","199":"199","200":"200","201":"201","202":"202","203":"203","204":"204","205":"205","206":"206","207":"207","208":"208","209":"209","210":"210","211":"211","212":"212","213":"213","214":"214","215":"215","216":"216","217":"217","218":"218","219":"219","220":"220","221":"221","222":"222","223":"223","224":"224","225":"225","226":"226","227":"227","228":"228","229":"229","230":"230","231":"231","232":"232","233":"233","234":"234","235":"235","236":"236","237":"237","238":"238","239":"239","240":"240","241":"241","242":"242","243":"243","244":"244","245":"245","246":"246","247":"247","248":"248","249":"249","250":"250","251":"251","252":"252","253":"253","254":"254","255":"255","256":"256","257":"257","258":"258","259":"259","260":"260","261":"261","262":"262","263":"263","264":"264","265":"265","266":"266","267":"267","268":"268","269":"269","270":"270","271":"271","272":"272","273":"273","274":"274","275":"275","276":"276","277":"277","278":"278","279":"279","280":"280","281":"281","282":"282","283":"283","284":"284","285":"285","286":"286","287":"287","288":"288","289":"289","290":"290","291":"291","292":"292","293":"293","294":"294","295":"295","296":"296","297":"297","298":"298","299":"299"];

2
scripts/small.toy Normal file
View File

@@ -0,0 +1,2 @@
print ["foo", "bar"];
print ["foo":1, "bar":2];

View File

@@ -2,6 +2,10 @@
#include "memory.h"
#include "literal.h"
#include "literal_array.h"
#include "literal_dictionary.h"
#include <stdio.h>
void initCompiler(Compiler* compiler) {
@@ -90,6 +94,72 @@ void writeCompiler(Compiler* compiler, Node* node) {
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_END; //1 byte
break;
case NODE_COMPOUND: {
int index = -1;
//for both, stored as an array
LiteralArray* store = ALLOCATE(LiteralArray, 1);
initLiteralArray(store);
//emit an array or a dictionary definition
if (node->compound.nodes->type == NODE_PAIR) {
//ensure each literal key and value are in the cache, individually
for (int i = 0; i < node->compound.count; i++) {
//keys
int key = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
if (key < 0) {
key = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
}
//values
int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
if (val < 0) {
val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
}
pushLiteralArray(store, TO_INTEGER_LITERAL(key));
pushLiteralArray(store, TO_INTEGER_LITERAL(val));
}
//push the store to the cache, with instructions about how pack it
index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store));
}
else {
//ensure each literal value is in the cache, individually
for (int i = 0; i < node->compound.count; i++) {
//values
int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
if (val < 0) {
val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
}
pushLiteralArray(store, TO_INTEGER_LITERAL(val));
}
//push the store to the cache, with instructions about how pack it
index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store));
}
//push the node opcode to the bytecode
if (index >= 256) {
//push a "long" index
compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)index; //2 bytes
compiler->count += sizeof(unsigned short);
}
else {
//push the index
compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte
compiler->bytecode[compiler->count++] = (unsigned char)index; //1 byte
}
}
break;
case NODE_PAIR:
fprintf(stderr, "[Internal] NODE_PAIR encountered in writeCompiler()");
break;
case NODE_VAR_TYPES:
//TODO: OP_TYPE_DECL
break;
@@ -221,6 +291,39 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) {
}
break;
case LITERAL_ARRAY: {
emitByte(&collation, &capacity, &count, LITERAL_ARRAY);
LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]);
//length of the array, as a short
emitShort(&collation, &capacity, &count, ptr->count);
//each element of the array
for (int i = 0; i < ptr->count; i++) {
emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values
}
freeLiteralArray(ptr);
}
break;
case LITERAL_DICTIONARY:
emitByte(&collation, &capacity, &count, LITERAL_DICTIONARY);
LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above
//length of the array, as a short
emitShort(&collation, &capacity, &count, ptr->count); //count is the array size, NOT the dictionary size
//each element of the array
for (int i = 0; i < ptr->count; i++) {
emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values
}
freeLiteralArray(ptr);
break;
default:
fprintf(stderr, "[Internal] Unknown literal type encountered within literal cache\n");
return NULL;

View File

@@ -306,6 +306,11 @@ static void execInterpreter(Interpreter* interpreter) {
}
void runInterpreter(Interpreter* interpreter) {
if (!interpreter->bytecode) {
printf(ERROR "Error: No valid bytecode given\n" RESET);
return;
}
//header section
const unsigned char major = readByte(interpreter->bytecode, &interpreter->count);
const unsigned char minor = readByte(interpreter->bytecode, &interpreter->count);
@@ -385,6 +390,53 @@ void runInterpreter(Interpreter* interpreter) {
}
}
break;
case LITERAL_ARRAY: {
LiteralArray* array = ALLOCATE(LiteralArray, 1);
initLiteralArray(array);
unsigned short length = readShort(interpreter->bytecode, &interpreter->count);
//read each index, then unpack the value from the existing literal cache
for (int i = 0; i < length; i++) {
int index = readShort(interpreter->bytecode, &interpreter->count);
pushLiteralArray(array, interpreter->literalCache.literals[index]);
}
if (command.verbose) {
printf("(array ");
printLiteral(TO_ARRAY_LITERAL(array));
printf(")\n");
}
//finally, push the array proper
pushLiteralArray(&interpreter->literalCache, TO_ARRAY_LITERAL(array));
}
break;
case LITERAL_DICTIONARY: {
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
initLiteralDictionary(dictionary);
unsigned short length = readShort(interpreter->bytecode, &interpreter->count);
//read each index, then unpack the value from the existing literal cache
for (int i = 0; i < length / 2; i++) {
int key = readShort(interpreter->bytecode, &interpreter->count);
int val = readShort(interpreter->bytecode, &interpreter->count);
setLiteralDictionary(dictionary, interpreter->literalCache.literals[key], interpreter->literalCache.literals[val]);
}
if (command.verbose) {
printf("(dictionary ");
printLiteral(TO_DICTIONARY_LITERAL(dictionary));
printf(")\n");
}
//finally, push the dictionary proper
pushLiteralArray(&interpreter->literalCache, TO_DICTIONARY_LITERAL(dictionary));
}
break;
}
}

View File

@@ -69,6 +69,7 @@ static void eatWhitespace(Lexer* lexer) {
advance(lexer);
break;
}
break;
default:
return;

View File

@@ -1,13 +1,35 @@
#include "literal.h"
#include "memory.h"
#include "literal_array.h"
#include "literal_dictionary.h"
#include <stdio.h>
#include <string.h>
//utils
static void stdoutWrapper(const char* output) {
fprintf(stdout, output);
}
//buffer the prints
static char* globalPrintBuffer = NULL;
static size_t globalPrintCapacity = 0;
static size_t globalPrintCount = 0;
static void printToBuffer(const char* str) {
while (strlen(str) + globalPrintCount > globalPrintCapacity) {
int oldCapacity = globalPrintCapacity;
globalPrintCapacity = GROW_CAPACITY(globalPrintCapacity);
globalPrintBuffer = GROW_ARRAY(char, globalPrintBuffer, oldCapacity, globalPrintCapacity);
}
snprintf(globalPrintBuffer + globalPrintCount, strlen(str) + 1, "%s", str);
globalPrintCount += strlen(str);
}
//exposed functions
void printLiteral(Literal literal) {
printLiteralCustom(literal, stdoutWrapper);
}
@@ -37,12 +59,93 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
break;
case LITERAL_STRING: {
char buffer[256];
snprintf(buffer, 256, "%.*s", STRLEN(literal), AS_STRING(literal));
char buffer[4096];
snprintf(buffer, 4096, "\"%.*s\"", STRLEN(literal), AS_STRING(literal));
printFn(buffer);
}
break;
case LITERAL_ARRAY: {
LiteralArray* ptr = AS_ARRAY(literal);
//hold potential parent-call buffers
char* cacheBuffer = globalPrintBuffer;
globalPrintBuffer = NULL;
int cacheCapacity = globalPrintCapacity;
globalPrintCapacity = 0;
int cacheCount = globalPrintCount;
globalPrintCount = 0;
//print the contents to the global buffer
printToBuffer("[");
for (int i = 0; i < ptr->count; i++) {
printLiteralCustom(ptr->literals[i], printToBuffer);
if (i + 1 < ptr->count) {
printToBuffer(",");
}
}
printToBuffer("]");
//swap the parent-call buffer back into place
char* printBuffer = globalPrintBuffer;
int printCapacity = globalPrintCapacity;
int printCount = globalPrintCount;
globalPrintBuffer = cacheBuffer;
globalPrintCapacity = cacheCapacity;
globalPrintCount = cacheCount;
//finally, output and cleanup
printFn(printBuffer);
FREE_ARRAY(char, printBuffer, printCapacity);
}
break;
case LITERAL_DICTIONARY: {
LiteralDictionary* ptr = AS_DICTIONARY(literal);
//hold potential parent-call buffers
char* cacheBuffer = globalPrintBuffer;
globalPrintBuffer = NULL;
int cacheCapacity = globalPrintCapacity;
globalPrintCapacity = 0;
int cacheCount = globalPrintCount;
globalPrintCount = 0;
//print the contents to the global buffer
int delimCount = 0;
printToBuffer("[");
for (int i = 0; i < ptr->capacity; i++) {
if (ptr->entries[i].key.type == LITERAL_NULL) {
continue;
}
if (delimCount++ > 0) {
printToBuffer(",");
}
printLiteralCustom(ptr->entries[i].key, printToBuffer);
printToBuffer(":");
printLiteralCustom(ptr->entries[i].value, printToBuffer);
}
printToBuffer("]");
//swap the parent-call buffer back into place
char* printBuffer = globalPrintBuffer;
int printCapacity = globalPrintCapacity;
int printCount = globalPrintCount;
globalPrintBuffer = cacheBuffer;
globalPrintCapacity = cacheCapacity;
globalPrintCount = cacheCount;
//finally, output and cleanup
printFn(printBuffer);
FREE_ARRAY(char, printBuffer, printCapacity);
}
break;
case LITERAL_IDENTIFIER: {
char buffer[256];
snprintf(buffer, 256, "%.*s", STRLEN_I(literal), AS_IDENTIFIER(literal));

View File

@@ -10,10 +10,11 @@ typedef enum {
LITERAL_INTEGER,
LITERAL_FLOAT,
LITERAL_STRING,
// LITERAL_ARRAY,
// LITERAL_DICTIONARY,
LITERAL_ARRAY,
LITERAL_DICTIONARY,
// LITERAL_FUNCTION,
LITERAL_IDENTIFIER,
// LITERAL_TYPE,
} LiteralType;
typedef struct {
@@ -27,15 +28,17 @@ typedef struct {
int length;
} string;
// //experimental
// void* array;
// void* dictionary;
void* array;
void* dictionary;
// void* function;
struct { //for variable names
char* ptr;
int length;
} identifier;
//TODO: type
} as;
} Literal;
@@ -53,8 +56,8 @@ typedef struct {
#define AS_INTEGER(value) ((value).as.integer)
#define AS_FLOAT(value) ((value).as.number)
#define AS_STRING(value) ((value).as.string.ptr)
// #define AS_ARRAY(value)
// #define AS_DICTIONARY(value)
#define AS_ARRAY(value) ((value).as.array)
#define AS_DICTIONARY(value) ((value).as.dictionary)
// #define AS_FUNCTION(value)
#define AS_IDENTIFIER(value) ((value).as.identifier.ptr)
@@ -63,8 +66,8 @@ typedef struct {
#define TO_INTEGER_LITERAL(value) ((Literal){LITERAL_INTEGER, { .integer = value }})
#define TO_FLOAT_LITERAL(value) ((Literal){LITERAL_FLOAT, { .number = value }})
#define TO_STRING_LITERAL(value) _toStringLiteral(value)
// #define TO_ARRAY_LITERAL
// #define TO_DICTIONARY_LITERAL
#define TO_ARRAY_LITERAL(value) ((Literal){LITERAL_ARRAY, { .array = value }})
#define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }})
// #define TO_FUNCTION_LITERAL
#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value)

View File

@@ -37,14 +37,26 @@ void freeNode(Node* node) {
for (int i = 0; i < node->block.count; i++) {
freeNode(node->block.nodes + i);
}
//each sub-node gets freed individually
FREE_ARRAY(Node, node->block.nodes, node->block.capacity);
break;
case NODE_COMPOUND:
for (int i = 0; i < node->compound.count; i++) {
freeNode(node->compound.nodes + i);
}
FREE_ARRAY(Node, node->compound.nodes, node->compound.capacity);
break;
case NODE_PAIR:
freeNode(node->pair.left);
freeNode(node->pair.right);
break;
case NODE_VAR_TYPES:
for (int i = 0; i < node->varTypes.count; i++) {
freeNode(node->varTypes.nodes + 1);
}
//each sub-node gets freed individually
FREE_ARRAY(Node, node->varTypes.nodes, node->varTypes.capacity);
break;
case NODE_VAR_DECL:
@@ -53,8 +65,6 @@ void freeNode(Node* node) {
freeNode(node->varDecl.expression);
break;
}
FREE(Node, node);
}
void emitNodeLiteral(Node** nodeHandle, Literal literal) {
@@ -105,6 +115,27 @@ void emitNodeBlock(Node** nodeHandle) {
*nodeHandle = tmp;
}
void emitNodeCompound(Node** nodeHandle) {
Node* tmp = ALLOCATE(Node, 1);
tmp->type = NODE_COMPOUND;
tmp->compound.nodes = NULL;
tmp->compound.capacity = 0;
tmp->compound.count = 0;
*nodeHandle = tmp;
}
void emitNodePair(Node** nodeHandle, Node* left, Node* right) {
Node* tmp = ALLOCATE(Node, 1);
tmp->type = NODE_PAIR;
tmp->pair.left = left;
tmp->pair.right = right;
*nodeHandle = tmp;
}
void emitNodeVarTypes(Node** nodeHandle, unsigned char mask) {
Node* tmp = ALLOCATE(Node, 1);
@@ -172,8 +203,26 @@ void printNode(Node* node) {
printf("}\n");
break;
case NODE_COMPOUND:
printf("compound[\n");
for (int i = 0; i < node->compound.count; i++) {
printNode(&(node->compound.nodes[i]));
}
printf("]\n");
break;
case NODE_PAIR:
printf("pair-left:");
printNode(node->pair.left);
printf(";pair-right:");
printNode(node->pair.right);
printf(";");
break;
case NODE_VAR_TYPES:
printf("[\n");
printf("type[\n");
for (int i = 0; i < node->varTypes.count; i++) {
printNode(&(node->varTypes.nodes[i]));

View File

@@ -9,10 +9,12 @@ typedef union _node Node;
typedef enum NodeType {
NODE_ERROR,
NODE_LITERAL, //a simple value
NODE_UNARY, //one child
NODE_BINARY, //two children, left and right
NODE_UNARY, //one child + opcode
NODE_BINARY, //two children, left and right + opcode
NODE_GROUPING, //one child
NODE_BLOCK, //contains sub-node array
NODE_BLOCK, //contains a sub-node array
NODE_COMPOUND, //contains a sub-node array
NODE_PAIR, //contains a left and right
NODE_VAR_TYPES, //contains a type mask and a sub-node array for compound types
NODE_VAR_DECL, //contains identifier literal, typenode, expression definition
// NODE_CONDITIONAL, //three children: conditional, then path, else path
@@ -48,6 +50,19 @@ typedef struct NodeBlock {
int count;
} NodeBlock;
typedef struct NodeCompound {
NodeType type;
Node* nodes;
int capacity;
int count;
} NodeCompound;
typedef struct NodePair {
NodeType type;
Node* left;
Node* right;
} NodePair;
typedef struct NodeVarTypes {
NodeType type;
unsigned char mask;
@@ -70,6 +85,8 @@ union _node {
NodeBinary binary;
NodeGrouping grouping;
NodeBlock block;
NodeCompound compound;
NodePair pair;
NodeVarTypes varTypes;
NodeVarDecl varDecl;
};
@@ -80,6 +97,8 @@ void emitNodeUnary(Node** nodeHandle, Opcode opcode);
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode);
void emitNodeGrouping(Node** nodeHandle);
void emitNodeBlock(Node** nodeHandle);
void emitNodeCompound(Node** nodeHandle);
void emitNodePair(Node** nodeHandle, Node* left, Node* right);
void emitNodeVarTypes(Node** nodeHandle, unsigned char mask);
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Node* varType, Node* expression);

View File

@@ -36,6 +36,7 @@ static void advance(Parser* parser) {
if (parser->current.type == TOKEN_ERROR) {
error(parser, parser->current, "Lexer error");
printf(parser->lexer->source);
}
}
@@ -115,6 +116,106 @@ static void declaration(Parser* parser, Node** nodeHandle);
static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule rule);
//the expression rules
static Opcode compound(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
//read either an array or a dictionary into a literal node
int iterations = 0; //count the number of entries iterated over
//compound nodes to store what is read
Node* array = NULL;
Node* dictionary = NULL;
while (!match(parser, TOKEN_BRACKET_RIGHT)) {
//if empty dictionary, there will be a colon between the brackets
if (iterations == 0 && match(parser, TOKEN_COLON)) {
consume(parser, TOKEN_BRACE_RIGHT, "Expected ']' at the end of empty dictionary definition");
break;
}
if (iterations > 0) {
consume(parser, TOKEN_COMMA, "Expected ',' in array or dictionary");
}
iterations++;
Node* left = NULL;
Node* right = NULL;
//store the left
parsePrecedence(parser, &left, PREC_PRIMARY);
//detect a dictionary
if (match(parser, TOKEN_COLON)) {
parsePrecedence(parser, &right, PREC_PRIMARY);
//check we ARE defining a dictionary
if (array) {
error(parser, parser->previous, "Incorrect detection between array and dictionary");
freeNode(array);
return OP_EOF;
}
//init the dictionary
if (!dictionary) {
emitNodeCompound(&dictionary);
}
//grow the node if needed
if (dictionary->compound.capacity < dictionary->compound.count + 1) {
int oldCapacity = dictionary->compound.capacity;
dictionary->compound.capacity = GROW_CAPACITY(oldCapacity);
dictionary->compound.nodes = GROW_ARRAY(Node, dictionary->compound.nodes, oldCapacity, dictionary->compound.capacity);
}
//store the left and right in the node
Node* pair = NULL;
emitNodePair(&pair, left, right);
dictionary->compound.nodes[dictionary->compound.count++] = *pair;
}
//detect an array
else {
//check we ARE defining an array
if (dictionary) {
error(parser, parser->current, "Incorrect detection between array and dictionary");
freeNode(dictionary);
return OP_EOF;
}
//init the array
if (!array) {
emitNodeCompound(&array);
}
//grow the node if needed
if (array->compound.capacity < array->compound.count + 1) {
int oldCapacity = array->compound.capacity;
array->compound.capacity = GROW_CAPACITY(oldCapacity);
array->compound.nodes = GROW_ARRAY(Node, array->compound.nodes, oldCapacity, array->compound.capacity);
}
//store the left in the array
array->compound.nodes[array->compound.count++] = *left;
}
}
//save the result
if (array) {
(*nodeHandle) = array;
}
else if (dictionary) {
(*nodeHandle) = dictionary;
}
else {
error(parser, parser->current, "[internal] Couldn't determine if should save an array or dictionary");
}
//ignored
return OP_EOF;
}
static Opcode string(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
//handle strings
switch(parser->previous.type) {
@@ -330,7 +431,7 @@ ParseRule parseRules[] = { //must match the token types
//logical operators
{grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT,
{NULL, NULL, PREC_NONE},// TOKEN_PAREN_RIGHT,
{NULL, NULL, PREC_NONE},// TOKEN_BRACKET_LEFT,
{compound, NULL, PREC_CALL},// TOKEN_BRACKET_LEFT,
{NULL, NULL, PREC_NONE},// TOKEN_BRACKET_RIGHT,
{NULL, NULL, PREC_NONE},// TOKEN_BRACE_LEFT,
{NULL, NULL, PREC_NONE},// TOKEN_BRACE_RIGHT,
@@ -348,7 +449,7 @@ ParseRule parseRules[] = { //must match the token types
{NULL, NULL, PREC_NONE},// TOKEN_ASSIGN,
{NULL, NULL, PREC_NONE},// TOKEN_COLON,
{NULL, NULL, PREC_NONE},// TOKEN_SEMICOLON,
{NULL, NULL, PREC_NONE},// TOKEN_COMMA,
{NULL, NULL, PREC_CALL},// TOKEN_COMMA,
{NULL, NULL, PREC_NONE},// TOKEN_DOT,
{NULL, NULL, PREC_NONE},// TOKEN_PIPE,
{NULL, NULL, PREC_NONE},// TOKEN_REST,
@@ -570,9 +671,9 @@ static void assertStmt(Parser* parser, Node* node) {
node->type = NODE_BINARY;
node->unary.opcode = OP_ASSERT;
expression(parser, &(node->binary.left));
parsePrecedence(parser, &(node->binary.left), PREC_PRIMARY);
consume(parser, TOKEN_COMMA, "Expected ',' in assert statement");
expression(parser, &(node->binary.right));
parsePrecedence(parser, &(node->binary.right), PREC_PRIMARY);
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of assert statement");
}
@@ -607,7 +708,7 @@ static void statement(Parser* parser, Node* node) {
//declarations and definitions
static void readVarType(Parser* parser, Node** nodeHandle) {
//TODO: compound types with the "type" keyword
//TODO: custom types with the "type" keyword
advance(parser);
unsigned char typeMask = 0;

View File

@@ -25,7 +25,7 @@ char* readFile(char* path, size_t* fileSize) {
*fileSize = ftell(file);
rewind(file);
char* buffer = (char*)malloc(*fileSize);
char* buffer = (char*)malloc(*fileSize + 1);
if (buffer == NULL) {
fprintf(stderr, "Not enough memory to read \"%s\"\n", path);
@@ -34,6 +34,8 @@ char* readFile(char* path, size_t* fileSize) {
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this
if (bytesRead < *fileSize) {
fprintf(stderr, "Could not read file \"%s\"\n", path);
exit(-1);
@@ -109,13 +111,19 @@ void runBinary(unsigned char* tb, size_t size) {
void runBinaryFile(char* fname) {
size_t size = 0; //not used
unsigned char* tb = (unsigned char*)readFile(fname, &size);
if (!tb) {
return;
}
runBinary(tb, size);
//interpreter takes ownership of the binary data
}
void runSource(char* source) {
size_t size;
size_t size = 0;
unsigned char* tb = compileString(source, &size);
if (!tb) {
return;
}
runBinary(tb, size);
}
@@ -169,11 +177,11 @@ void repl() {
int size = 0;
unsigned char* tb = collateCompiler(&compiler, &size);
// for (int i = 0; i < size; i++) {
// printf("%d ", tb[i]);
// }
for (int i = 0; i < size; i++) {
printf("%d ", tb[i]);
}
// printf("\n");
printf("\n");
//run the bytecode
initInterpreter(&interpreter, tb, size);