WE ARE THE CHAMPIONS!

This commit is contained in:
2022-08-29 15:33:58 +10:00
parent a6f0200255
commit d055e9dc94
7 changed files with 1288 additions and 73 deletions

View File

@@ -5,7 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
void freeNode(Node* node) {
void freeNodeCustom(Node* node, bool freeSelf) {
//don't free a NULL node
if (node == NULL) {
return;
@@ -35,14 +35,14 @@ void freeNode(Node* node) {
case NODE_BLOCK:
for (int i = 0; i < node->block.count; i++) {
freeNode(node->block.nodes + i);
freeNodeCustom(node->block.nodes + i, false);
}
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);
freeNodeCustom(node->compound.nodes + i, false);
}
FREE_ARRAY(Node, node->compound.nodes, node->compound.capacity);
break;
@@ -67,7 +67,7 @@ void freeNode(Node* node) {
case NODE_FN_COLLECTION:
for (int i = 0; i < node->fnCollection.count; i++) {
freeNode(node->fnCollection.nodes + i);
freeNodeCustom(node->fnCollection.nodes + i, false);
}
FREE_ARRAY(Node, node->fnCollection.nodes, node->fnCollection.capacity);
break;
@@ -94,6 +94,14 @@ void freeNode(Node* node) {
freeLiteral(node->increment.identifier);
break;
}
if (freeSelf) {
FREE(Node, node);
}
}
void freeNode(Node* node) {
freeNodeCustom(node, true);
}
void emitNodeLiteral(Node** nodeHandle, Literal literal) {
@@ -101,7 +109,7 @@ void emitNodeLiteral(Node** nodeHandle, Literal literal) {
*nodeHandle = ALLOCATE(Node, 1);
(*nodeHandle)->type = NODE_LITERAL;
(*nodeHandle)->atomic.literal = literal;
(*nodeHandle)->atomic.literal = copyLiteral(literal);
}
void emitNodeUnary(Node** nodeHandle, Opcode opcode, Node* child) {
@@ -156,14 +164,11 @@ void emitNodeCompound(Node** nodeHandle, LiteralType literalType) {
*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 setNodePair(Node* node, Node* left, Node* right) {
//assume the node has already been allocated
node->type = NODE_PAIR;
node->pair.left = left;
node->pair.right = right;
}
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal typeLiteral, Node* expression) {
@@ -226,7 +231,7 @@ void emitNodePrefixIncrement(Node** nodeHandle, Literal identifier, int incremen
Node* tmp = ALLOCATE(Node, 1);
tmp->type = NODE_INCREMENT_PREFIX;
tmp->increment.identifier = identifier;
tmp->increment.identifier = copyLiteral(identifier);
tmp->increment.increment = increment;
*nodeHandle = tmp;
@@ -236,7 +241,7 @@ void emitNodePostfixIncrement(Node** nodeHandle, Literal identifier, int increme
Node* tmp = ALLOCATE(Node, 1);
tmp->type = NODE_INCREMENT_POSTFIX;
tmp->increment.identifier = identifier;
tmp->increment.identifier = copyLiteral(identifier);
tmp->increment.increment = increment;
*nodeHandle = tmp;

View File

@@ -141,7 +141,7 @@ void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode); //handled node
void emitNodeGrouping(Node** nodeHandle);
void emitNodeBlock(Node** nodeHandle);
void emitNodeCompound(Node** nodeHandle, LiteralType literalType);
void emitNodePair(Node** nodeHandle, Node* left, Node* right);
void setNodePair(Node* node, Node* left, Node* right);
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression);
void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node* returns, Node* block);
void emitFnCall(Node** nodeHandle, Node* arguments);

View File

@@ -125,6 +125,8 @@ static Opcode forceType(Parser* parser, Node** nodeHandle) {
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
return OP_EOF;
}
@@ -192,9 +194,7 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
}
//store the left and right in the node
Node* pair = NULL;
emitNodePair(&pair, left, right);
dictionary->compound.nodes[dictionary->compound.count++] = *pair;
setNodePair(&dictionary->compound.nodes[dictionary->compound.count++], left, right);
}
//detect an array
else {
@@ -218,8 +218,9 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
array->compound.nodes = GROW_ARRAY(Node, array->compound.nodes, oldCapacity, array->compound.capacity);
}
//store the left in the array
//copy into the array, and manually free the temp node
array->compound.nodes[array->compound.count++] = *left;
FREE(Node, left);
}
}
@@ -255,7 +256,9 @@ static Opcode string(Parser* parser, Node** nodeHandle) {
error(parser, parser->previous, buffer);
}
emitNodeLiteral(nodeHandle, TO_STRING_LITERAL(copyString(parser->previous.lexeme, length), length));
Literal literal = TO_STRING_LITERAL(copyString(parser->previous.lexeme, length), length);
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
return OP_EOF;
}
@@ -512,29 +515,43 @@ static Opcode identifier(Parser* parser, Node** nodeHandle) {
}
char* cpy = copyString(identifierToken.lexeme, length);
Literal identifier = _toIdentifierLiteral(cpy, strlen(cpy)); //BUGFIX: use this instead of the macro
Literal identifier = _toIdentifierLiteral(cpy, length); //BUGFIX: use this instead of the macro
emitNodeLiteral(nodeHandle, identifier);
freeLiteral(identifier); //don't leave it hanging
return OP_EOF;
}
static Opcode castingPrefix(Parser* parser, Node** nodeHandle) {
switch(parser->previous.type) {
case TOKEN_BOOLEAN:
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_BOOLEAN, false));
case TOKEN_BOOLEAN: {
Literal literal = TO_TYPE_LITERAL(LITERAL_BOOLEAN, false);
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
}
break;
case TOKEN_INTEGER:
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_INTEGER, false));
case TOKEN_INTEGER: {
Literal literal = TO_TYPE_LITERAL(LITERAL_INTEGER, false);
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
}
break;
case TOKEN_FLOAT:
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_FLOAT, false));
case TOKEN_FLOAT: {
Literal literal = TO_TYPE_LITERAL(LITERAL_FLOAT, false);
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
}
break;
case TOKEN_STRING:
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_STRING, false));
case TOKEN_STRING: {
Literal literal = TO_TYPE_LITERAL(LITERAL_STRING, false);
emitNodeLiteral(nodeHandle, literal);
freeLiteral(literal);
}
break;
default:
@@ -586,6 +603,8 @@ static Opcode incrementPrefix(Parser* parser, Node** nodeHandle) {
emitNodePrefixIncrement(nodeHandle, node->atomic.literal, 1);
freeNode(node);
return OP_EOF;
}
@@ -597,6 +616,8 @@ static Opcode incrementInfix(Parser* parser, Node** nodeHandle) {
emitNodePostfixIncrement(nodeHandle, node->atomic.literal, 1);
freeNode(node);
return OP_EOF;
}
@@ -604,10 +625,12 @@ static Opcode decrementPrefix(Parser* parser, Node** nodeHandle) {
advance(parser);
Node* node = NULL;
identifier(parser, &node);
identifier(parser, &node); //weird
emitNodePrefixIncrement(nodeHandle, node->atomic.literal, -1);
freeNode(node);
return OP_EOF;
}
@@ -619,6 +642,8 @@ static Opcode decrementInfix(Parser* parser, Node** nodeHandle) {
emitNodePostfixIncrement(nodeHandle, node->atomic.literal, -1);
freeNode(node);
return OP_EOF;
}
@@ -647,6 +672,7 @@ static Opcode fnCall(Parser* parser, Node** nodeHandle) {
Node* node = NULL;
parsePrecedence(parser, &node, PREC_TERNARY);
arguments->fnCollection.nodes[arguments->fnCollection.count++] = *node;
FREE(Node, node);
} while(match(parser, TOKEN_COMMA));
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of argument list");
@@ -1007,21 +1033,14 @@ static void blockStmt(Parser* parser, Node** nodeHandle) {
(*nodeHandle)->block.nodes = GROW_ARRAY(Node, (*nodeHandle)->block.nodes, oldCapacity, (*nodeHandle)->block.capacity);
}
//use the next node in sequence
(*nodeHandle)->block.nodes[(*nodeHandle)->block.count].type = NODE_ERROR; //BUGFIX: so freeing won't break the damn thing
Node* ptr = &((*nodeHandle)->block.nodes[(*nodeHandle)->block.count]);
Node* node = NULL;
//process the grammar rule for this line
declaration(parser, &ptr);
declaration(parser, &node);
// //BUGFIX: if ptr has been re-assigned, copy the new value into the block's child
// if (&((*nodeHandle)->block.nodes[(*nodeHandle)->block.count]) != ptr) {
// ((*nodeHandle)->block.nodes[(*nodeHandle)->block.count]) = *ptr;
// FREE(Node, ptr);
// }
(*nodeHandle)->block.count++;
//BUGFIX: statements no longer require an existing node
((*nodeHandle)->block.nodes[(*nodeHandle)->block.count++]) = *node;
FREE(Node, node); //simply free the tmp node
// Ground floor: perfumery / Stationery and leather goods / Wigs and haberdashery / Kitchenware and food / Going up!
if (parser->panic) {
@@ -1032,15 +1051,16 @@ static void blockStmt(Parser* parser, Node** nodeHandle) {
static void printStmt(Parser* parser, Node** nodeHandle) {
//set the node info
(*nodeHandle)->type = NODE_UNARY;
(*nodeHandle)->unary.opcode = OP_PRINT;
expression(parser, &((*nodeHandle)->unary.child));
Node* node = NULL;
expression(parser, &node);
emitNodeUnary(nodeHandle, OP_PRINT, node);
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of print statement");
}
static void assertStmt(Parser* parser, Node** nodeHandle) {
//set the node info
(*nodeHandle) = ALLOCATE(Node, 1); //special case, because I'm lazy
(*nodeHandle)->type = NODE_BINARY;
(*nodeHandle)->binary.opcode = OP_ASSERT;
@@ -1062,16 +1082,13 @@ static void ifStmt(Parser* parser, Node** nodeHandle) {
//read the then path
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of if clause");
thenPath = ALLOCATE(Node, 1);
declaration(parser, &thenPath);
//read the optional else path
if (match(parser, TOKEN_ELSE)) {
elsePath = ALLOCATE(Node, 1);
declaration(parser, &elsePath);
}
freeNode(*nodeHandle); //free the initial node
emitNodePath(nodeHandle, NODE_PATH_IF, NULL, NULL, condition, thenPath, elsePath);
}
@@ -1085,18 +1102,16 @@ static void whileStmt(Parser* parser, Node** nodeHandle) {
//read the then path
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of while clause");
thenPath = ALLOCATE(Node, 1);
declaration(parser, &thenPath);
freeNode(*nodeHandle); //free the initial node
emitNodePath(nodeHandle, NODE_PATH_WHILE, NULL, NULL, condition, thenPath, NULL);
}
static void forStmt(Parser* parser, Node** nodeHandle) {
Node* preClause = ALLOCATE(Node, 1);
Node* preClause = NULL;
Node* postClause = NULL;
Node* condition = NULL;
Node* thenPath = ALLOCATE(Node, 1);
Node* thenPath = NULL;
//read the clauses
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause");
@@ -1110,22 +1125,18 @@ static void forStmt(Parser* parser, Node** nodeHandle) {
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of for clause");
//read the path
thenPath = ALLOCATE(Node, 1);
declaration(parser, &thenPath);
freeNode(*nodeHandle); //free the initial node
emitNodePath(nodeHandle, NODE_PATH_FOR, preClause, postClause, condition, thenPath, NULL);
}
static void breakStmt(Parser* parser, Node** nodeHandle) {
freeNode(*nodeHandle);
emitNodePath(nodeHandle, NODE_PATH_BREAK, NULL, NULL, NULL, NULL, NULL);
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of break statement");
}
static void continueStmt(Parser* parser, Node** nodeHandle) {
freeNode(*nodeHandle);
emitNodePath(nodeHandle, NODE_PATH_CONTINUE, NULL, NULL, NULL, NULL, NULL);
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of continue statement");
@@ -1136,7 +1147,7 @@ static void returnStmt(Parser* parser, Node** nodeHandle) {
emitNodeFnCollection(&returnValues);
if (!match(parser, TOKEN_SEMICOLON)) {
do {
do { //loop for multiple returns (disabled later in the pipeline)
//append the node to the return list (grow the node if needed)
if (returnValues->fnCollection.capacity < returnValues->fnCollection.count + 1) {
int oldCapacity = returnValues->fnCollection.capacity;
@@ -1149,12 +1160,12 @@ static void returnStmt(Parser* parser, Node** nodeHandle) {
parsePrecedence(parser, &node, PREC_TERNARY);
returnValues->fnCollection.nodes[returnValues->fnCollection.count++] = *node;
FREE(Node, node);
} while(match(parser, TOKEN_COMMA));
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of return statement");
}
freeNode(*nodeHandle); //free the initial node
emitNodePath(nodeHandle, NODE_PATH_RETURN, NULL, NULL, NULL, returnValues, NULL);
}
@@ -1162,8 +1173,7 @@ static void returnStmt(Parser* parser, Node** nodeHandle) {
static void expressionStmt(Parser* parser, Node** nodeHandle) {
//BUGFIX: check for empty statements
if (match(parser, TOKEN_SEMICOLON)) {
(*nodeHandle)->type = NODE_LITERAL;
(*nodeHandle)->atomic.literal = TO_NULL_LITERAL;
emitNodeLiteral(nodeHandle, TO_NULL_LITERAL);
return;
}
@@ -1172,8 +1182,7 @@ static void expressionStmt(Parser* parser, Node** nodeHandle) {
expression(parser, &ptr);
if (ptr != NULL) {
**nodeHandle = *ptr;
FREE(Node, ptr); //BUGFIX: this thread of execution is nuts
*nodeHandle = ptr;
}
consume(parser, TOKEN_SEMICOLON, "Expected ';' at the end of expression statement");
@@ -1383,7 +1392,7 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
char* cpy = copyString(identifierToken.lexeme, length);
Literal identifier = _toIdentifierLiteral(cpy, strlen(cpy)); //BUGFIX: use this instead of the macro
//TODO: read the parameters and arity
//read the parameters and arity
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' after function identifier");
//for holding the array of arguments
@@ -1426,6 +1435,7 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
emitNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
argumentNode->fnCollection.nodes[argumentNode->fnCollection.count++] = *literalNode;
FREE(Node, literalNode);
break;
}
@@ -1469,6 +1479,7 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
emitNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
argumentNode->fnCollection.nodes[argumentNode->fnCollection.count++] = *literalNode;
FREE(Node, literalNode);
} while (match(parser, TOKEN_COMMA)); //if comma is read, continue
@@ -1493,13 +1504,14 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
emitNodeLiteral(&literalNode, readTypeToLiteral(parser));
returnNode->fnCollection.nodes[returnNode->fnCollection.count++] = *literalNode;
FREE(Node, literalNode);
} while(match(parser, TOKEN_COMMA));
}
//read the function body
consume(parser, TOKEN_BRACE_LEFT, "Expected '{' after return list");
Node* blockNode = ALLOCATE(Node, 1);
Node* blockNode = NULL;
blockStmt(parser, &blockNode);
//declare it
@@ -1547,8 +1559,7 @@ Node* scanParser(Parser* parser) {
}
//returns nodes on the heap
Node* node = ALLOCATE(Node, 1);
node->type = NODE_ERROR; //BUGFIX: so freeing won't break the damn thing
Node* node = NULL;
//process the grammar rule for this line
declaration(parser, &node);
@@ -1563,3 +1574,4 @@ Node* scanParser(Parser* parser) {
return node;
}