mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
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:
@@ -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
337
scripts/long-array.toy
Normal 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"
|
||||
|
||||
];
|
||||
2
scripts/long-dictionary.toy
Normal file
2
scripts/long-dictionary.toy
Normal 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
2
scripts/small.toy
Normal file
@@ -0,0 +1,2 @@
|
||||
print ["foo", "bar"];
|
||||
print ["foo":1, "bar":2];
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ static void eatWhitespace(Lexer* lexer) {
|
||||
advance(lexer);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
||||
107
source/literal.c
107
source/literal.c
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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]));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
111
source/parser.c
111
source/parser.c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user