Browse Source

Added for loops, bug fixes and misc. refactoring

- Added a nice wrapper for compileExpression, compileVoidExpression() which does some optimizations and leaves nothing on the stack
- TOKEN_FOR, NODE_STATE_FOR were added to the lexer, parser & compiler
master
Seth Stubbs 3 months ago
parent
commit
b8c3bf57d1
  1. 8
      main.uxc
  2. 2
      src/main.c
  3. 79
      src/uasm.c
  4. 1
      src/ulex.c
  5. 1
      src/ulex.h
  6. 33
      src/uparse.c
  7. 8
      src/uparse.h

8
main.uxc

@ -1,5 +1,5 @@
int i = 0;
while (i < 10) {
int i;
for (i = 0; i < 10; i = i + 1)
prntint i;
i = i + 1;
}
prntint 0xFFFF;

2
src/main.c

@ -54,5 +54,7 @@ int main(int argc, const char *argv[]) {
/* clean up */
UP_freeTree((UASTNode*)tree);
free(src);
printf("Compiled successfully! Wrote generated uxntal to %s\n", out);
return 0;
}

79
src/uasm.c

@ -262,8 +262,10 @@ void defineSubLbl(UCompState *state, int subLblID) {
fprintf(state->out, "&lbl%d\n", subLblID);
}
/* expects TYPE_BOOL at the top of the stack */
void jmpCondSub(UCompState *state, int subLblID) {
fprintf(state->out, ",&lbl%d JCN\n", subLblID);
state->pushed -= SIZE_BOOL;
}
void jmpSub(UCompState *state, int subLblID) {
@ -384,6 +386,19 @@ UVarType compileExpression(UCompState *state, UASTNode *node) {
return lType;
}
/* compile an expression without leaving anything on the stack */
void compileVoidExpression(UCompState *state, UASTNode *node) {
int savedPushed = state->pushed;
if (node->type == NODE_ASSIGN)
compileAssignment(state, node, 0);
else
compileExpression(state, node);
/* clean the stack */
pop(state, state->pushed - savedPushed);
}
void compilePrintInt(UCompState *state, UASTNode *node) {
compileExpression(state, node->left);
fwrite(";print-decimal JSR2 #20 .Console/char DEO\n", 42, 1, state->out);
@ -422,20 +437,19 @@ void compileIf(UCompState *state, UASTNode *node) {
UVarType type = compileExpression(state, node->left);
if (!tryTypeCast(state, type, TYPE_BOOL))
cErrorNode(state, (UASTNode*)ifNode, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
cErrorNode(state, (UASTNode*)node->left, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
state->pushed -= SIZE_BOOL;
if (ifNode->elseBlock) {
int tmpJmp = jmpID;
/* write comparison jump, if the flag is equal to true, skip the else statements */
/* write comparison jump, if the flag is equal to true, jump to the true block */
jmpCondSub(state, tmpJmp);
compileAST(state, ifNode->elseBlock);
jmpCondSub(state, jmpID = newLbl(state));
jmpSub(state, jmpID = newLbl(state)); /* skip the true block */
/* true block */
defineSubLbl(state, tmpJmp);
compileAST(state, ifNode->block);
} else {
/* write comparison jump, if the flag is not equal to true, skip the true statements */
/* write comparison jump, if the flag is not equal to true, skip the true block */
fprintf(state->out, "#01 NEQ ");
jmpCondSub(state, jmpID);
compileAST(state, ifNode->block);
@ -445,7 +459,7 @@ void compileIf(UCompState *state, UASTNode *node) {
}
void compileWhile(UCompState *state, UASTNode *node) {
UASTWhileNode *ifNode = (UASTWhileNode*)node;
UASTWhileNode *whileNode = (UASTWhileNode*)node;
int loopStart = newLbl(state);
int loopExit = newLbl(state);
@ -454,14 +468,47 @@ void compileWhile(UCompState *state, UASTNode *node) {
UVarType type = compileExpression(state, node->left);
if (!tryTypeCast(state, type, TYPE_BOOL))
cErrorNode(state, (UASTNode*)ifNode, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
cErrorNode(state, node, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
/* write comparison jump, if the flag is not equal to true, exit the loop */
fprintf(state->out, "#01 NEQ ");
jmpCondSub(state, loopExit);
state->pushed -= SIZE_BOOL;
compileAST(state, ifNode->block);
compileAST(state, whileNode->block);
/* jump back to the start of the loop */
jmpSub(state, loopStart);
defineSubLbl(state, loopExit);
}
void compileFor(UCompState *state, UASTNode *node) {
UVarType type;
UASTForNode *forNode = (UASTForNode*)node;
int loopEntry = newLbl(state);
int loopStart = newLbl(state);
int loopExit = newLbl(state);
/* compile initalizer */
compileVoidExpression(state, node->left);
jmpSub(state, loopEntry); /* on entry, we skip the iterator */
/* compile iterator */
defineSubLbl(state, loopStart);
compileVoidExpression(state, forNode->iter);
/* compile conditional */
defineSubLbl(state, loopEntry);
type = compileExpression(state, forNode->cond);
if (!tryTypeCast(state, type, TYPE_BOOL))
cErrorNode(state, node, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
/* write comparison jump, if the flag is not equal to true, exit the loop */
fprintf(state->out, "#01 NEQ ");
jmpCondSub(state, loopExit);
/* finally, compile loop block */
compileAST(state, forNode->block);
/* jump back to the start of the loop */
jmpSub(state, loopStart);
@ -471,26 +518,18 @@ void compileWhile(UCompState *state, UASTNode *node) {
void compileAST(UCompState *state, UASTNode *node) {
/* STATE nodes hold the expression in node->left, and the next expression in node->right */
while (node) {
int startPushed = state->pushed;
switch(node->type) {
switch(node->type) { /* these functions should NOT leave any values on the stack */
case NODE_STATE_PRNT: compilePrintInt(state, node); break;
case NODE_STATE_DECLARE_VAR: compileDeclaration(state, node); break;
case NODE_STATE_EXPR:
if (node->left->type == NODE_ASSIGN)
compileAssignment(state, node->left, 0);
else
compileExpression(state, node->left);
break;
case NODE_STATE_EXPR: compileVoidExpression(state, node->left); break;
case NODE_STATE_SCOPE: compileScope(state, node); break;
case NODE_STATE_IF: compileIf(state, node); break;
case NODE_STATE_WHILE: compileWhile(state, node); break;
case NODE_STATE_FOR: compileFor(state, node); break;
default:
cError(state, "unknown statement node!! [%d]\n", node->type);
}
/* clean the stack */
pop(state, state->pushed - startPushed);
/* move to the next statement */
node = node->right;
}

1
src/ulex.c

@ -13,6 +13,7 @@ UReservedWord reservedWords[] = {
{TOKEN_VOID, "void", 4},
{TOKEN_BOOL, "bool", 4},
{TOKEN_WHILE, "while", 5},
{TOKEN_FOR, "for", 3},
{TOKEN_PRINTINT, "prntint", 7},
{TOKEN_IF, "if", 2},
{TOKEN_ELSE, "else", 4},

1
src/ulex.h

@ -11,6 +11,7 @@ typedef enum {
TOKEN_IF,
TOKEN_ELSE,
TOKEN_WHILE,
TOKEN_FOR,
/* literals */
TOKEN_IDENT,

33
src/uparse.c

@ -224,6 +224,7 @@ ParseRule ruleTable[] = {
{NULL, NULL, PREC_NONE}, /* TOKEN_IF */
{NULL, NULL, PREC_NONE}, /* TOKEN_ELSE */
{NULL, NULL, PREC_NONE}, /* TOKEN_WHILE */
{NULL, NULL, PREC_NONE}, /* TOKEN_FOR */
/* literals */
{identifer, NULL, PREC_LITERAL}, /* TOKEN_IDENT */
@ -373,7 +374,34 @@ UASTNode* whileStatement(UParseState *state) {
if (!match(state, TOKEN_RIGHT_PAREN))
error(state, "Expected ')' to end while conditional!");
/* parse the true block */
/* parse the loop block */
node->block = statement(state);
return (UASTNode*)node;
}
UASTNode* forStatement(UParseState *state) {
UASTForNode *node = (UASTForNode*)newBaseNode(state, state->previous, sizeof(UASTForNode), NODE_STATE_FOR, NULL, NULL);
if (!match(state, TOKEN_LEFT_PAREN))
error(state, "Expected '(' to start for initalizer!");
/* set the initalizer */
node->_node.left = expression(state);
if (!match(state, TOKEN_COLON))
error(state, "Expected ';' to start for conditional!");
node->cond = expression(state);
if (!match(state, TOKEN_COLON))
error(state, "Expected ';' to start for iterator!");
node->iter = expression(state);
if (!match(state, TOKEN_RIGHT_PAREN))
error(state, "Expected ')' to end for iterator!");
/* parse the loop block */
node->block = statement(state);
return (UASTNode*)node;
}
@ -404,6 +432,8 @@ UASTNode* statement(UParseState *state) {
return ifStatement(state);
} else if (match(state, TOKEN_WHILE)) {
return whileStatement(state);
} else if (match(state, TOKEN_FOR)) {
return forStatement(state);
} else {
UToken tkn = state->previous;
/* no statement match was found, just parse the expression */
@ -437,6 +467,7 @@ void printNode(UASTNode *node) {
case NODE_STATE_DECLARE_VAR: printf("NVAR"); break;
case NODE_STATE_IF: printf("IF"); break;
case NODE_STATE_WHILE: printf("WHIL"); break;
case NODE_STATE_FOR: printf("FOR"); break;
case NODE_VAR: printf("VAR[%d]", ((UASTVarNode*)node)->var); break;
case NODE_STATE_EXPR: printf("EXPR"); break;
default: break;

8
src/uparse.h

@ -35,6 +35,7 @@ typedef enum {
NODE_STATE_EXPR,
NODE_STATE_IF,
NODE_STATE_WHILE,
NODE_STATE_FOR,
/* scopes are different, node->left holds the statement tree for the scope, node->right holds the next statement */
NODE_STATE_SCOPE,
} UASTNodeType;
@ -99,6 +100,13 @@ typedef struct {
UASTNode *block;
} UASTWhileNode;
typedef struct {
COMMON_NODE_HEADER;
UASTNode *cond;
UASTNode *iter;
UASTNode *block;
} UASTForNode;
typedef struct {
/* lexer related info */
ULexState lstate;

Loading…
Cancel
Save