diff --git a/scripts/example.toy b/scripts/example.toy index ac7d3ee..58f01e1 100644 --- a/scripts/example.toy +++ b/scripts/example.toy @@ -6,50 +6,3 @@ print 42; print 3.14; print -69; print -4.20; -print "hello world"; -print "hello world"; -print "hello world"; -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print "hello world"; -print "hello world"; -print "hello world"; -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print "hello world"; -print "hello world"; -print "hello world"; -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print "hello world"; -print "hello world"; -print "hello world"; -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print "hello world"; -print "hello world"; -print "hello world"; diff --git a/source/debug.c b/source/debug.c index b315330..5f01c67 100644 --- a/source/debug.c +++ b/source/debug.c @@ -20,6 +20,7 @@ void initCommand(int argc, const char* argv[]) { command.filename = NULL; command.source = NULL; command.verbose = false; + command.optimize = 1; for (int i = 1; i < argc; i++) { //start at 1 to skip the program name if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { @@ -49,6 +50,11 @@ void initCommand(int argc, const char* argv[]) { continue; } + if (!strncmp(argv[i], "-O", 2)) { + sscanf(argv[i], "-O%d", &command.optimize); + continue; + } + command.error = true; } @@ -59,7 +65,7 @@ void initCommand(int argc, const char* argv[]) { } void usageCommand(int argc, const char* argv[]) { - printf("Usage: %s [-h | -v | [-d][-f filename | -i source]]\n\n", argv[0]); + printf("Usage: %s [-h | -v | [-OX][-d][-f filename | -i source]]\n\n", argv[0]); } void helpCommand(int argc, const char* argv[]) { @@ -70,6 +76,7 @@ void helpCommand(int argc, const char* argv[]) { printf("-f | --file filename\tParse and execute the source file.\n"); printf("-i | --input source\tParse and execute this given string of source code.\n"); printf("-d | --debug\t\tBe verbose when operating.\n"); + printf("-OX\t\t\tUse level X optimization (default 1)\n"); } void copyrightCommand(int argc, const char* argv[]) { @@ -194,7 +201,7 @@ void dissectBytecode(const char* tb, int size) { switch (opcode) { case OP_PRINT: - printf("print:\n"); + printf("print\n"); break; case OP_LITERAL: { diff --git a/source/debug.h b/source/debug.h index 08e835e..d45b8de 100644 --- a/source/debug.h +++ b/source/debug.h @@ -10,6 +10,7 @@ typedef struct { char* filename; char* source; bool verbose; + int optimize; } Command; extern Command command; diff --git a/source/node.c b/source/node.c index 18eef81..145a505 100644 --- a/source/node.c +++ b/source/node.c @@ -46,7 +46,7 @@ void printNode(Node* node) { printf("literal:"); printLiteral(node->atomic.literal); break; - + case NODE_UNARY: printf("unary:"); printNode(node->unary.child); diff --git a/source/node.h b/source/node.h index 058e044..c84a894 100644 --- a/source/node.h +++ b/source/node.h @@ -7,6 +7,7 @@ typedef union _node Node; typedef enum NodeType { + NODE_ERROR, NODE_LITERAL, //a simple value NODE_UNARY, //one child NODE_BINARY, //two children, left and right diff --git a/source/parser.c b/source/parser.c index 4a3f417..c02d494 100644 --- a/source/parser.c +++ b/source/parser.c @@ -1,4 +1,6 @@ #include "parser.h" + +#include "debug.h" #include "common.h" #include "memory.h" @@ -134,29 +136,36 @@ static void unary(Parser* parser, Node** nodeHandle, bool canBeAssigned) { case TOKEN_MINUS: { //temp handle to potentially negate values Node* tmpNode = NULL; - parsePrecedence(parser, &tmpNode, PREC_TERNARY); + parsePrecedence(parser, &tmpNode, PREC_TERNARY); //can be a literal - //check for literals - if (tmpNode->type == NODE_LITERAL) { + //check for negative literals (optimisation) + if (command.optimize >= 1 && tmpNode->type == NODE_LITERAL) { //negate directly, if int or float Literal lit = tmpNode->atomic.literal; if (IS_INTEGER(lit)) { - lit = TO_INTEGER_LITERAL( -AS_INTEGER(lit) ); + lit = TO_INTEGER_LITERAL(-AS_INTEGER(lit)); } if (IS_FLOAT(lit)) { - lit = TO_FLOAT_LITERAL( -AS_FLOAT(lit) ); + lit = TO_FLOAT_LITERAL(-AS_FLOAT(lit)); } tmpNode->atomic.literal = lit; *nodeHandle = tmpNode; + + break; } - else { - //process normally + + //process the literal without optimizations + if (tmpNode->type == NODE_LITERAL) { emitNodeUnary(nodeHandle, OP_NEGATE); - parsePrecedence(parser, nodeHandle, PREC_TERNARY); + nodeHandle = &((*nodeHandle)->unary.child); //re-align after append + (*nodeHandle) = tmpNode; //set negate's child to the literal + break; } + + error(parser, parser->previous, "Unexpected token passed to unary minus precedence rule"); } break; @@ -200,7 +209,7 @@ static void atomic(Parser* parser, Node** nodeHandle, bool canBeAssigned) { ParseRule parseRules[] = { //must match the token types //types - {atomic, NULL, PREC_NONE},// TOKEN_NULL, + {atomic, NULL, PREC_PRIMARY},// TOKEN_NULL, {NULL, NULL, PREC_NONE},// TOKEN_BOOLEAN, {NULL, NULL, PREC_NONE},// TOKEN_INTEGER, {NULL, NULL, PREC_NONE},// TOKEN_FLOAT, @@ -234,15 +243,15 @@ ParseRule parseRules[] = { //must match the token types //literal values {NULL, NULL, PREC_NONE},// TOKEN_IDENTIFIER, - {atomic, NULL, PREC_NONE},// TOKEN_LITERAL_TRUE, - {atomic, NULL, PREC_NONE},// TOKEN_LITERAL_FALSE, - {atomic, NULL, PREC_NONE},// TOKEN_LITERAL_INTEGER, - {atomic, NULL, PREC_NONE},// TOKEN_LITERAL_FLOAT, + {atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_TRUE, + {atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_FALSE, + {atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_INTEGER, + {atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_FLOAT, {string, NULL, PREC_PRIMARY},// TOKEN_LITERAL_STRING, //math operators {NULL, NULL, PREC_NONE},// TOKEN_PLUS, - {unary, NULL, PREC_NONE},// TOKEN_MINUS, + {unary, NULL, PREC_UNARY},// TOKEN_MINUS, {NULL, NULL, PREC_NONE},// TOKEN_MULTIPLY, {NULL, NULL, PREC_NONE},// TOKEN_DIVIDE, {NULL, NULL, PREC_NONE},// TOKEN_MODULO, @@ -334,7 +343,6 @@ static void printStmt(Parser* parser, Node* node) { //set the node info node->type = NODE_UNARY; node->unary.opcode = OP_PRINT; - node->unary.child = ALLOCATE(Node, 1); expression(parser, &(node->unary.child)); consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of print statement");