mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Renamed Node to ASTNode
This commit is contained in:
@@ -74,10 +74,10 @@ unsigned char* compileString(char* source, size_t* size) {
|
||||
initCompiler(&compiler);
|
||||
|
||||
//run the parser until the end of the source
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
while(node != NULL) {
|
||||
//pack up and leave
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
printf(ERROR "error node detected\n" RESET);
|
||||
freeNode(node);
|
||||
freeCompiler(&compiler);
|
||||
@@ -168,10 +168,10 @@ void repl() {
|
||||
initCompiler(&compiler);
|
||||
|
||||
//run this iteration
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
while(node != NULL) {
|
||||
//pack up and restart
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
printf(ERROR "error node detected\n" RESET);
|
||||
error = true;
|
||||
freeNode(node);
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
#include "node.h"
|
||||
#include "ast_node.h"
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void freeNodeCustom(Node* node, bool freeSelf) {
|
||||
void freeNodeCustom(ASTNode* node, bool freeSelf) {
|
||||
//don't free a NULL node
|
||||
if (node == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(node->type) {
|
||||
case NODE_ERROR:
|
||||
case AST_NODEERROR:
|
||||
//NO-OP
|
||||
break;
|
||||
|
||||
case NODE_LITERAL:
|
||||
case AST_NODELITERAL:
|
||||
freeLiteral(node->atomic.literal);
|
||||
break;
|
||||
|
||||
case NODE_UNARY:
|
||||
case AST_NODEUNARY:
|
||||
freeNode(node->unary.child);
|
||||
break;
|
||||
|
||||
case NODE_BINARY:
|
||||
case AST_NODEBINARY:
|
||||
freeNode(node->binary.left);
|
||||
freeNode(node->binary.right);
|
||||
break;
|
||||
|
||||
case NODE_GROUPING:
|
||||
case AST_NODEGROUPING:
|
||||
freeNode(node->grouping.child);
|
||||
break;
|
||||
|
||||
case NODE_BLOCK:
|
||||
case AST_NODEBLOCK:
|
||||
for (int i = 0; i < node->block.count; i++) {
|
||||
freeNodeCustom(node->block.nodes + i, false);
|
||||
}
|
||||
FREE_ARRAY(Node, node->block.nodes, node->block.capacity);
|
||||
FREE_ARRAY(ASTNode, node->block.nodes, node->block.capacity);
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND:
|
||||
case AST_NODECOMPOUND:
|
||||
for (int i = 0; i < node->compound.count; i++) {
|
||||
freeNodeCustom(node->compound.nodes + i, false);
|
||||
}
|
||||
FREE_ARRAY(Node, node->compound.nodes, node->compound.capacity);
|
||||
FREE_ARRAY(ASTNode, node->compound.nodes, node->compound.capacity);
|
||||
break;
|
||||
|
||||
case NODE_PAIR:
|
||||
case AST_NODEPAIR:
|
||||
freeNode(node->pair.left);
|
||||
freeNode(node->pair.right);
|
||||
break;
|
||||
|
||||
case NODE_VAR_DECL:
|
||||
case AST_NODEVAR_DECL:
|
||||
freeLiteral(node->varDecl.identifier);
|
||||
freeLiteral(node->varDecl.typeLiteral);
|
||||
freeNode(node->varDecl.expression);
|
||||
break;
|
||||
|
||||
case NODE_FN_DECL:
|
||||
case AST_NODEFN_DECL:
|
||||
freeLiteral(node->fnDecl.identifier);
|
||||
freeNode(node->fnDecl.arguments);
|
||||
freeNode(node->fnDecl.returns);
|
||||
freeNode(node->fnDecl.block);
|
||||
break;
|
||||
|
||||
case NODE_FN_COLLECTION:
|
||||
case AST_NODEFN_COLLECTION:
|
||||
for (int i = 0; i < node->fnCollection.count; i++) {
|
||||
freeNodeCustom(node->fnCollection.nodes + i, false);
|
||||
}
|
||||
FREE_ARRAY(Node, node->fnCollection.nodes, node->fnCollection.capacity);
|
||||
FREE_ARRAY(ASTNode, node->fnCollection.nodes, node->fnCollection.capacity);
|
||||
break;
|
||||
|
||||
case NODE_FN_CALL:
|
||||
case AST_NODEFN_CALL:
|
||||
freeNode(node->fnCall.arguments);
|
||||
break;
|
||||
|
||||
case NODE_PATH_IF:
|
||||
case NODE_PATH_WHILE:
|
||||
case NODE_PATH_FOR:
|
||||
case NODE_PATH_BREAK:
|
||||
case NODE_PATH_CONTINUE:
|
||||
case NODE_PATH_RETURN:
|
||||
case AST_NODEPATH_IF:
|
||||
case AST_NODEPATH_WHILE:
|
||||
case AST_NODEPATH_FOR:
|
||||
case AST_NODEPATH_BREAK:
|
||||
case AST_NODEPATH_CONTINUE:
|
||||
case AST_NODEPATH_RETURN:
|
||||
freeNode(node->path.preClause);
|
||||
freeNode(node->path.postClause);
|
||||
freeNode(node->path.condition);
|
||||
@@ -89,19 +89,19 @@ void freeNodeCustom(Node* node, bool freeSelf) {
|
||||
freeNode(node->path.elsePath);
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_PREFIX:
|
||||
case NODE_INCREMENT_POSTFIX:
|
||||
case AST_NODEINCREMENT_PREFIX:
|
||||
case AST_NODEINCREMENT_POSTFIX:
|
||||
freeLiteral(node->increment.identifier);
|
||||
break;
|
||||
|
||||
case NODE_IMPORT:
|
||||
case NODE_EXPORT:
|
||||
case AST_NODEIMPORT:
|
||||
case AST_NODEEXPORT:
|
||||
freeLiteral(node->import.identifier);
|
||||
freeLiteral(node->import.alias);
|
||||
break;
|
||||
|
||||
case NODE_INDEX:
|
||||
case NODE_DOT:
|
||||
case AST_NODEINDEX:
|
||||
case AST_NODEDOT:
|
||||
freeNode(node->index.first);
|
||||
freeNode(node->index.second);
|
||||
freeNode(node->index.third);
|
||||
@@ -109,35 +109,35 @@ void freeNodeCustom(Node* node, bool freeSelf) {
|
||||
}
|
||||
|
||||
if (freeSelf) {
|
||||
FREE(Node, node);
|
||||
FREE(ASTNode, node);
|
||||
}
|
||||
}
|
||||
|
||||
void freeNode(Node* node) {
|
||||
void freeNode(ASTNode* node) {
|
||||
freeNodeCustom(node, true);
|
||||
}
|
||||
|
||||
void emitNodeLiteral(Node** nodeHandle, Literal literal) {
|
||||
void emitASTNodeLiteral(ASTNode** nodeHandle, Literal literal) {
|
||||
//allocate a new node
|
||||
*nodeHandle = ALLOCATE(Node, 1);
|
||||
*nodeHandle = ALLOCATE(ASTNode, 1);
|
||||
|
||||
(*nodeHandle)->type = NODE_LITERAL;
|
||||
(*nodeHandle)->type = AST_NODELITERAL;
|
||||
(*nodeHandle)->atomic.literal = copyLiteral(literal);
|
||||
}
|
||||
|
||||
void emitNodeUnary(Node** nodeHandle, Opcode opcode, Node* child) {
|
||||
void emitASTNodeUnary(ASTNode** nodeHandle, Opcode opcode, ASTNode* child) {
|
||||
//allocate a new node
|
||||
*nodeHandle = ALLOCATE(Node, 1);
|
||||
*nodeHandle = ALLOCATE(ASTNode, 1);
|
||||
|
||||
(*nodeHandle)->type = NODE_UNARY;
|
||||
(*nodeHandle)->type = AST_NODEUNARY;
|
||||
(*nodeHandle)->unary.opcode = opcode;
|
||||
(*nodeHandle)->unary.child = child;
|
||||
}
|
||||
|
||||
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeBinary(ASTNode** nodeHandle, ASTNode* rhs, Opcode opcode) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_BINARY;
|
||||
tmp->type = AST_NODEBINARY;
|
||||
tmp->binary.opcode = opcode;
|
||||
tmp->binary.left = *nodeHandle;
|
||||
tmp->binary.right = rhs;
|
||||
@@ -145,19 +145,19 @@ void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode) {
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeGrouping(Node** nodeHandle) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeGrouping(ASTNode** nodeHandle) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_GROUPING;
|
||||
tmp->type = AST_NODEGROUPING;
|
||||
tmp->grouping.child = *nodeHandle;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeBlock(Node** nodeHandle) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeBlock(ASTNode** nodeHandle) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_BLOCK;
|
||||
tmp->type = AST_NODEBLOCK;
|
||||
tmp->block.nodes = NULL;
|
||||
tmp->block.capacity = 0;
|
||||
tmp->block.count = 0;
|
||||
@@ -165,10 +165,10 @@ void emitNodeBlock(Node** nodeHandle) {
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeCompound(Node** nodeHandle, LiteralType literalType) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeCompound(ASTNode** nodeHandle, LiteralType literalType) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_COMPOUND;
|
||||
tmp->type = AST_NODECOMPOUND;
|
||||
tmp->compound.literalType = literalType;
|
||||
tmp->compound.nodes = NULL;
|
||||
tmp->compound.capacity = 0;
|
||||
@@ -177,17 +177,17 @@ void emitNodeCompound(Node** nodeHandle, LiteralType literalType) {
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void setNodePair(Node* node, Node* left, Node* right) {
|
||||
void setASTNodePair(ASTNode* node, ASTNode* left, ASTNode* right) {
|
||||
//assume the node has already been allocated
|
||||
node->type = NODE_PAIR;
|
||||
node->type = AST_NODEPAIR;
|
||||
node->pair.left = left;
|
||||
node->pair.right = right;
|
||||
}
|
||||
|
||||
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal typeLiteral, Node* expression) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeVarDecl(ASTNode** nodeHandle, Literal identifier, Literal typeLiteral, ASTNode* expression) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_VAR_DECL;
|
||||
tmp->type = AST_NODEVAR_DECL;
|
||||
tmp->varDecl.identifier = identifier;
|
||||
tmp->varDecl.typeLiteral = typeLiteral;
|
||||
tmp->varDecl.expression = expression;
|
||||
@@ -195,10 +195,10 @@ void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal typeLiteral,
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node* returns, Node* block) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeFnDecl(ASTNode** nodeHandle, Literal identifier, ASTNode* arguments, ASTNode* returns, ASTNode* block) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_FN_DECL;
|
||||
tmp->type = AST_NODEFN_DECL;
|
||||
tmp->fnDecl.identifier = identifier;
|
||||
tmp->fnDecl.arguments = arguments;
|
||||
tmp->fnDecl.returns = returns;
|
||||
@@ -207,20 +207,20 @@ void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitFnCall(Node** nodeHandle, Node* arguments, int argumentCount) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTFnCall(ASTNode** nodeHandle, ASTNode* arguments, int argumentCount) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_FN_CALL;
|
||||
tmp->type = AST_NODEFN_CALL;
|
||||
tmp->fnCall.arguments = arguments;
|
||||
tmp->fnCall.argumentCount = argumentCount;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeFnCollection(Node** nodeHandle) { //a collection of nodes, intended for use with functions
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeFnCollection(ASTNode** nodeHandle) { //a collection of nodes, intended for use with functions
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_FN_COLLECTION;
|
||||
tmp->type = AST_NODEFN_COLLECTION;
|
||||
tmp->fnCollection.nodes = NULL;
|
||||
tmp->fnCollection.capacity = 0;
|
||||
tmp->fnCollection.count = 0;
|
||||
@@ -228,8 +228,8 @@ void emitNodeFnCollection(Node** nodeHandle) { //a collection of nodes, intended
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodePath(ASTNode** nodeHandle, ASTNodeType type, ASTNode* preClause, ASTNode* postClause, ASTNode* condition, ASTNode* thenPath, ASTNode* elsePath) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = type;
|
||||
tmp->path.preClause = preClause;
|
||||
@@ -241,28 +241,28 @@ void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postC
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodePrefixIncrement(ASTNode** nodeHandle, Literal identifier, int increment) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_INCREMENT_PREFIX;
|
||||
tmp->type = AST_NODEINCREMENT_PREFIX;
|
||||
tmp->increment.identifier = copyLiteral(identifier);
|
||||
tmp->increment.increment = increment;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodePostfixIncrement(Node** nodeHandle, Literal identifier, int increment) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodePostfixIncrement(ASTNode** nodeHandle, Literal identifier, int increment) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_INCREMENT_POSTFIX;
|
||||
tmp->type = AST_NODEINCREMENT_POSTFIX;
|
||||
tmp->increment.identifier = copyLiteral(identifier);
|
||||
tmp->increment.increment = increment;
|
||||
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeImport(Node** nodeHandle, NodeType mode, Literal identifier, Literal alias) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeImport(ASTNode** nodeHandle, ASTNodeType mode, Literal identifier, Literal alias) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = mode;
|
||||
tmp->import.identifier = copyLiteral(identifier);
|
||||
@@ -271,10 +271,10 @@ void emitNodeImport(Node** nodeHandle, NodeType mode, Literal identifier, Litera
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeIndex(Node** nodeHandle, Node* first, Node* second, Node* third) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeIndex(ASTNode** nodeHandle, ASTNode* first, ASTNode* second, ASTNode* third) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_INDEX;
|
||||
tmp->type = AST_NODEINDEX;
|
||||
tmp->index.first = first;
|
||||
tmp->index.second = second;
|
||||
tmp->index.third = third;
|
||||
@@ -282,10 +282,10 @@ void emitNodeIndex(Node** nodeHandle, Node* first, Node* second, Node* third) {
|
||||
*nodeHandle = tmp;
|
||||
}
|
||||
|
||||
void emitNodeDot(Node** nodeHandle, Node* first) {
|
||||
Node* tmp = ALLOCATE(Node, 1);
|
||||
void emitASTNodeDot(ASTNode** nodeHandle, ASTNode* first) {
|
||||
ASTNode* tmp = ALLOCATE(ASTNode, 1);
|
||||
|
||||
tmp->type = NODE_DOT;
|
||||
tmp->type = AST_NODEDOT;
|
||||
tmp->index.first = first;
|
||||
tmp->index.second = NULL;
|
||||
tmp->index.third = NULL;
|
||||
175
source/ast_node.h
Normal file
175
source/ast_node.h
Normal file
@@ -0,0 +1,175 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "literal.h"
|
||||
#include "opcodes.h"
|
||||
#include "token_types.h"
|
||||
|
||||
//nodes are the intermediaries between parsers and compilers
|
||||
typedef union _node ASTNode;
|
||||
|
||||
typedef enum ASTNodeType {
|
||||
AST_NODEERROR,
|
||||
AST_NODELITERAL, //a simple value
|
||||
AST_NODEUNARY, //one child + opcode
|
||||
AST_NODEBINARY, //two children, left and right + opcode
|
||||
AST_NODEGROUPING, //one child
|
||||
AST_NODEBLOCK, //contains a sub-node array
|
||||
AST_NODECOMPOUND, //contains a sub-node array
|
||||
AST_NODEPAIR, //contains a left and right
|
||||
AST_NODEVAR_DECL, //contains identifier literal, typenode, expression definition
|
||||
AST_NODEFN_DECL, //containd identifier literal, arguments node, returns node, block node
|
||||
AST_NODEFN_COLLECTION, //parts of a function
|
||||
AST_NODEFN_CALL,
|
||||
AST_NODEPATH_IF, //for control flow
|
||||
AST_NODEPATH_WHILE, //for control flow
|
||||
AST_NODEPATH_FOR, //for control flow
|
||||
AST_NODEPATH_BREAK, //for control flow
|
||||
AST_NODEPATH_CONTINUE, //for control flow
|
||||
AST_NODEPATH_RETURN,
|
||||
AST_NODEINCREMENT_PREFIX,
|
||||
AST_NODEINCREMENT_POSTFIX,
|
||||
AST_NODEIMPORT,
|
||||
AST_NODEEXPORT,
|
||||
AST_NODEINDEX,
|
||||
AST_NODEDOT,
|
||||
} ASTNodeType;
|
||||
|
||||
typedef struct NodeLiteral {
|
||||
ASTNodeType type;
|
||||
Literal literal;
|
||||
} NodeLiteral;
|
||||
|
||||
typedef struct NodeUnary {
|
||||
ASTNodeType type;
|
||||
Opcode opcode;
|
||||
ASTNode* child;
|
||||
} NodeUnary;
|
||||
|
||||
typedef struct NodeBinary {
|
||||
ASTNodeType type;
|
||||
Opcode opcode;
|
||||
ASTNode* left;
|
||||
ASTNode* right;
|
||||
} NodeBinary;
|
||||
|
||||
typedef struct NodeGrouping {
|
||||
ASTNodeType type;
|
||||
ASTNode* child;
|
||||
} NodeGrouping;
|
||||
|
||||
typedef struct NodeBlock {
|
||||
ASTNodeType type;
|
||||
ASTNode* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeBlock;
|
||||
|
||||
typedef struct NodeCompound {
|
||||
ASTNodeType type;
|
||||
LiteralType literalType;
|
||||
ASTNode* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeCompound;
|
||||
|
||||
typedef struct NodePair {
|
||||
ASTNodeType type;
|
||||
ASTNode* left;
|
||||
ASTNode* right;
|
||||
} NodePair;
|
||||
|
||||
typedef struct NodeVarDecl {
|
||||
ASTNodeType type;
|
||||
Literal identifier;
|
||||
Literal typeLiteral;
|
||||
ASTNode* expression;
|
||||
} NodeVarDecl;
|
||||
|
||||
typedef struct NodeFnDecl {
|
||||
ASTNodeType type;
|
||||
Literal identifier;
|
||||
ASTNode* arguments;
|
||||
ASTNode* returns;
|
||||
ASTNode* block;
|
||||
} NodeFnDecl;
|
||||
|
||||
typedef struct NodeFnCollection {
|
||||
ASTNodeType type;
|
||||
ASTNode* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeFnCollection;
|
||||
|
||||
typedef struct NodeFnCall {
|
||||
ASTNodeType type;
|
||||
ASTNode* arguments;
|
||||
int argumentCount;
|
||||
} NodeFnCall;
|
||||
|
||||
typedef struct NodePath {
|
||||
ASTNodeType type;
|
||||
ASTNode* preClause;
|
||||
ASTNode* postClause;
|
||||
ASTNode* condition;
|
||||
ASTNode* thenPath;
|
||||
ASTNode* elsePath;
|
||||
} NodePath;
|
||||
|
||||
typedef struct NodeIncrement {
|
||||
ASTNodeType type;
|
||||
Literal identifier;
|
||||
int increment;
|
||||
} NodeIncrement;
|
||||
|
||||
typedef struct NodeImport {
|
||||
ASTNodeType type;
|
||||
Literal identifier;
|
||||
Literal alias;
|
||||
} NodeImport;
|
||||
|
||||
typedef struct NodeIndex {
|
||||
ASTNodeType type;
|
||||
ASTNode* first;
|
||||
ASTNode* second;
|
||||
ASTNode* third;
|
||||
} NodeIndex;
|
||||
|
||||
union _node {
|
||||
ASTNodeType type;
|
||||
NodeLiteral atomic;
|
||||
NodeUnary unary;
|
||||
NodeBinary binary;
|
||||
NodeGrouping grouping;
|
||||
NodeBlock block;
|
||||
NodeCompound compound;
|
||||
NodePair pair;
|
||||
NodeVarDecl varDecl;
|
||||
NodeFnDecl fnDecl;
|
||||
NodeFnCollection fnCollection;
|
||||
NodeFnCall fnCall;
|
||||
NodePath path;
|
||||
NodeIncrement increment;
|
||||
NodeImport import;
|
||||
NodeIndex index;
|
||||
};
|
||||
|
||||
TOY_API void freeNode(ASTNode* node);
|
||||
|
||||
void emitASTNodeLiteral(ASTNode** nodeHandle, Literal literal);
|
||||
void emitASTNodeUnary(ASTNode** nodeHandle, Opcode opcode, ASTNode* child);
|
||||
void emitASTNodeBinary(ASTNode** nodeHandle, ASTNode* rhs, Opcode opcode); //handled node becomes lhs
|
||||
void emitASTNodeGrouping(ASTNode** nodeHandle);
|
||||
void emitASTNodeBlock(ASTNode** nodeHandle);
|
||||
void emitASTNodeCompound(ASTNode** nodeHandle, LiteralType literalType);
|
||||
void setASTNodePair(ASTNode* node, ASTNode* left, ASTNode* right);
|
||||
void emitASTNodeVarDecl(ASTNode** nodeHandle, Literal identifier, Literal type, ASTNode* expression);
|
||||
void emitASTNodeFnDecl(ASTNode** nodeHandle, Literal identifier, ASTNode* arguments, ASTNode* returns, ASTNode* block);
|
||||
void emitASTFnCall(ASTNode** nodeHandle, ASTNode* arguments, int argumentCount);
|
||||
void emitASTNodeFnCollection(ASTNode** nodeHandle);
|
||||
void emitASTNodePath(ASTNode** nodeHandle, ASTNodeType type, ASTNode* preClause, ASTNode* postClause, ASTNode* condition, ASTNode* thenPath, ASTNode* elsePath);
|
||||
void emitASTNodePrefixIncrement(ASTNode** nodeHandle, Literal identifier, int increment);
|
||||
void emitASTNodePostfixIncrement(ASTNode** nodeHandle, Literal identifier, int increment);
|
||||
void emitASTNodeImport(ASTNode** nodeHandle, ASTNodeType mode, Literal identifier, Literal alias);
|
||||
void emitASTNodeIndex(ASTNode** nodeHandle, ASTNode* first, ASTNode* second, ASTNode* third);
|
||||
void emitASTNodeDot(ASTNode** nodeHandle, ASTNode* first);
|
||||
@@ -70,7 +70,7 @@ static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal)
|
||||
return writeLiteralTypeToCacheOpt(literalCache, literal, false);
|
||||
}
|
||||
|
||||
static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
static int writeNodeCompoundToCache(Compiler* compiler, ASTNode* node) {
|
||||
int index = -1;
|
||||
|
||||
//for both, stored as an array
|
||||
@@ -83,7 +83,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
for (int i = 0; i < node->compound.count; i++) {
|
||||
//keys
|
||||
switch(node->compound.nodes[i].pair.left->type) {
|
||||
case NODE_LITERAL: {
|
||||
case AST_NODELITERAL: {
|
||||
//keys are literals
|
||||
int key = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal);
|
||||
if (key < 0) {
|
||||
@@ -96,7 +96,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND: {
|
||||
case AST_NODECOMPOUND: {
|
||||
int key = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.left);
|
||||
|
||||
Literal literal = TO_INTEGER_LITERAL(key);
|
||||
@@ -112,7 +112,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
|
||||
//values
|
||||
switch(node->compound.nodes[i].pair.right->type) {
|
||||
case NODE_LITERAL: {
|
||||
case AST_NODELITERAL: {
|
||||
//values are literals
|
||||
int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal);
|
||||
if (val < 0) {
|
||||
@@ -125,7 +125,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND: {
|
||||
case AST_NODECOMPOUND: {
|
||||
int val = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.right);
|
||||
|
||||
Literal literal = TO_INTEGER_LITERAL(val);
|
||||
@@ -150,7 +150,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
//ensure each literal value is in the cache, individually
|
||||
for (int i = 0; i < node->compound.count; i++) {
|
||||
switch(node->compound.nodes[i].type) {
|
||||
case NODE_LITERAL: {
|
||||
case AST_NODELITERAL: {
|
||||
//values
|
||||
int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal);
|
||||
if (val < 0) {
|
||||
@@ -163,7 +163,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND: {
|
||||
case AST_NODECOMPOUND: {
|
||||
int val = writeNodeCompoundToCache(compiler, &node->compound.nodes[i]);
|
||||
|
||||
Literal literal = TO_INTEGER_LITERAL(val);
|
||||
@@ -190,14 +190,14 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
||||
return index;
|
||||
}
|
||||
|
||||
static int writeNodeCollectionToCache(Compiler* compiler, Node* node) {
|
||||
static int writeNodeCollectionToCache(Compiler* compiler, ASTNode* node) {
|
||||
LiteralArray* store = ALLOCATE(LiteralArray, 1);
|
||||
initLiteralArray(store);
|
||||
|
||||
//ensure each literal value is in the cache, individually
|
||||
for (int i = 0; i < node->fnCollection.count; i++) {
|
||||
switch(node->fnCollection.nodes[i].type) {
|
||||
case NODE_VAR_DECL: {
|
||||
case AST_NODEVAR_DECL: {
|
||||
//write each piece of the declaration to the cache
|
||||
int identifierIndex = pushLiteralArray(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.identifier); //store without duplication optimisation
|
||||
int typeIndex = writeLiteralTypeToCacheOpt(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.typeLiteral, false);
|
||||
@@ -212,7 +212,7 @@ static int writeNodeCollectionToCache(Compiler* compiler, Node* node) {
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_LITERAL: {
|
||||
case AST_NODELITERAL: {
|
||||
//write each piece of the declaration to the cache
|
||||
int typeIndex = writeLiteralTypeToCacheOpt(&compiler->literalCache, node->fnCollection.nodes[i].atomic.literal, false);
|
||||
|
||||
@@ -269,7 +269,7 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
|
||||
|
||||
//NOTE: jumpOfsets are included, because function arg and return indexes are embedded in the code body i.e. need to include thier sizes in the jump
|
||||
//NODE: rootNode should NOT include groupings and blocks
|
||||
static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr, int jumpOffsets, Node* rootNode) {
|
||||
static Opcode writeCompilerWithJumps(Compiler* compiler, ASTNode* node, void* breakAddressesPtr, void* continueAddressesPtr, int jumpOffsets, ASTNode* rootNode) {
|
||||
//grow if the bytecode space is too small
|
||||
if (compiler->count + 32 > compiler->capacity) {
|
||||
int oldCapacity = compiler->capacity;
|
||||
@@ -280,18 +280,18 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
|
||||
//determine node type
|
||||
switch(node->type) {
|
||||
case NODE_ERROR: {
|
||||
fprintf(stderr, ERROR "[internal] NODE_ERROR encountered in writeCompilerWithJumps()\n" RESET);
|
||||
case AST_NODEERROR: {
|
||||
fprintf(stderr, ERROR "[internal] AST_NODEERROR encountered in writeCompilerWithJumps()\n" RESET);
|
||||
compiler->bytecode[compiler->count++] = OP_EOF; //1 byte
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_LITERAL: {
|
||||
case AST_NODELITERAL: {
|
||||
writeLiteralToCompiler(compiler, node->atomic.literal);
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_UNARY: {
|
||||
case AST_NODEUNARY: {
|
||||
//pass to the child node, then embed the unary command (print, negate, etc.)
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
|
||||
@@ -304,7 +304,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
break;
|
||||
|
||||
//all infixes come here
|
||||
case NODE_BINARY: {
|
||||
case AST_NODEBINARY: {
|
||||
//pass to the child nodes, then embed the binary command (math, etc.)
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
|
||||
@@ -324,7 +324,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
//return this if...
|
||||
Opcode ret = writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
|
||||
if (node->binary.opcode == OP_INDEX && rootNode->type == NODE_BINARY && rootNode->binary.opcode == OP_VAR_ASSIGN) { //why var assign?
|
||||
if (node->binary.opcode == OP_INDEX && rootNode->type == AST_NODEBINARY && rootNode->binary.opcode == OP_VAR_ASSIGN) { //why var assign?
|
||||
return OP_INDEX_ASSIGN_INTERMEDIATE;
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_GROUPING: {
|
||||
case AST_NODEGROUPING: {
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_BEGIN; //1 byte
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets, node->grouping.child);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
@@ -354,7 +354,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_BLOCK: {
|
||||
case AST_NODEBLOCK: {
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_BEGIN; //1 byte
|
||||
|
||||
for (int i = 0; i < node->block.count; i++) {
|
||||
@@ -368,7 +368,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND: {
|
||||
case AST_NODECOMPOUND: {
|
||||
int index = writeNodeCompoundToCache(compiler, node);
|
||||
|
||||
//push the node opcode to the bytecode
|
||||
@@ -387,12 +387,12 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PAIR:
|
||||
fprintf(stderr, ERROR "[internal] NODE_PAIR encountered in writeCompilerWithJumps()\n" RESET);
|
||||
case AST_NODEPAIR:
|
||||
fprintf(stderr, ERROR "[internal] AST_NODEPAIR encountered in writeCompilerWithJumps()\n" RESET);
|
||||
compiler->bytecode[compiler->count++] = OP_EOF; //1 byte
|
||||
break;
|
||||
|
||||
case NODE_VAR_DECL: {
|
||||
case AST_NODEVAR_DECL: {
|
||||
//first, embed the expression (leaves it on the stack)
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
@@ -427,7 +427,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_FN_DECL: {
|
||||
case AST_NODEFN_DECL: {
|
||||
//run a compiler over the function
|
||||
Compiler* fnCompiler = ALLOCATE(Compiler, 1);
|
||||
initCompiler(fnCompiler);
|
||||
@@ -471,7 +471,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_FN_COLLECTION: {
|
||||
case AST_NODEFN_COLLECTION: {
|
||||
//embed these in the bytecode...
|
||||
int index = writeNodeCollectionToCache(compiler, node);
|
||||
|
||||
@@ -480,12 +480,12 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_FN_CALL: {
|
||||
case AST_NODEFN_CALL: {
|
||||
//NOTE: assume the function definition/name is above us
|
||||
|
||||
for (int i = 0; i < node->fnCall.arguments->fnCollection.count; i++) { //reverse order, to count from the beginning in the interpreter
|
||||
//sub-calls
|
||||
if (node->fnCall.arguments->fnCollection.nodes[i].type != NODE_LITERAL) {
|
||||
if (node->fnCall.arguments->fnCollection.nodes[i].type != AST_NODELITERAL) {
|
||||
Opcode override = writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
@@ -540,7 +540,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_IF: {
|
||||
case AST_NODEPATH_IF: {
|
||||
//process the condition
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
@@ -583,7 +583,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_WHILE: {
|
||||
case AST_NODEPATH_WHILE: {
|
||||
//for breaks and continues
|
||||
LiteralArray breakAddresses;
|
||||
LiteralArray continueAddresses;
|
||||
@@ -639,7 +639,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_FOR: {
|
||||
case AST_NODEPATH_FOR: {
|
||||
//for breaks and continues
|
||||
LiteralArray breakAddresses;
|
||||
LiteralArray continueAddresses;
|
||||
@@ -712,7 +712,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_BREAK: {
|
||||
case AST_NODEPATH_BREAK: {
|
||||
if (!breakAddressesPtr) {
|
||||
fprintf(stderr, ERROR "ERROR: Can't place a break statement here\n" RESET);
|
||||
break;
|
||||
@@ -730,7 +730,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_CONTINUE: {
|
||||
case AST_NODEPATH_CONTINUE: {
|
||||
if (!continueAddressesPtr) {
|
||||
fprintf(stderr, ERROR "ERROR: Can't place a continue statement here\n" RESET);
|
||||
break;
|
||||
@@ -748,7 +748,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_PATH_RETURN: {
|
||||
case AST_NODEPATH_RETURN: {
|
||||
//read each returned literal onto the stack, and return the number of values to return
|
||||
for (int i = 0; i < node->path.thenPath->fnCollection.count; i++) {
|
||||
Opcode override = writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||
@@ -765,7 +765,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_PREFIX: {
|
||||
case AST_NODEINCREMENT_PREFIX: {
|
||||
//push the literal to the stack (twice)
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
@@ -786,7 +786,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_INCREMENT_POSTFIX: {
|
||||
case AST_NODEINCREMENT_POSTFIX: {
|
||||
//push the identifier's VALUE to the stack
|
||||
writeLiteralToCompiler(compiler, node->increment.identifier);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_LITERAL_RAW; //1 byte
|
||||
@@ -807,7 +807,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_IMPORT: {
|
||||
case AST_NODEIMPORT: {
|
||||
//push the identifier, and the alias
|
||||
writeLiteralToCompiler(compiler, node->import.identifier);
|
||||
writeLiteralToCompiler(compiler, node->import.alias);
|
||||
@@ -817,7 +817,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_EXPORT: {
|
||||
case AST_NODEEXPORT: {
|
||||
//push the identifier, and the alias
|
||||
writeLiteralToCompiler(compiler, node->import.identifier);
|
||||
writeLiteralToCompiler(compiler, node->import.alias);
|
||||
@@ -827,7 +827,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_INDEX: {
|
||||
case AST_NODEINDEX: {
|
||||
//pass to the child nodes, then embed the opcode
|
||||
|
||||
//first
|
||||
@@ -869,8 +869,8 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_DOT: {
|
||||
fprintf(stderr, ERROR "[internal] NODE_DOT encountered in writeCompilerWithJumps()\n" RESET);
|
||||
case AST_NODEDOT: {
|
||||
fprintf(stderr, ERROR "[internal] AST_NODEDOT encountered in writeCompilerWithJumps()\n" RESET);
|
||||
compiler->bytecode[compiler->count++] = OP_EOF; //1 byte
|
||||
}
|
||||
break;
|
||||
@@ -879,7 +879,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
void writeCompiler(Compiler* compiler, Node* node) {
|
||||
void writeCompiler(Compiler* compiler, ASTNode* node) {
|
||||
Opcode op = writeCompilerWithJumps(compiler, node, NULL, NULL, 0, node); //pass in "node" as the root node
|
||||
|
||||
if (op != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "opcodes.h"
|
||||
#include "node.h"
|
||||
#include "ast_node.h"
|
||||
#include "literal_array.h"
|
||||
|
||||
//the compiler takes the nodes, and turns them into sequential chunks of bytecode, saving literals to an external array
|
||||
@@ -14,7 +14,7 @@ typedef struct Compiler {
|
||||
} Compiler;
|
||||
|
||||
TOY_API void initCompiler(Compiler* compiler);
|
||||
TOY_API void writeCompiler(Compiler* compiler, Node* node);
|
||||
TOY_API void writeCompiler(Compiler* compiler, ASTNode* node);
|
||||
TOY_API void freeCompiler(Compiler* compiler);
|
||||
|
||||
//embed the header, data section, code section, function section, etc.
|
||||
|
||||
175
source/node.h
175
source/node.h
@@ -1,175 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "literal.h"
|
||||
#include "opcodes.h"
|
||||
#include "token_types.h"
|
||||
|
||||
//nodes are the intermediaries between parsers and compilers
|
||||
typedef union _node Node;
|
||||
|
||||
typedef enum NodeType {
|
||||
NODE_ERROR,
|
||||
NODE_LITERAL, //a simple value
|
||||
NODE_UNARY, //one child + opcode
|
||||
NODE_BINARY, //two children, left and right + opcode
|
||||
NODE_GROUPING, //one child
|
||||
NODE_BLOCK, //contains a sub-node array
|
||||
NODE_COMPOUND, //contains a sub-node array
|
||||
NODE_PAIR, //contains a left and right
|
||||
NODE_VAR_DECL, //contains identifier literal, typenode, expression definition
|
||||
NODE_FN_DECL, //containd identifier literal, arguments node, returns node, block node
|
||||
NODE_FN_COLLECTION, //parts of a function
|
||||
NODE_FN_CALL,
|
||||
NODE_PATH_IF, //for control flow
|
||||
NODE_PATH_WHILE, //for control flow
|
||||
NODE_PATH_FOR, //for control flow
|
||||
NODE_PATH_BREAK, //for control flow
|
||||
NODE_PATH_CONTINUE, //for control flow
|
||||
NODE_PATH_RETURN,
|
||||
NODE_INCREMENT_PREFIX,
|
||||
NODE_INCREMENT_POSTFIX,
|
||||
NODE_IMPORT,
|
||||
NODE_EXPORT,
|
||||
NODE_INDEX,
|
||||
NODE_DOT,
|
||||
} NodeType;
|
||||
|
||||
typedef struct NodeLiteral {
|
||||
NodeType type;
|
||||
Literal literal;
|
||||
} NodeLiteral;
|
||||
|
||||
typedef struct NodeUnary {
|
||||
NodeType type;
|
||||
Opcode opcode;
|
||||
Node* child;
|
||||
} NodeUnary;
|
||||
|
||||
typedef struct NodeBinary {
|
||||
NodeType type;
|
||||
Opcode opcode;
|
||||
Node* left;
|
||||
Node* right;
|
||||
} NodeBinary;
|
||||
|
||||
typedef struct NodeGrouping {
|
||||
NodeType type;
|
||||
Node* child;
|
||||
} NodeGrouping;
|
||||
|
||||
typedef struct NodeBlock {
|
||||
NodeType type;
|
||||
Node* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeBlock;
|
||||
|
||||
typedef struct NodeCompound {
|
||||
NodeType type;
|
||||
LiteralType literalType;
|
||||
Node* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeCompound;
|
||||
|
||||
typedef struct NodePair {
|
||||
NodeType type;
|
||||
Node* left;
|
||||
Node* right;
|
||||
} NodePair;
|
||||
|
||||
typedef struct NodeVarDecl {
|
||||
NodeType type;
|
||||
Literal identifier;
|
||||
Literal typeLiteral;
|
||||
Node* expression;
|
||||
} NodeVarDecl;
|
||||
|
||||
typedef struct NodeFnDecl {
|
||||
NodeType type;
|
||||
Literal identifier;
|
||||
Node* arguments;
|
||||
Node* returns;
|
||||
Node* block;
|
||||
} NodeFnDecl;
|
||||
|
||||
typedef struct NodeFnCollection {
|
||||
NodeType type;
|
||||
Node* nodes;
|
||||
int capacity;
|
||||
int count;
|
||||
} NodeFnCollection;
|
||||
|
||||
typedef struct NodeFnCall {
|
||||
NodeType type;
|
||||
Node* arguments;
|
||||
int argumentCount;
|
||||
} NodeFnCall;
|
||||
|
||||
typedef struct NodePath {
|
||||
NodeType type;
|
||||
Node* preClause;
|
||||
Node* postClause;
|
||||
Node* condition;
|
||||
Node* thenPath;
|
||||
Node* elsePath;
|
||||
} NodePath;
|
||||
|
||||
typedef struct NodeIncrement {
|
||||
NodeType type;
|
||||
Literal identifier;
|
||||
int increment;
|
||||
} NodeIncrement;
|
||||
|
||||
typedef struct NodeImport {
|
||||
NodeType type;
|
||||
Literal identifier;
|
||||
Literal alias;
|
||||
} NodeImport;
|
||||
|
||||
typedef struct NodeIndex {
|
||||
NodeType type;
|
||||
Node* first;
|
||||
Node* second;
|
||||
Node* third;
|
||||
} NodeIndex;
|
||||
|
||||
union _node {
|
||||
NodeType type;
|
||||
NodeLiteral atomic;
|
||||
NodeUnary unary;
|
||||
NodeBinary binary;
|
||||
NodeGrouping grouping;
|
||||
NodeBlock block;
|
||||
NodeCompound compound;
|
||||
NodePair pair;
|
||||
NodeVarDecl varDecl;
|
||||
NodeFnDecl fnDecl;
|
||||
NodeFnCollection fnCollection;
|
||||
NodeFnCall fnCall;
|
||||
NodePath path;
|
||||
NodeIncrement increment;
|
||||
NodeImport import;
|
||||
NodeIndex index;
|
||||
};
|
||||
|
||||
TOY_API void freeNode(Node* node);
|
||||
|
||||
void emitNodeLiteral(Node** nodeHandle, Literal literal);
|
||||
void emitNodeUnary(Node** nodeHandle, Opcode opcode, Node* child);
|
||||
void emitNodeBinary(Node** nodeHandle, Node* rhs, Opcode opcode); //handled node becomes lhs
|
||||
void emitNodeGrouping(Node** nodeHandle);
|
||||
void emitNodeBlock(Node** nodeHandle);
|
||||
void emitNodeCompound(Node** nodeHandle, LiteralType literalType);
|
||||
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, int argumentCount);
|
||||
void emitNodeFnCollection(Node** nodeHandle);
|
||||
void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath);
|
||||
void emitNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment);
|
||||
void emitNodePostfixIncrement(Node** nodeHandle, Literal identifier, int increment);
|
||||
void emitNodeImport(Node** nodeHandle, NodeType mode, Literal identifier, Literal alias);
|
||||
void emitNodeIndex(Node** nodeHandle, Node* first, Node* second, Node* third);
|
||||
void emitNodeDot(Node** nodeHandle, Node* first);
|
||||
330
source/parser.c
330
source/parser.c
@@ -106,7 +106,7 @@ typedef enum {
|
||||
PREC_PRIMARY,
|
||||
} PrecedenceRule;
|
||||
|
||||
typedef Opcode (*ParseFn)(Parser* parser, Node** nodeHandle);
|
||||
typedef Opcode (*ParseFn)(Parser* parser, ASTNode** nodeHandle);
|
||||
|
||||
typedef struct {
|
||||
ParseFn prefix;
|
||||
@@ -117,12 +117,12 @@ typedef struct {
|
||||
ParseRule parseRules[];
|
||||
|
||||
//forward declarations
|
||||
static void declaration(Parser* parser, Node** nodeHandle);
|
||||
static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule rule);
|
||||
static void declaration(Parser* parser, ASTNode** nodeHandle);
|
||||
static void parsePrecedence(Parser* parser, ASTNode** nodeHandle, PrecedenceRule rule);
|
||||
static Literal readTypeToLiteral(Parser* parser);
|
||||
|
||||
//the expression rules
|
||||
static Opcode asType(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode asType(Parser* parser, ASTNode** nodeHandle) {
|
||||
Literal literal = readTypeToLiteral(parser);
|
||||
|
||||
if (!IS_TYPE(literal)) {
|
||||
@@ -131,35 +131,35 @@ static Opcode asType(Parser* parser, Node** nodeHandle) {
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
|
||||
freeLiteral(literal);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode typeOf(Parser* parser, Node** nodeHandle) {
|
||||
Node* rhs = NULL;
|
||||
static Opcode typeOf(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* rhs = NULL;
|
||||
parsePrecedence(parser, &rhs, PREC_TERNARY);
|
||||
emitNodeUnary(nodeHandle, OP_TYPE_OF, rhs);
|
||||
emitASTNodeUnary(nodeHandle, OP_TYPE_OF, rhs);
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode compound(Parser* parser, ASTNode** nodeHandle) {
|
||||
//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;
|
||||
ASTNode* array = NULL;
|
||||
ASTNode* 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_BRACKET_RIGHT, "Expected ']' at the end of empty dictionary definition");
|
||||
//emit an empty dictionary and finish
|
||||
emitNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
emitASTNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -169,8 +169,8 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
|
||||
iterations++;
|
||||
|
||||
Node* left = NULL;
|
||||
Node* right = NULL;
|
||||
ASTNode* left = NULL;
|
||||
ASTNode* right = NULL;
|
||||
|
||||
//store the left
|
||||
parsePrecedence(parser, &left, PREC_PRIMARY);
|
||||
@@ -197,7 +197,7 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
|
||||
//init the dictionary
|
||||
if (!dictionary) {
|
||||
emitNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
emitASTNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
}
|
||||
|
||||
//grow the node if needed
|
||||
@@ -205,11 +205,11 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = dictionary->compound.capacity;
|
||||
|
||||
dictionary->compound.capacity = GROW_CAPACITY(oldCapacity);
|
||||
dictionary->compound.nodes = GROW_ARRAY(Node, dictionary->compound.nodes, oldCapacity, dictionary->compound.capacity);
|
||||
dictionary->compound.nodes = GROW_ARRAY(ASTNode, dictionary->compound.nodes, oldCapacity, dictionary->compound.capacity);
|
||||
}
|
||||
|
||||
//store the left and right in the node
|
||||
setNodePair(&dictionary->compound.nodes[dictionary->compound.count++], left, right);
|
||||
setASTNodePair(&dictionary->compound.nodes[dictionary->compound.count++], left, right);
|
||||
}
|
||||
//detect an array
|
||||
else {
|
||||
@@ -222,7 +222,7 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
|
||||
//init the array
|
||||
if (!array) {
|
||||
emitNodeCompound(&array, LITERAL_ARRAY);
|
||||
emitASTNodeCompound(&array, LITERAL_ARRAY);
|
||||
}
|
||||
|
||||
//grow the node if needed
|
||||
@@ -230,12 +230,12 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = array->compound.capacity;
|
||||
|
||||
array->compound.capacity = GROW_CAPACITY(oldCapacity);
|
||||
array->compound.nodes = GROW_ARRAY(Node, array->compound.nodes, oldCapacity, array->compound.capacity);
|
||||
array->compound.nodes = GROW_ARRAY(ASTNode, array->compound.nodes, oldCapacity, array->compound.capacity);
|
||||
}
|
||||
|
||||
//copy into the array, and manually free the temp node
|
||||
array->compound.nodes[array->compound.count++] = *left;
|
||||
FREE(Node, left);
|
||||
FREE(ASTNode, left);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
else {
|
||||
//both are null, must be an array (because reasons)
|
||||
emitNodeCompound(&array, LITERAL_ARRAY);
|
||||
emitASTNodeCompound(&array, LITERAL_ARRAY);
|
||||
(*nodeHandle) = array;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ static Opcode compound(Parser* parser, Node** nodeHandle) {
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode string(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode string(Parser* parser, ASTNode** nodeHandle) {
|
||||
//handle strings
|
||||
switch(parser->previous.type) {
|
||||
case TOKEN_LITERAL_STRING: {
|
||||
@@ -272,7 +272,7 @@ static Opcode string(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
Literal literal = TO_STRING_LITERAL(copyString(parser->previous.lexeme, length), length);
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
freeLiteral(literal);
|
||||
return OP_EOF;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ static Opcode string(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
static Opcode grouping(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode grouping(Parser* parser, ASTNode** nodeHandle) {
|
||||
//handle groupings with ()
|
||||
switch(parser->previous.type) {
|
||||
case TOKEN_PAREN_LEFT: {
|
||||
@@ -293,7 +293,7 @@ static Opcode grouping(Parser* parser, Node** nodeHandle) {
|
||||
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of grouping");
|
||||
|
||||
//process the result without optimisations
|
||||
emitNodeGrouping(nodeHandle);
|
||||
emitASTNodeGrouping(nodeHandle);
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ static Opcode grouping(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
static Opcode binary(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode binary(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
//binary() is an infix rule - so only get the RHS of the operator
|
||||
@@ -412,15 +412,15 @@ static Opcode binary(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
static Opcode unary(Parser* parser, Node** nodeHandle) {
|
||||
Node* tmpNode = NULL;
|
||||
static Opcode unary(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* tmpNode = NULL;
|
||||
|
||||
if (parser->previous.type == TOKEN_MINUS) {
|
||||
//temp handle to potentially negate values
|
||||
parsePrecedence(parser, &tmpNode, PREC_TERNARY); //can be a literal
|
||||
|
||||
//check for negative literals (optimisation)
|
||||
if (tmpNode->type == NODE_LITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) {
|
||||
if (tmpNode->type == AST_NODELITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) {
|
||||
//negate directly, if int or float
|
||||
Literal lit = tmpNode->atomic.literal;
|
||||
|
||||
@@ -439,13 +439,13 @@ static Opcode unary(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//check for negated boolean errors
|
||||
if (tmpNode->type == NODE_LITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) {
|
||||
if (tmpNode->type == AST_NODELITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) {
|
||||
error(parser, parser->previous, "Negative booleans are not allowed");
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
//actually emit the negation
|
||||
emitNodeUnary(nodeHandle, OP_NEGATE, tmpNode);
|
||||
emitASTNodeUnary(nodeHandle, OP_NEGATE, tmpNode);
|
||||
}
|
||||
|
||||
else if (parser->previous.type == TOKEN_NOT) {
|
||||
@@ -453,7 +453,7 @@ static Opcode unary(Parser* parser, Node** nodeHandle) {
|
||||
parsePrecedence(parser, &tmpNode, PREC_CALL); //can be a literal
|
||||
|
||||
//check for inverted booleans
|
||||
if (tmpNode->type == NODE_LITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) {
|
||||
if (tmpNode->type == AST_NODELITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) {
|
||||
//negate directly, if int or float
|
||||
Literal lit = tmpNode->atomic.literal;
|
||||
|
||||
@@ -466,13 +466,13 @@ static Opcode unary(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//check for inverted number errors
|
||||
if (tmpNode->type == NODE_LITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) {
|
||||
if (tmpNode->type == AST_NODELITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) {
|
||||
error(parser, parser->previous, "Inverted numbers are not allowed");
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
//actually emit the negation
|
||||
emitNodeUnary(nodeHandle, OP_INVERT, tmpNode);
|
||||
emitASTNodeUnary(nodeHandle, OP_INVERT, tmpNode);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -483,40 +483,40 @@ static Opcode unary(Parser* parser, Node** nodeHandle) {
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode atomic(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode atomic(Parser* parser, ASTNode** nodeHandle) {
|
||||
switch(parser->previous.type) {
|
||||
case TOKEN_NULL:
|
||||
emitNodeLiteral(nodeHandle, TO_NULL_LITERAL);
|
||||
emitASTNodeLiteral(nodeHandle, TO_NULL_LITERAL);
|
||||
return OP_EOF;
|
||||
|
||||
case TOKEN_LITERAL_TRUE:
|
||||
emitNodeLiteral(nodeHandle, TO_BOOLEAN_LITERAL(true));
|
||||
emitASTNodeLiteral(nodeHandle, TO_BOOLEAN_LITERAL(true));
|
||||
return OP_EOF;
|
||||
|
||||
case TOKEN_LITERAL_FALSE:
|
||||
emitNodeLiteral(nodeHandle, TO_BOOLEAN_LITERAL(false));
|
||||
emitASTNodeLiteral(nodeHandle, TO_BOOLEAN_LITERAL(false));
|
||||
return OP_EOF;
|
||||
|
||||
case TOKEN_LITERAL_INTEGER: {
|
||||
int value = 0;
|
||||
sscanf(parser->previous.lexeme, "%d", &value);
|
||||
emitNodeLiteral(nodeHandle, TO_INTEGER_LITERAL(value));
|
||||
emitASTNodeLiteral(nodeHandle, TO_INTEGER_LITERAL(value));
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
case TOKEN_LITERAL_FLOAT: {
|
||||
float value = 0;
|
||||
sscanf(parser->previous.lexeme, "%f", &value);
|
||||
emitNodeLiteral(nodeHandle, TO_FLOAT_LITERAL(value));
|
||||
emitASTNodeLiteral(nodeHandle, TO_FLOAT_LITERAL(value));
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
case TOKEN_TYPE: {
|
||||
if (match(parser, TOKEN_CONST)) {
|
||||
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_TYPE, true));
|
||||
emitASTNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_TYPE, true));
|
||||
}
|
||||
else {
|
||||
emitNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_TYPE, false));
|
||||
emitASTNodeLiteral(nodeHandle, TO_TYPE_LITERAL(LITERAL_TYPE, false));
|
||||
}
|
||||
|
||||
return OP_EOF;
|
||||
@@ -528,7 +528,7 @@ static Opcode atomic(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
static Opcode identifier(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode identifier(Parser* parser, ASTNode** nodeHandle) {
|
||||
//make a copy of the string
|
||||
Token identifierToken = parser->previous;
|
||||
|
||||
@@ -548,39 +548,39 @@ static Opcode identifier(Parser* parser, Node** nodeHandle) {
|
||||
char* cpy = copyString(identifierToken.lexeme, length);
|
||||
Literal identifier = _toIdentifierLiteral(cpy, length); //BUGFIX: use this instead of the macro
|
||||
|
||||
emitNodeLiteral(nodeHandle, identifier);
|
||||
emitASTNodeLiteral(nodeHandle, identifier);
|
||||
|
||||
freeLiteral(identifier); //don't leave it hanging
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode castingPrefix(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode castingPrefix(Parser* parser, ASTNode** nodeHandle) {
|
||||
switch(parser->previous.type) {
|
||||
case TOKEN_BOOLEAN: {
|
||||
Literal literal = TO_TYPE_LITERAL(LITERAL_BOOLEAN, false);
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
freeLiteral(literal);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_INTEGER: {
|
||||
Literal literal = TO_TYPE_LITERAL(LITERAL_INTEGER, false);
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
freeLiteral(literal);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_FLOAT: {
|
||||
Literal literal = TO_TYPE_LITERAL(LITERAL_FLOAT, false);
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
freeLiteral(literal);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_STRING: {
|
||||
Literal literal = TO_TYPE_LITERAL(LITERAL_STRING, false);
|
||||
emitNodeLiteral(nodeHandle, literal);
|
||||
emitASTNodeLiteral(nodeHandle, literal);
|
||||
freeLiteral(literal);
|
||||
}
|
||||
break;
|
||||
@@ -593,7 +593,7 @@ static Opcode castingPrefix(Parser* parser, Node** nodeHandle) {
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode castingInfix(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode castingInfix(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
switch(parser->previous.type) {
|
||||
@@ -626,67 +626,67 @@ static Opcode castingInfix(Parser* parser, Node** nodeHandle) {
|
||||
return OP_TYPE_CAST;
|
||||
}
|
||||
|
||||
static Opcode incrementPrefix(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode incrementPrefix(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
emitNodePrefixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
emitASTNodePrefixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
|
||||
freeNode(node);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode incrementInfix(Parser* parser, Node** nodeHandle) {
|
||||
Node* node = NULL;
|
||||
static Opcode incrementInfix(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
advance(parser);
|
||||
|
||||
emitNodePostfixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
emitASTNodePostfixIncrement(nodeHandle, node->atomic.literal, 1);
|
||||
|
||||
freeNode(node);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode decrementPrefix(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode decrementPrefix(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
identifier(parser, &node); //weird
|
||||
|
||||
emitNodePrefixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
emitASTNodePrefixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
|
||||
freeNode(node);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode decrementInfix(Parser* parser, Node** nodeHandle) {
|
||||
Node* node = NULL;
|
||||
static Opcode decrementInfix(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* node = NULL;
|
||||
identifier(parser, &node);
|
||||
|
||||
advance(parser);
|
||||
|
||||
emitNodePostfixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
emitASTNodePostfixIncrement(nodeHandle, node->atomic.literal, -1);
|
||||
|
||||
freeNode(node);
|
||||
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode fnCall(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode fnCall(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser); //skip the left paren
|
||||
|
||||
//binary() is an infix rule - so only get the RHS of the operator
|
||||
switch(parser->previous.type) {
|
||||
//arithmetic
|
||||
case TOKEN_PAREN_LEFT: {
|
||||
Node* arguments = NULL;
|
||||
emitNodeFnCollection(&arguments);
|
||||
ASTNode* arguments = NULL;
|
||||
emitASTNodeFnCollection(&arguments);
|
||||
|
||||
//if there's arguments
|
||||
if (!match(parser, TOKEN_PAREN_RIGHT)) {
|
||||
@@ -697,20 +697,20 @@ static Opcode fnCall(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = arguments->fnCollection.capacity;
|
||||
|
||||
arguments->fnCollection.capacity = GROW_CAPACITY(oldCapacity);
|
||||
arguments->fnCollection.nodes = GROW_ARRAY(Node, arguments->fnCollection.nodes, oldCapacity, arguments->fnCollection.capacity);
|
||||
arguments->fnCollection.nodes = GROW_ARRAY(ASTNode, arguments->fnCollection.nodes, oldCapacity, arguments->fnCollection.capacity);
|
||||
}
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
parsePrecedence(parser, &node, PREC_TERNARY);
|
||||
arguments->fnCollection.nodes[arguments->fnCollection.count++] = *node;
|
||||
FREE(Node, node);
|
||||
FREE(ASTNode, node);
|
||||
} while(match(parser, TOKEN_COMMA));
|
||||
|
||||
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of argument list");
|
||||
}
|
||||
|
||||
//emit the call
|
||||
emitFnCall(nodeHandle, arguments, arguments->fnCollection.count);
|
||||
emitASTFnCall(nodeHandle, arguments, arguments->fnCollection.count);
|
||||
|
||||
return OP_FN_CALL;
|
||||
}
|
||||
@@ -724,19 +724,19 @@ static Opcode fnCall(Parser* parser, Node** nodeHandle) {
|
||||
return OP_EOF;
|
||||
}
|
||||
|
||||
static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode indexAccess(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser);
|
||||
|
||||
//val[first : second : third]
|
||||
|
||||
Node* first = NULL;
|
||||
Node* second = NULL;
|
||||
Node* third = NULL;
|
||||
ASTNode* first = NULL;
|
||||
ASTNode* second = NULL;
|
||||
ASTNode* third = NULL;
|
||||
|
||||
//booleans indicate blank slice indexing
|
||||
emitNodeLiteral(&first, TO_BOOLEAN_LITERAL(true));
|
||||
emitNodeLiteral(&second, TO_BOOLEAN_LITERAL(true));
|
||||
emitNodeLiteral(&third, TO_BOOLEAN_LITERAL(true));
|
||||
emitASTNodeLiteral(&first, TO_BOOLEAN_LITERAL(true));
|
||||
emitASTNodeLiteral(&second, TO_BOOLEAN_LITERAL(true));
|
||||
emitASTNodeLiteral(&third, TO_BOOLEAN_LITERAL(true));
|
||||
|
||||
bool readFirst = false; //pattern matching is bullcrap
|
||||
|
||||
@@ -758,7 +758,7 @@ static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
|
||||
freeNode(third);
|
||||
third = NULL;
|
||||
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
emitASTNodeIndex(nodeHandle, first, second, third);
|
||||
return OP_INDEX;
|
||||
}
|
||||
|
||||
@@ -772,24 +772,24 @@ static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
|
||||
if (match(parser, TOKEN_BRACKET_RIGHT)) {
|
||||
freeNode(third);
|
||||
third = NULL;
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
emitASTNodeIndex(nodeHandle, first, second, third);
|
||||
return OP_INDEX;
|
||||
}
|
||||
|
||||
//eat the third
|
||||
freeNode(third);
|
||||
parsePrecedence(parser, &third, PREC_TERNARY);
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
emitASTNodeIndex(nodeHandle, first, second, third);
|
||||
|
||||
consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' in index notation");
|
||||
|
||||
return OP_INDEX;
|
||||
}
|
||||
|
||||
static Opcode dot(Parser* parser, Node** nodeHandle) {
|
||||
static Opcode dot(Parser* parser, ASTNode** nodeHandle) {
|
||||
advance(parser); //for the dot
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
|
||||
parsePrecedence(parser, &node, PREC_CALL);
|
||||
|
||||
@@ -901,7 +901,7 @@ ParseRule* getRule(TokenType type) {
|
||||
}
|
||||
|
||||
//constant folding
|
||||
static bool calcStaticBinaryArithmetic(Parser* parser, Node** nodeHandle) {
|
||||
static bool calcStaticBinaryArithmetic(Parser* parser, ASTNode** nodeHandle) {
|
||||
switch((*nodeHandle)->binary.opcode) {
|
||||
case OP_ADDITION:
|
||||
case OP_SUBTRACTION:
|
||||
@@ -921,16 +921,16 @@ static bool calcStaticBinaryArithmetic(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//recurse to the left and right
|
||||
if ((*nodeHandle)->binary.left->type == NODE_BINARY) {
|
||||
if ((*nodeHandle)->binary.left->type == AST_NODEBINARY) {
|
||||
calcStaticBinaryArithmetic(parser, &(*nodeHandle)->binary.left);
|
||||
}
|
||||
|
||||
if ((*nodeHandle)->binary.right->type == NODE_BINARY) {
|
||||
if ((*nodeHandle)->binary.right->type == AST_NODEBINARY) {
|
||||
calcStaticBinaryArithmetic(parser, &(*nodeHandle)->binary.right);
|
||||
}
|
||||
|
||||
//make sure left and right are both literals
|
||||
if (!((*nodeHandle)->binary.left->type == NODE_LITERAL && (*nodeHandle)->binary.right->type == NODE_LITERAL)) {
|
||||
if (!((*nodeHandle)->binary.left->type == AST_NODELITERAL && (*nodeHandle)->binary.right->type == AST_NODELITERAL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1076,13 +1076,13 @@ static bool calcStaticBinaryArithmetic(Parser* parser, Node** nodeHandle) {
|
||||
freeNode((*nodeHandle)->binary.left);
|
||||
freeNode((*nodeHandle)->binary.right);
|
||||
|
||||
(*nodeHandle)->type = NODE_LITERAL;
|
||||
(*nodeHandle)->type = AST_NODELITERAL;
|
||||
(*nodeHandle)->atomic.literal = result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule rule) {
|
||||
static void parsePrecedence(Parser* parser, ASTNode** nodeHandle, PrecedenceRule rule) {
|
||||
//every valid expression has a prefix rule
|
||||
advance(parser);
|
||||
ParseFn prefixRule = getRule(parser->previous.type)->prefix;
|
||||
@@ -1106,7 +1106,7 @@ static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule ru
|
||||
return;
|
||||
}
|
||||
|
||||
Node* rhsNode = NULL;
|
||||
ASTNode* rhsNode = NULL;
|
||||
const Opcode opcode = infixRule(parser, &rhsNode); //NOTE: infix rule must advance the parser
|
||||
|
||||
if (opcode == OP_EOF) {
|
||||
@@ -1115,7 +1115,7 @@ static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule ru
|
||||
return; //we're done here
|
||||
}
|
||||
|
||||
emitNodeBinary(nodeHandle, rhsNode, opcode);
|
||||
emitASTNodeBinary(nodeHandle, rhsNode, opcode);
|
||||
|
||||
if (!calcStaticBinaryArithmetic(parser, nodeHandle)) {
|
||||
return;
|
||||
@@ -1129,15 +1129,15 @@ static void parsePrecedence(Parser* parser, Node** nodeHandle, PrecedenceRule ru
|
||||
}
|
||||
|
||||
//expressions
|
||||
static void expression(Parser* parser, Node** nodeHandle) {
|
||||
static void expression(Parser* parser, ASTNode** nodeHandle) {
|
||||
//delegate to the pratt table for expression precedence
|
||||
parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT);
|
||||
}
|
||||
|
||||
//statements
|
||||
static void blockStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void blockStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//init
|
||||
emitNodeBlock(nodeHandle);
|
||||
emitASTNodeBlock(nodeHandle);
|
||||
|
||||
//sub-scope, compile it and push it up in a node
|
||||
while (!match(parser, TOKEN_BRACE_RIGHT)) {
|
||||
@@ -1145,10 +1145,10 @@ static void blockStmt(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = (*nodeHandle)->block.capacity;
|
||||
|
||||
(*nodeHandle)->block.capacity = GROW_CAPACITY(oldCapacity);
|
||||
(*nodeHandle)->block.nodes = GROW_ARRAY(Node, (*nodeHandle)->block.nodes, oldCapacity, (*nodeHandle)->block.capacity);
|
||||
(*nodeHandle)->block.nodes = GROW_ARRAY(ASTNode, (*nodeHandle)->block.nodes, oldCapacity, (*nodeHandle)->block.capacity);
|
||||
}
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
|
||||
//process the grammar rule for this line
|
||||
declaration(parser, &node);
|
||||
@@ -1160,23 +1160,23 @@ static void blockStmt(Parser* parser, Node** nodeHandle) {
|
||||
|
||||
//BUGFIX: statements no longer require an existing node
|
||||
((*nodeHandle)->block.nodes[(*nodeHandle)->block.count++]) = *node;
|
||||
FREE(Node, node); //simply free the tmp node
|
||||
FREE(ASTNode, node); //simply free the tmp node
|
||||
}
|
||||
}
|
||||
|
||||
static void printStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void printStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//set the node info
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
expression(parser, &node);
|
||||
emitNodeUnary(nodeHandle, OP_PRINT, node);
|
||||
emitASTNodeUnary(nodeHandle, OP_PRINT, node);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of print statement");
|
||||
}
|
||||
|
||||
static void assertStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void assertStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//set the node info
|
||||
(*nodeHandle) = ALLOCATE(Node, 1); //special case, because I'm lazy
|
||||
(*nodeHandle)->type = NODE_BINARY;
|
||||
(*nodeHandle) = ALLOCATE(ASTNode, 1); //special case, because I'm lazy
|
||||
(*nodeHandle)->type = AST_NODEBINARY;
|
||||
(*nodeHandle)->binary.opcode = OP_ASSERT;
|
||||
|
||||
parsePrecedence(parser, &((*nodeHandle)->binary.left), PREC_TERNARY);
|
||||
@@ -1186,10 +1186,10 @@ static void assertStmt(Parser* parser, Node** nodeHandle) {
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of assert statement");
|
||||
}
|
||||
|
||||
static void ifStmt(Parser* parser, Node** nodeHandle) {
|
||||
Node* condition = NULL;
|
||||
Node* thenPath = NULL;
|
||||
Node* elsePath = NULL;
|
||||
static void ifStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* condition = NULL;
|
||||
ASTNode* thenPath = NULL;
|
||||
ASTNode* elsePath = NULL;
|
||||
|
||||
//read the condition
|
||||
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of if clause");
|
||||
@@ -1204,12 +1204,12 @@ static void ifStmt(Parser* parser, Node** nodeHandle) {
|
||||
declaration(parser, &elsePath);
|
||||
}
|
||||
|
||||
emitNodePath(nodeHandle, NODE_PATH_IF, NULL, NULL, condition, thenPath, elsePath);
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_IF, NULL, NULL, condition, thenPath, elsePath);
|
||||
}
|
||||
|
||||
static void whileStmt(Parser* parser, Node** nodeHandle) {
|
||||
Node* condition = NULL;
|
||||
Node* thenPath = NULL;
|
||||
static void whileStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* condition = NULL;
|
||||
ASTNode* thenPath = NULL;
|
||||
|
||||
//read the condition
|
||||
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of while clause");
|
||||
@@ -1219,14 +1219,14 @@ static void whileStmt(Parser* parser, Node** nodeHandle) {
|
||||
consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of while clause");
|
||||
declaration(parser, &thenPath);
|
||||
|
||||
emitNodePath(nodeHandle, NODE_PATH_WHILE, NULL, NULL, condition, thenPath, NULL);
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_WHILE, NULL, NULL, condition, thenPath, NULL);
|
||||
}
|
||||
|
||||
static void forStmt(Parser* parser, Node** nodeHandle) {
|
||||
Node* preClause = NULL;
|
||||
Node* postClause = NULL;
|
||||
Node* condition = NULL;
|
||||
Node* thenPath = NULL;
|
||||
static void forStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* preClause = NULL;
|
||||
ASTNode* postClause = NULL;
|
||||
ASTNode* condition = NULL;
|
||||
ASTNode* thenPath = NULL;
|
||||
|
||||
//read the clauses
|
||||
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' at beginning of for clause");
|
||||
@@ -1242,24 +1242,24 @@ static void forStmt(Parser* parser, Node** nodeHandle) {
|
||||
//read the path
|
||||
declaration(parser, &thenPath);
|
||||
|
||||
emitNodePath(nodeHandle, NODE_PATH_FOR, preClause, postClause, condition, thenPath, NULL);
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_FOR, preClause, postClause, condition, thenPath, NULL);
|
||||
}
|
||||
|
||||
static void breakStmt(Parser* parser, Node** nodeHandle) {
|
||||
emitNodePath(nodeHandle, NODE_PATH_BREAK, NULL, NULL, NULL, NULL, NULL);
|
||||
static void breakStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_BREAK, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of break statement");
|
||||
}
|
||||
|
||||
static void continueStmt(Parser* parser, Node** nodeHandle) {
|
||||
emitNodePath(nodeHandle, NODE_PATH_CONTINUE, NULL, NULL, NULL, NULL, NULL);
|
||||
static void continueStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_CONTINUE, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of continue statement");
|
||||
}
|
||||
|
||||
static void returnStmt(Parser* parser, Node** nodeHandle) {
|
||||
Node* returnValues = NULL;
|
||||
emitNodeFnCollection(&returnValues);
|
||||
static void returnStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
ASTNode* returnValues = NULL;
|
||||
emitASTNodeFnCollection(&returnValues);
|
||||
|
||||
if (!match(parser, TOKEN_SEMICOLON)) {
|
||||
do { //loop for multiple returns (disabled later in the pipeline)
|
||||
@@ -1268,25 +1268,25 @@ static void returnStmt(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = returnValues->fnCollection.capacity;
|
||||
|
||||
returnValues->fnCollection.capacity = GROW_CAPACITY(oldCapacity);
|
||||
returnValues->fnCollection.nodes = GROW_ARRAY(Node, returnValues->fnCollection.nodes, oldCapacity, returnValues->fnCollection.capacity);
|
||||
returnValues->fnCollection.nodes = GROW_ARRAY(ASTNode, returnValues->fnCollection.nodes, oldCapacity, returnValues->fnCollection.capacity);
|
||||
}
|
||||
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
parsePrecedence(parser, &node, PREC_TERNARY);
|
||||
|
||||
returnValues->fnCollection.nodes[returnValues->fnCollection.count++] = *node;
|
||||
FREE(Node, node);
|
||||
FREE(ASTNode, node);
|
||||
} while(match(parser, TOKEN_COMMA));
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of return statement");
|
||||
}
|
||||
|
||||
emitNodePath(nodeHandle, NODE_PATH_RETURN, NULL, NULL, NULL, returnValues, NULL);
|
||||
emitASTNodePath(nodeHandle, AST_NODEPATH_RETURN, NULL, NULL, NULL, returnValues, NULL);
|
||||
}
|
||||
|
||||
static void importStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void importStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//read the identifier
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
advance(parser);
|
||||
identifier(parser, &node);
|
||||
|
||||
@@ -1306,7 +1306,7 @@ static void importStmt(Parser* parser, Node** nodeHandle) {
|
||||
freeNode(node);
|
||||
}
|
||||
|
||||
emitNodeImport(nodeHandle, NODE_IMPORT, idn, alias);
|
||||
emitASTNodeImport(nodeHandle, AST_NODEIMPORT, idn, alias);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of import statement");
|
||||
|
||||
@@ -1314,9 +1314,9 @@ static void importStmt(Parser* parser, Node** nodeHandle) {
|
||||
freeLiteral(alias);
|
||||
}
|
||||
|
||||
static void exportStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void exportStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//read the identifier
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
advance(parser);
|
||||
identifier(parser, &node);
|
||||
|
||||
@@ -1336,7 +1336,7 @@ static void exportStmt(Parser* parser, Node** nodeHandle) {
|
||||
freeNode(node);
|
||||
}
|
||||
|
||||
emitNodeImport(nodeHandle, NODE_EXPORT, idn, alias);
|
||||
emitASTNodeImport(nodeHandle, AST_NODEEXPORT, idn, alias);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of export statement");
|
||||
|
||||
@@ -1345,14 +1345,14 @@ static void exportStmt(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//precedence functions
|
||||
static void expressionStmt(Parser* parser, Node** nodeHandle) {
|
||||
static void expressionStmt(Parser* parser, ASTNode** nodeHandle) {
|
||||
//BUGFIX: check for empty statements
|
||||
if (match(parser, TOKEN_SEMICOLON)) {
|
||||
emitNodeLiteral(nodeHandle, TO_NULL_LITERAL);
|
||||
emitASTNodeLiteral(nodeHandle, TO_NULL_LITERAL);
|
||||
return;
|
||||
}
|
||||
|
||||
Node* ptr = NULL;
|
||||
ASTNode* ptr = NULL;
|
||||
expression(parser, &ptr);
|
||||
|
||||
if (ptr != NULL) {
|
||||
@@ -1362,7 +1362,7 @@ static void expressionStmt(Parser* parser, Node** nodeHandle) {
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at the end of expression statement");
|
||||
}
|
||||
|
||||
static void statement(Parser* parser, Node** nodeHandle) {
|
||||
static void statement(Parser* parser, ASTNode** nodeHandle) {
|
||||
//block
|
||||
if (match(parser, TOKEN_BRACE_LEFT)) {
|
||||
blockStmt(parser, nodeHandle);
|
||||
@@ -1523,7 +1523,7 @@ static Literal readTypeToLiteral(Parser* parser) {
|
||||
return literal;
|
||||
}
|
||||
|
||||
static void varDecl(Parser* parser, Node** nodeHandle) {
|
||||
static void varDecl(Parser* parser, ASTNode** nodeHandle) {
|
||||
//read the identifier
|
||||
consume(parser, TOKEN_IDENTIFIER, "Expected identifier after var keyword");
|
||||
Token identifierToken = parser->previous;
|
||||
@@ -1550,24 +1550,24 @@ static void varDecl(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//variable definition is an expression
|
||||
Node* expressionNode = NULL;
|
||||
ASTNode* expressionNode = NULL;
|
||||
if (match(parser, TOKEN_ASSIGN)) {
|
||||
expression(parser, &expressionNode);
|
||||
}
|
||||
else {
|
||||
//values are null by default
|
||||
emitNodeLiteral(&expressionNode, TO_NULL_LITERAL);
|
||||
emitASTNodeLiteral(&expressionNode, TO_NULL_LITERAL);
|
||||
}
|
||||
|
||||
//TODO: static type checking?
|
||||
|
||||
//declare it
|
||||
emitNodeVarDecl(nodeHandle, identifier, typeLiteral, expressionNode);
|
||||
emitASTNodeVarDecl(nodeHandle, identifier, typeLiteral, expressionNode);
|
||||
|
||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of var declaration");
|
||||
}
|
||||
|
||||
static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
static void fnDecl(Parser* parser, ASTNode** nodeHandle) {
|
||||
//read the identifier
|
||||
consume(parser, TOKEN_IDENTIFIER, "Expected identifier after fn keyword");
|
||||
Token identifierToken = parser->previous;
|
||||
@@ -1587,8 +1587,8 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
consume(parser, TOKEN_PAREN_LEFT, "Expected '(' after function identifier");
|
||||
|
||||
//for holding the array of arguments
|
||||
Node* argumentNode = NULL;
|
||||
emitNodeFnCollection(&argumentNode);
|
||||
ASTNode* argumentNode = NULL;
|
||||
emitASTNodeFnCollection(&argumentNode);
|
||||
|
||||
//read args
|
||||
if (!match(parser, TOKEN_PAREN_RIGHT)) {
|
||||
@@ -1618,15 +1618,15 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = argumentNode->fnCollection.capacity;
|
||||
|
||||
argumentNode->fnCollection.capacity = GROW_CAPACITY(oldCapacity);
|
||||
argumentNode->fnCollection.nodes = GROW_ARRAY(Node, argumentNode->fnCollection.nodes, oldCapacity, argumentNode->fnCollection.capacity);
|
||||
argumentNode->fnCollection.nodes = GROW_ARRAY(ASTNode, argumentNode->fnCollection.nodes, oldCapacity, argumentNode->fnCollection.capacity);
|
||||
}
|
||||
|
||||
//store the arg in the array
|
||||
Node* literalNode = NULL;
|
||||
emitNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
|
||||
ASTNode* literalNode = NULL;
|
||||
emitASTNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
|
||||
|
||||
argumentNode->fnCollection.nodes[argumentNode->fnCollection.count++] = *literalNode;
|
||||
FREE(Node, literalNode);
|
||||
FREE(ASTNode, literalNode);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1662,15 +1662,15 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = argumentNode->fnCollection.capacity;
|
||||
|
||||
argumentNode->fnCollection.capacity = GROW_CAPACITY(oldCapacity);
|
||||
argumentNode->fnCollection.nodes = GROW_ARRAY(Node, argumentNode->fnCollection.nodes, oldCapacity, argumentNode->fnCollection.capacity);
|
||||
argumentNode->fnCollection.nodes = GROW_ARRAY(ASTNode, argumentNode->fnCollection.nodes, oldCapacity, argumentNode->fnCollection.capacity);
|
||||
}
|
||||
|
||||
//store the arg in the array
|
||||
Node* literalNode = NULL;
|
||||
emitNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
|
||||
ASTNode* literalNode = NULL;
|
||||
emitASTNodeVarDecl(&literalNode, argIdentifier, argTypeLiteral, NULL);
|
||||
|
||||
argumentNode->fnCollection.nodes[argumentNode->fnCollection.count++] = *literalNode;
|
||||
FREE(Node, literalNode);
|
||||
FREE(ASTNode, literalNode);
|
||||
|
||||
} while (match(parser, TOKEN_COMMA)); //if comma is read, continue
|
||||
|
||||
@@ -1678,8 +1678,8 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
}
|
||||
|
||||
//read the return types, if present
|
||||
Node* returnNode = NULL;
|
||||
emitNodeFnCollection(&returnNode);
|
||||
ASTNode* returnNode = NULL;
|
||||
emitASTNodeFnCollection(&returnNode);
|
||||
|
||||
if (match(parser, TOKEN_COLON)) {
|
||||
do {
|
||||
@@ -1688,28 +1688,28 @@ static void fnDecl(Parser* parser, Node** nodeHandle) {
|
||||
int oldCapacity = returnNode->fnCollection.capacity;
|
||||
|
||||
returnNode->fnCollection.capacity = GROW_CAPACITY(oldCapacity);
|
||||
returnNode->fnCollection.nodes = GROW_ARRAY(Node, returnNode->fnCollection.nodes, oldCapacity, returnNode->fnCollection.capacity);
|
||||
returnNode->fnCollection.nodes = GROW_ARRAY(ASTNode, returnNode->fnCollection.nodes, oldCapacity, returnNode->fnCollection.capacity);
|
||||
}
|
||||
|
||||
Node* literalNode = NULL;
|
||||
emitNodeLiteral(&literalNode, readTypeToLiteral(parser));
|
||||
ASTNode* literalNode = NULL;
|
||||
emitASTNodeLiteral(&literalNode, readTypeToLiteral(parser));
|
||||
|
||||
returnNode->fnCollection.nodes[returnNode->fnCollection.count++] = *literalNode;
|
||||
FREE(Node, literalNode);
|
||||
FREE(ASTNode, literalNode);
|
||||
} while(match(parser, TOKEN_COMMA));
|
||||
}
|
||||
|
||||
//read the function body
|
||||
consume(parser, TOKEN_BRACE_LEFT, "Expected '{' after return list");
|
||||
|
||||
Node* blockNode = NULL;
|
||||
ASTNode* blockNode = NULL;
|
||||
blockStmt(parser, &blockNode);
|
||||
|
||||
//declare it
|
||||
emitNodeFnDecl(nodeHandle, identifier, argumentNode, returnNode, blockNode);
|
||||
emitASTNodeFnDecl(nodeHandle, identifier, argumentNode, returnNode, blockNode);
|
||||
}
|
||||
|
||||
static void declaration(Parser* parser, Node** nodeHandle) { //assume nodeHandle holds a blank node
|
||||
static void declaration(Parser* parser, ASTNode** nodeHandle) { //assume nodeHandle holds a blank node
|
||||
//variable declarations
|
||||
if (match(parser, TOKEN_VAR)) {
|
||||
varDecl(parser, nodeHandle);
|
||||
@@ -1742,14 +1742,14 @@ void freeParser(Parser* parser) {
|
||||
parser->current.type = TOKEN_NULL;
|
||||
}
|
||||
|
||||
Node* scanParser(Parser* parser) {
|
||||
ASTNode* scanParser(Parser* parser) {
|
||||
//check for EOF
|
||||
if (match(parser, TOKEN_EOF)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//returns nodes on the heap
|
||||
Node* node = NULL;
|
||||
ASTNode* node = NULL;
|
||||
|
||||
//process the grammar rule for this line
|
||||
declaration(parser, &node);
|
||||
@@ -1758,8 +1758,8 @@ Node* scanParser(Parser* parser) {
|
||||
synchronize(parser);
|
||||
//return an error node for this iteration
|
||||
freeNode(node);
|
||||
node = ALLOCATE(Node, 1);
|
||||
node->type = NODE_ERROR;
|
||||
node = ALLOCATE(ASTNode, 1);
|
||||
node->type = AST_NODEERROR;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "lexer.h"
|
||||
#include "node.h"
|
||||
#include "ast_node.h"
|
||||
|
||||
//DOCS: parsers are bound to a lexer, and turn the outputted tokens into AST nodes
|
||||
typedef struct {
|
||||
@@ -17,4 +17,4 @@ typedef struct {
|
||||
|
||||
TOY_API void initParser(Parser* parser, Lexer* lexer);
|
||||
TOY_API void freeParser(Parser* parser);
|
||||
TOY_API Node* scanParser(Parser* parser);
|
||||
TOY_API ASTNode* scanParser(Parser* parser);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "node.h"
|
||||
#include "ast_node.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "console_colors.h"
|
||||
@@ -12,8 +12,8 @@ int main() {
|
||||
|
||||
Literal literal = TO_STRING_LITERAL(copyString(str, strlen(str)), strlen(str));
|
||||
|
||||
Node* node;
|
||||
emitNodeLiteral(&node, literal);
|
||||
ASTNode* node;
|
||||
emitASTNodeLiteral(&node, literal);
|
||||
freeLiteral(literal);
|
||||
freeNode(node);
|
||||
}
|
||||
@@ -23,27 +23,27 @@ int main() {
|
||||
char* idn = "foobar";
|
||||
char* str = "hello world";
|
||||
|
||||
Node* dictionary;
|
||||
Node* left;
|
||||
Node* right;
|
||||
ASTNode* dictionary;
|
||||
ASTNode* left;
|
||||
ASTNode* right;
|
||||
|
||||
Literal identifier = TO_IDENTIFIER_LITERAL(copyString(idn, strlen(idn)), strlen(idn));
|
||||
Literal string = TO_STRING_LITERAL(copyString(str, strlen(str)), strlen(str));
|
||||
|
||||
emitNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
emitNodeLiteral(&left, identifier);
|
||||
emitNodeLiteral(&right, string);
|
||||
emitASTNodeCompound(&dictionary, LITERAL_DICTIONARY);
|
||||
emitASTNodeLiteral(&left, identifier);
|
||||
emitASTNodeLiteral(&right, string);
|
||||
|
||||
//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);
|
||||
dictionary->compound.nodes = GROW_ARRAY(ASTNode, dictionary->compound.nodes, oldCapacity, dictionary->compound.capacity);
|
||||
}
|
||||
|
||||
//store the left and right in the node
|
||||
setNodePair(&dictionary->compound.nodes[dictionary->compound.count++], left, right);
|
||||
setASTNodePair(&dictionary->compound.nodes[dictionary->compound.count++], left, right);
|
||||
|
||||
//the real test
|
||||
freeNode(dictionary);
|
||||
@@ -65,7 +65,7 @@ int main() {
|
||||
initParser(&parser, &lexer);
|
||||
initCompiler(&compiler);
|
||||
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
|
||||
//write
|
||||
writeCompiler(&compiler, node);
|
||||
@@ -95,9 +95,9 @@ int main() {
|
||||
initParser(&parser, &lexer);
|
||||
initCompiler(&compiler);
|
||||
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
while (node != NULL) {
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
fprintf(stderr, ERROR "ERROR: Error node found" RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -60,10 +60,10 @@ unsigned char* compileString(char* source, size_t* size) {
|
||||
initCompiler(&compiler);
|
||||
|
||||
//run the parser until the end of the source
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
while(node != NULL) {
|
||||
//pack up and leave
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
printf(ERROR "error node detected\n" RESET);
|
||||
freeNode(node);
|
||||
freeCompiler(&compiler);
|
||||
@@ -138,7 +138,7 @@ int main() {
|
||||
initCompiler(&compiler);
|
||||
initInterpreter(&interpreter);
|
||||
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
|
||||
//write
|
||||
writeCompiler(&compiler, node);
|
||||
|
||||
@@ -62,10 +62,10 @@ unsigned char* compileString(char* source, size_t* size) {
|
||||
initCompiler(&compiler);
|
||||
|
||||
//run the parser until the end of the source
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
while(node != NULL) {
|
||||
//pack up and leave
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
printf(ERROR "error node detected\n" RESET);
|
||||
freeNode(node);
|
||||
freeCompiler(&compiler);
|
||||
|
||||
@@ -64,21 +64,21 @@ int main() {
|
||||
initLexer(&lexer, source);
|
||||
initParser(&parser, &lexer);
|
||||
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
|
||||
//inspect the node
|
||||
if (node == NULL) {
|
||||
fprintf(stderr, ERROR "ERROR: Node is null" RESET);
|
||||
fprintf(stderr, ERROR "ERROR: ASTNode is null" RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (node->type != NODE_UNARY || node->unary.opcode != OP_PRINT) {
|
||||
fprintf(stderr, ERROR "ERROR: Node is not a print instruction" RESET);
|
||||
if (node->type != AST_NODEUNARY || node->unary.opcode != OP_PRINT) {
|
||||
fprintf(stderr, ERROR "ERROR: ASTNode is not a print instruction" RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (node->unary.child->type != NODE_LITERAL || !IS_NULL(node->unary.child->atomic.literal)) {
|
||||
fprintf(stderr, ERROR "ERROR: Node to be printed is not a null value" RESET);
|
||||
if (node->unary.child->type != AST_NODELITERAL || !IS_NULL(node->unary.child->atomic.literal)) {
|
||||
fprintf(stderr, ERROR "ERROR: ASTNode to be printed is not a null value" RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -98,10 +98,10 @@ int main() {
|
||||
initLexer(&lexer, source);
|
||||
initParser(&parser, &lexer);
|
||||
|
||||
Node* node = scanParser(&parser);
|
||||
ASTNode* node = scanParser(&parser);
|
||||
|
||||
while (node != NULL) {
|
||||
if (node->type == NODE_ERROR) {
|
||||
if (node->type == AST_NODEERROR) {
|
||||
fprintf(stderr, ERROR "ERROR: Error node detected" RESET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user