Browse Source

Added TOKEN_EQUAL_EQUAL && TOKEN_BANG_EQUAL

- Also added uasm.c:tryTypeCast to automatically convert between types
- Added TOKEN_BANG but left unimplmented
remotes/origin/HEAD
Seth Stubbs 5 months ago
parent
commit
5584d746a6
  1. 48
      src/uasm.c
  2. 12
      src/ulex.c
  3. 5
      src/ulex.h
  4. 6
      src/uparse.c
  5. 4
      src/uparse.h

48
src/uasm.c

@ -211,6 +211,30 @@ int compareVarTypes(UCompState *state, UVarType t1, UVarType t2) {
return t1 == t2;
}
/* assumes `from` is already on the stack */
int tryTypeCast(UCompState *state, UVarType from, UVarType to) {
if (compareVarTypes(state, from, to))
return 1;
switch(to) {
case TYPE_INT:
switch(from) {
case TYPE_CHAR: fprintf(state->out, "SWP POP\n"); state->pushed -= 1; break; /* moves the most significant byte to the front and pops it */
default: return 0;
}
break;
case TYPE_CHAR:
switch(from) {
case TYPE_INT: fprintf(state->out, "#00 SWP\n"); state->pushed += 1; break; /* pushes an empty byte to the stack and moves it to the most significant byte */
default: return 0;
}
break;
default: return 0;
}
return 1;
}
/* ==================================[[ arithmetic ]]================================== */
void pop(UCompState *state, int size) {
@ -251,6 +275,22 @@ void doArith(UCompState *state, const char *instr, UVarType type) {
}
}
void doComp(UCompState *state, const char *instr, UVarType type) {
switch(type) {
case TYPE_INT:
fprintf(state->out, "%s2\n", instr);
state->pushed -= SIZE_INT*2; /* pop the two shorts */
break;
case TYPE_CHAR:
fprintf(state->out, "%s\n", instr);
state->pushed -= SIZE_CHAR*2; /* pop the two chars */
break;
default:
cError(state, "Unknown variable type! [%d]", type);
}
state->pushed += SIZE_CHAR;
}
UVarType compileAssignment(UCompState *state, UASTNode *node) {
UASTVarNode *nVar = (UASTVarNode*)node->left;
UVar *rawVar = getVarByID(state, nVar->scope, nVar->var);
@ -260,7 +300,7 @@ UVarType compileAssignment(UCompState *state, UASTNode *node) {
expType = compileExpression(state, node->right);
/* make sure we can assign the value of this expression to this variable */
if (!compareVarTypes(state, expType, rawVar->type))
if (!tryTypeCast(state, expType, rawVar->type))
cErrorNode(state, node, "Cannot assign type '%s' to '%.*s' of type '%s'", getTypeName(expType), rawVar->len, rawVar->name, getTypeName(rawVar->type));
/* duplicate the value on the stack */
@ -269,7 +309,7 @@ UVarType compileAssignment(UCompState *state, UASTNode *node) {
/* assign the copy to the variable, leaving a copy on the stack for the expression */
setVar(state, nVar->scope, nVar->var, expType);
return expType;
return rawVar->type;
}
UVarType compileExpression(UCompState *state, UASTNode *node) {
@ -293,7 +333,9 @@ UVarType compileExpression(UCompState *state, UASTNode *node) {
case NODE_SUB: doArith(state, "SUB", lType); break;
case NODE_MUL: doArith(state, "MUL", lType); break;
case NODE_DIV: doArith(state, "DIV", lType); break;
case NODE_INTLIT: writeIntLit(state, ((UASTIntNode*)node)->num); return TYPE_INT; break;
case NODE_EQUAL: doComp(state, "EQU", lType); return TYPE_CHAR;
case NODE_NOTEQUAL: doComp(state, "NEQ", lType); return TYPE_CHAR;
case NODE_INTLIT: writeIntLit(state, ((UASTIntNode*)node)->num); return TYPE_INT;
case NODE_VAR: return compileVar(state, node); break;
default:
cError(state, "unknown AST node!! [%d]\n", node->type);

12
src/ulex.c

@ -67,6 +67,15 @@ char peekNext(ULexState *state) {
return state->current[1];
}
int charMatch(ULexState *state, char expected) {
if (isEnd(state) || *state->current != expected)
return 0;
/* it charMatched, so increment the currentChar and return true */
state->current++;
return 1;
}
int isAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; /* identifiers can have '_' */
}
@ -169,12 +178,13 @@ UToken UL_scanNext(ULexState *state) {
case '}': return makeToken(state, TOKEN_RIGHT_BRACE);
case '[': return makeToken(state, TOKEN_LEFT_BRACKET);
case ']': return makeToken(state, TOKEN_RIGHT_BRACKET);
case '=': return makeToken(state, TOKEN_EQUAL);
case '+': return makeToken(state, TOKEN_PLUS);
case '-': return makeToken(state, TOKEN_MINUS);
case '/': return makeToken(state, TOKEN_SLASH);
case '*': return makeToken(state, TOKEN_STAR);
case ';': return makeToken(state, TOKEN_COLON);
case '=': return charMatch(state, '=') ? makeToken(state, TOKEN_EQUAL_EQUAL) : makeToken(state, TOKEN_EQUAL);
case '!': return charMatch(state, '=') ? makeToken(state, TOKEN_BANG_EQUAL) : makeToken(state, TOKEN_BANG);
case '\'': return readCharacter(state);
case '\0': return makeToken(state, TOKEN_EOF);
default:

5
src/ulex.h

@ -26,6 +26,11 @@ typedef enum {
TOKEN_MINUS,
TOKEN_SLASH,
TOKEN_STAR,
TOKEN_BANG,
/* two character tokens */
TOKEN_EQUAL_EQUAL,
TOKEN_BANG_EQUAL,
TOKEN_EOF, /* end of file */
TOKEN_UNREC, /* unrecognized symbol */

6
src/uparse.c

@ -4,6 +4,7 @@
typedef enum {
PREC_NONE,
PREC_ASSIGNMENT, /* = */
PREC_COMPAR, /* == != */
PREC_TERM, /* + - */
PREC_FACTOR, /* * / */
PREC_LITERAL, /* literal values */
@ -192,6 +193,8 @@ UASTNode* binOperator(UParseState *state, UASTNode *left, Precedence currPrec) {
case TOKEN_MINUS: type = NODE_SUB; break;
case TOKEN_STAR: type = NODE_MUL; break;
case TOKEN_SLASH: type = NODE_DIV; break;
case TOKEN_EQUAL_EQUAL: type = NODE_EQUAL; break;
case TOKEN_BANG_EQUAL: type = NODE_NOTEQUAL; break;
default:
error(state, "Unknown binary operator '%.*s'!", state->current.len, state->current.str);
return NULL;
@ -241,7 +244,10 @@ ParseRule ruleTable[] = {
{NULL, binOperator, PREC_TERM}, /* TOKEN_MINUS */
{NULL, binOperator, PREC_FACTOR}, /* TOKEN_SLASH */
{NULL, binOperator, PREC_FACTOR}, /* TOKEN_STAR */
{NULL, NULL, PREC_NONE}, /* TOKEN_BANG */
{NULL, binOperator, PREC_COMPAR}, /* TOKEN_EQUAL_EQUAL */
{NULL, binOperator, PREC_COMPAR}, /* TOKEN_BANG_EQUAL */
{NULL, NULL, PREC_NONE}, /* TOKEN_EOF */
{NULL, NULL, PREC_NONE}, /* TOKEN_UNREC */
{NULL, NULL, PREC_NONE}, /* TOKEN_ERR */

4
src/uparse.h

@ -9,10 +9,14 @@
#define COMMON_NODE_HEADER UASTNode _node;
typedef enum {
/* arith op */
NODE_ADD,
NODE_SUB,
NODE_MUL,
NODE_DIV,
NODE_EQUAL,
NODE_NOTEQUAL,
/* literals */
NODE_INTLIT,
NODE_VAR,
NODE_ASSIGN, /* node->left holds Var node, node->right holds expression */

Loading…
Cancel
Save