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.";
|
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 arr : [int] = [1, 2, 3, 42];
|
||||||
//var dict : [string, int] = ["hello": 1, "world":2];
|
//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 "memory.h"
|
||||||
|
|
||||||
|
#include "literal.h"
|
||||||
|
#include "literal_array.h"
|
||||||
|
#include "literal_dictionary.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void initCompiler(Compiler* compiler) {
|
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
|
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_END; //1 byte
|
||||||
break;
|
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:
|
case NODE_VAR_TYPES:
|
||||||
//TODO: OP_TYPE_DECL
|
//TODO: OP_TYPE_DECL
|
||||||
break;
|
break;
|
||||||
@@ -221,6 +291,39 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) {
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
fprintf(stderr, "[Internal] Unknown literal type encountered within literal cache\n");
|
fprintf(stderr, "[Internal] Unknown literal type encountered within literal cache\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -306,6 +306,11 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void runInterpreter(Interpreter* interpreter) {
|
void runInterpreter(Interpreter* interpreter) {
|
||||||
|
if (!interpreter->bytecode) {
|
||||||
|
printf(ERROR "Error: No valid bytecode given\n" RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//header section
|
//header section
|
||||||
const unsigned char major = readByte(interpreter->bytecode, &interpreter->count);
|
const unsigned char major = readByte(interpreter->bytecode, &interpreter->count);
|
||||||
const unsigned char minor = readByte(interpreter->bytecode, &interpreter->count);
|
const unsigned char minor = readByte(interpreter->bytecode, &interpreter->count);
|
||||||
@@ -385,6 +390,53 @@ void runInterpreter(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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);
|
advance(lexer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|||||||
107
source/literal.c
107
source/literal.c
@@ -1,13 +1,35 @@
|
|||||||
#include "literal.h"
|
#include "literal.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "literal_array.h"
|
||||||
|
#include "literal_dictionary.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//utils
|
||||||
static void stdoutWrapper(const char* output) {
|
static void stdoutWrapper(const char* output) {
|
||||||
fprintf(stdout, 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) {
|
void printLiteral(Literal literal) {
|
||||||
printLiteralCustom(literal, stdoutWrapper);
|
printLiteralCustom(literal, stdoutWrapper);
|
||||||
}
|
}
|
||||||
@@ -37,12 +59,93 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LITERAL_STRING: {
|
case LITERAL_STRING: {
|
||||||
char buffer[256];
|
char buffer[4096];
|
||||||
snprintf(buffer, 256, "%.*s", STRLEN(literal), AS_STRING(literal));
|
snprintf(buffer, 4096, "\"%.*s\"", STRLEN(literal), AS_STRING(literal));
|
||||||
printFn(buffer);
|
printFn(buffer);
|
||||||
}
|
}
|
||||||
break;
|
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: {
|
case LITERAL_IDENTIFIER: {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
snprintf(buffer, 256, "%.*s", STRLEN_I(literal), AS_IDENTIFIER(literal));
|
snprintf(buffer, 256, "%.*s", STRLEN_I(literal), AS_IDENTIFIER(literal));
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ typedef enum {
|
|||||||
LITERAL_INTEGER,
|
LITERAL_INTEGER,
|
||||||
LITERAL_FLOAT,
|
LITERAL_FLOAT,
|
||||||
LITERAL_STRING,
|
LITERAL_STRING,
|
||||||
// LITERAL_ARRAY,
|
LITERAL_ARRAY,
|
||||||
// LITERAL_DICTIONARY,
|
LITERAL_DICTIONARY,
|
||||||
// LITERAL_FUNCTION,
|
// LITERAL_FUNCTION,
|
||||||
LITERAL_IDENTIFIER,
|
LITERAL_IDENTIFIER,
|
||||||
|
// LITERAL_TYPE,
|
||||||
} LiteralType;
|
} LiteralType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -27,15 +28,17 @@ typedef struct {
|
|||||||
int length;
|
int length;
|
||||||
} string;
|
} string;
|
||||||
|
|
||||||
// //experimental
|
void* array;
|
||||||
// void* array;
|
void* dictionary;
|
||||||
// void* dictionary;
|
|
||||||
// void* function;
|
// void* function;
|
||||||
|
|
||||||
struct { //for variable names
|
struct { //for variable names
|
||||||
char* ptr;
|
char* ptr;
|
||||||
int length;
|
int length;
|
||||||
} identifier;
|
} identifier;
|
||||||
|
|
||||||
|
//TODO: type
|
||||||
} as;
|
} as;
|
||||||
} Literal;
|
} Literal;
|
||||||
|
|
||||||
@@ -53,8 +56,8 @@ typedef struct {
|
|||||||
#define AS_INTEGER(value) ((value).as.integer)
|
#define AS_INTEGER(value) ((value).as.integer)
|
||||||
#define AS_FLOAT(value) ((value).as.number)
|
#define AS_FLOAT(value) ((value).as.number)
|
||||||
#define AS_STRING(value) ((value).as.string.ptr)
|
#define AS_STRING(value) ((value).as.string.ptr)
|
||||||
// #define AS_ARRAY(value)
|
#define AS_ARRAY(value) ((value).as.array)
|
||||||
// #define AS_DICTIONARY(value)
|
#define AS_DICTIONARY(value) ((value).as.dictionary)
|
||||||
// #define AS_FUNCTION(value)
|
// #define AS_FUNCTION(value)
|
||||||
#define AS_IDENTIFIER(value) ((value).as.identifier.ptr)
|
#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_INTEGER_LITERAL(value) ((Literal){LITERAL_INTEGER, { .integer = value }})
|
||||||
#define TO_FLOAT_LITERAL(value) ((Literal){LITERAL_FLOAT, { .number = value }})
|
#define TO_FLOAT_LITERAL(value) ((Literal){LITERAL_FLOAT, { .number = value }})
|
||||||
#define TO_STRING_LITERAL(value) _toStringLiteral(value)
|
#define TO_STRING_LITERAL(value) _toStringLiteral(value)
|
||||||
// #define TO_ARRAY_LITERAL
|
#define TO_ARRAY_LITERAL(value) ((Literal){LITERAL_ARRAY, { .array = value }})
|
||||||
// #define TO_DICTIONARY_LITERAL
|
#define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }})
|
||||||
// #define TO_FUNCTION_LITERAL
|
// #define TO_FUNCTION_LITERAL
|
||||||
#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value)
|
#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value)
|
||||||
|
|
||||||
|
|||||||
@@ -37,14 +37,26 @@ void freeNode(Node* node) {
|
|||||||
for (int i = 0; i < node->block.count; i++) {
|
for (int i = 0; i < node->block.count; i++) {
|
||||||
freeNode(node->block.nodes + 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;
|
break;
|
||||||
|
|
||||||
case NODE_VAR_TYPES:
|
case NODE_VAR_TYPES:
|
||||||
for (int i = 0; i < node->varTypes.count; i++) {
|
for (int i = 0; i < node->varTypes.count; i++) {
|
||||||
freeNode(node->varTypes.nodes + 1);
|
freeNode(node->varTypes.nodes + 1);
|
||||||
}
|
}
|
||||||
//each sub-node gets freed individually
|
FREE_ARRAY(Node, node->varTypes.nodes, node->varTypes.capacity);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_VAR_DECL:
|
case NODE_VAR_DECL:
|
||||||
@@ -53,8 +65,6 @@ void freeNode(Node* node) {
|
|||||||
freeNode(node->varDecl.expression);
|
freeNode(node->varDecl.expression);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE(Node, node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitNodeLiteral(Node** nodeHandle, Literal literal) {
|
void emitNodeLiteral(Node** nodeHandle, Literal literal) {
|
||||||
@@ -105,6 +115,27 @@ void emitNodeBlock(Node** nodeHandle) {
|
|||||||
*nodeHandle = tmp;
|
*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) {
|
void emitNodeVarTypes(Node** nodeHandle, unsigned char mask) {
|
||||||
Node* tmp = ALLOCATE(Node, 1);
|
Node* tmp = ALLOCATE(Node, 1);
|
||||||
|
|
||||||
@@ -172,8 +203,26 @@ void printNode(Node* node) {
|
|||||||
printf("}\n");
|
printf("}\n");
|
||||||
break;
|
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:
|
case NODE_VAR_TYPES:
|
||||||
printf("[\n");
|
printf("type[\n");
|
||||||
|
|
||||||
for (int i = 0; i < node->varTypes.count; i++) {
|
for (int i = 0; i < node->varTypes.count; i++) {
|
||||||
printNode(&(node->varTypes.nodes[i]));
|
printNode(&(node->varTypes.nodes[i]));
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ typedef union _node Node;
|
|||||||
typedef enum NodeType {
|
typedef enum NodeType {
|
||||||
NODE_ERROR,
|
NODE_ERROR,
|
||||||
NODE_LITERAL, //a simple value
|
NODE_LITERAL, //a simple value
|
||||||
NODE_UNARY, //one child
|
NODE_UNARY, //one child + opcode
|
||||||
NODE_BINARY, //two children, left and right
|
NODE_BINARY, //two children, left and right + opcode
|
||||||
NODE_GROUPING, //one child
|
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_TYPES, //contains a type mask and a sub-node array for compound types
|
||||||
NODE_VAR_DECL, //contains identifier literal, typenode, expression definition
|
NODE_VAR_DECL, //contains identifier literal, typenode, expression definition
|
||||||
// NODE_CONDITIONAL, //three children: conditional, then path, else path
|
// NODE_CONDITIONAL, //three children: conditional, then path, else path
|
||||||
@@ -48,6 +50,19 @@ typedef struct NodeBlock {
|
|||||||
int count;
|
int count;
|
||||||
} NodeBlock;
|
} 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 {
|
typedef struct NodeVarTypes {
|
||||||
NodeType type;
|
NodeType type;
|
||||||
unsigned char mask;
|
unsigned char mask;
|
||||||
@@ -70,6 +85,8 @@ union _node {
|
|||||||
NodeBinary binary;
|
NodeBinary binary;
|
||||||
NodeGrouping grouping;
|
NodeGrouping grouping;
|
||||||
NodeBlock block;
|
NodeBlock block;
|
||||||
|
NodeCompound compound;
|
||||||
|
NodePair pair;
|
||||||
NodeVarTypes varTypes;
|
NodeVarTypes varTypes;
|
||||||
NodeVarDecl varDecl;
|
NodeVarDecl varDecl;
|
||||||
};
|
};
|
||||||
@@ -80,6 +97,8 @@ void emitNodeUnary(Node** nodeHandle, Opcode opcode);
|
|||||||
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode);
|
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode);
|
||||||
void emitNodeGrouping(Node** nodeHandle);
|
void emitNodeGrouping(Node** nodeHandle);
|
||||||
void emitNodeBlock(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 emitNodeVarTypes(Node** nodeHandle, unsigned char mask);
|
||||||
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Node* varType, Node* expression);
|
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) {
|
if (parser->current.type == TOKEN_ERROR) {
|
||||||
error(parser, parser->current, "Lexer 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);
|
static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule rule);
|
||||||
|
|
||||||
//the expression rules
|
//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) {
|
static Opcode string(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
|
||||||
//handle strings
|
//handle strings
|
||||||
switch(parser->previous.type) {
|
switch(parser->previous.type) {
|
||||||
@@ -330,7 +431,7 @@ ParseRule parseRules[] = { //must match the token types
|
|||||||
//logical operators
|
//logical operators
|
||||||
{grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT,
|
{grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_PAREN_RIGHT,
|
{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_BRACKET_RIGHT,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_BRACE_LEFT,
|
{NULL, NULL, PREC_NONE},// TOKEN_BRACE_LEFT,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_BRACE_RIGHT,
|
{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_ASSIGN,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_COLON,
|
{NULL, NULL, PREC_NONE},// TOKEN_COLON,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_SEMICOLON,
|
{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_DOT,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_PIPE,
|
{NULL, NULL, PREC_NONE},// TOKEN_PIPE,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_REST,
|
{NULL, NULL, PREC_NONE},// TOKEN_REST,
|
||||||
@@ -570,9 +671,9 @@ static void assertStmt(Parser* parser, Node* node) {
|
|||||||
node->type = NODE_BINARY;
|
node->type = NODE_BINARY;
|
||||||
node->unary.opcode = OP_ASSERT;
|
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");
|
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");
|
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of assert statement");
|
||||||
}
|
}
|
||||||
@@ -607,7 +708,7 @@ static void statement(Parser* parser, Node* node) {
|
|||||||
|
|
||||||
//declarations and definitions
|
//declarations and definitions
|
||||||
static void readVarType(Parser* parser, Node** nodeHandle) {
|
static void readVarType(Parser* parser, Node** nodeHandle) {
|
||||||
//TODO: compound types with the "type" keyword
|
//TODO: custom types with the "type" keyword
|
||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
unsigned char typeMask = 0;
|
unsigned char typeMask = 0;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ char* readFile(char* path, size_t* fileSize) {
|
|||||||
*fileSize = ftell(file);
|
*fileSize = ftell(file);
|
||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
char* buffer = (char*)malloc(*fileSize);
|
char* buffer = (char*)malloc(*fileSize + 1);
|
||||||
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
fprintf(stderr, "Not enough memory to read \"%s\"\n", path);
|
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);
|
size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file);
|
||||||
|
|
||||||
|
buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this
|
||||||
|
|
||||||
if (bytesRead < *fileSize) {
|
if (bytesRead < *fileSize) {
|
||||||
fprintf(stderr, "Could not read file \"%s\"\n", path);
|
fprintf(stderr, "Could not read file \"%s\"\n", path);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -109,13 +111,19 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
void runBinaryFile(char* fname) {
|
void runBinaryFile(char* fname) {
|
||||||
size_t size = 0; //not used
|
size_t size = 0; //not used
|
||||||
unsigned char* tb = (unsigned char*)readFile(fname, &size);
|
unsigned char* tb = (unsigned char*)readFile(fname, &size);
|
||||||
|
if (!tb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
runBinary(tb, size);
|
runBinary(tb, size);
|
||||||
//interpreter takes ownership of the binary data
|
//interpreter takes ownership of the binary data
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSource(char* source) {
|
void runSource(char* source) {
|
||||||
size_t size;
|
size_t size = 0;
|
||||||
unsigned char* tb = compileString(source, &size);
|
unsigned char* tb = compileString(source, &size);
|
||||||
|
if (!tb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
runBinary(tb, size);
|
runBinary(tb, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,11 +177,11 @@ void repl() {
|
|||||||
int size = 0;
|
int size = 0;
|
||||||
unsigned char* tb = collateCompiler(&compiler, &size);
|
unsigned char* tb = collateCompiler(&compiler, &size);
|
||||||
|
|
||||||
// for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
// printf("%d ", tb[i]);
|
printf("%d ", tb[i]);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
//run the bytecode
|
//run the bytecode
|
||||||
initInterpreter(&interpreter, tb, size);
|
initInterpreter(&interpreter, tb, size);
|
||||||
|
|||||||
Reference in New Issue
Block a user