Author: mesyeti <mesyeti@mesyeti.uk>
basic: add if statements and assignments
basic/source/compiler.c | 69 +++++++------ basic/source/compiler.h | 11 - basic/source/frontend/c89.c | 39 ++++++- basic/source/lexer.c | 4 basic/source/lexer.h | 1 basic/source/parser.c | 172 ++++++++++++++++++++++++++++++---- basic/source/semanticAnalysis.c | 81 +++++++++------- basic/source/state.c | 6 + basic/source/state.h | 1 basic/test.bas | 11 ++
diff --git a/basic/source/compiler.c b/basic/source/compiler.c
index df9f561f0e56efa6adbd4548a02c6b99380b2c33..b37cd3093c6494615a61343fbc5a6a43dd374bb0 100644
--- a/basic/source/compiler.c
+++ b/basic/source/compiler.c
@@ -7,42 +7,45 @@ void Frontend_Init(Frontend p_frontend) {
frontend = p_frontend;
}
-void Frontend_Finish(void) {
- frontend.finish();
-}
-
-void Frontend_BeginMain(void) {
- frontend.beginMain();
-}
-
-void Frontend_CompileFuncDef(FuncDefNode* node) {
- frontend.compileFuncDef(node);
-}
-
-void Frontend_CompileDim(DimNode* node) {
- frontend.compileDim(node);
-}
-
-void Frontend_CompileFuncCall(FuncCallNode* node) {
- frontend.compileFuncCall(node);
-}
-
-void Frontend_CompileExtern(ExternNode* node) {
- frontend.compileExtern(node);
-}
-
void Compiler_Init(Node* nodes, size_t len) {
compiler.nodes = nodes;
compiler.len = len;
}
-void Compiler_Compile(Node* node, bool inFunc) {
+void Compiler_CompileBodyNode(Node* node) {
+ switch (node->i.type) {
+
+ case NODE_FUNC_CALL: frontend.compileFuncCall(&node->funcCall); break;
+ case NODE_FUNC_DEF: frontend.compileFuncDef(&node->funcDef); break;
+ case NODE_DIM: frontend.compileDim(&node->dim); break;
+ case NODE_EXTERN: frontend.compileExtern(&node->external); break;
+ case NODE_IF: frontend.compileIf(&node->ifStat); break;
+ case NODE_BINARY_OP: {
+ if (node->bin.op == TOKEN_ASSIGN) {
+ frontend.compileAssign(&node->bin);
+ break;
+ }
+ } // fall through
+ default: {
+ PrintError(node->i.err, "Unexpected '%s'", Parser_TypeStr(node->i.type));
+ }
+ }
+}
+
+void Compiler_CompileTopNode(Node* node, bool inFunc) {
if (inFunc) {
switch (node->i.type) {
case NODE_FUNC_DEF: break;
case NODE_DIM: break;
case NODE_EXTERN: break;
- case NODE_FUNC_CALL: Frontend_CompileFuncCall(&node->funcCall); break;
+ case NODE_FUNC_CALL: frontend.compileFuncCall(&node->funcCall); break;
+ case NODE_IF: frontend.compileIf(&node->ifStat); break;
+ case NODE_BINARY_OP: {
+ if (node->bin.op == TOKEN_ASSIGN) {
+ frontend.compileAssign(&node->bin);
+ break;
+ }
+ } // fall through
default: {
PrintError(node->i.err, "Unexpected '%s'", Parser_TypeStr(node->i.type));
}
@@ -50,9 +53,9 @@ }
}
else {
switch (node->i.type) {
- case NODE_FUNC_DEF: Frontend_CompileFuncDef(&node->funcDef); break;
- case NODE_DIM: Frontend_CompileDim(&node->dim); break;
- case NODE_EXTERN: Frontend_CompileExtern(&node->external); break;
+ case NODE_FUNC_DEF: frontend.compileFuncDef(&node->funcDef); break;
+ case NODE_DIM: frontend.compileDim(&node->dim); break;
+ case NODE_EXTERN: frontend.compileExtern(&node->external); break;
default: break;
}
}
@@ -61,16 +64,16 @@
void Compiler_Run(void) {
for (size_t i = 0; i < compiler.len; ++ i) {
Node* node = &compiler.nodes[i];
- Compiler_Compile(node, false);
+ Compiler_CompileTopNode(node, false);
}
- Frontend_BeginMain();
+ frontend.beginMain();
for (size_t i = 0; i < compiler.len; ++ i) {
Node* node = &compiler.nodes[i];
- Compiler_Compile(node, true);
+ Compiler_CompileTopNode(node, true);
}
- Frontend_Finish();
+ frontend.finish();
}
diff --git a/basic/source/compiler.h b/basic/source/compiler.h
index 5279ef5f9a599baf99af6686f11eeced12cad581..26db868dd7c4acf2e93fcffb7977d6768676ccc0 100644
--- a/basic/source/compiler.h
+++ b/basic/source/compiler.h
@@ -10,15 +10,11 @@ void (*compileFuncDef)(FuncDefNode* node);
void (*compileDim)(DimNode* node);
void (*compileFuncCall)(FuncCallNode* node);
void (*compileExtern)(ExternNode* node);
+ void (*compileIf)(IfNode* node);
+ void (*compileAssign)(BinaryNode* node);
} Frontend;
void Frontend_Init(Frontend p_frontend);
-void Frontend_Finish(void);
-void Frontend_BeginMain(void);
-void Frontend_CompileFuncDef(FuncDefNode* node);
-void Frontend_CompileDim(DimNode* node);
-void Frontend_CompileFuncCall(FuncCallNode* node);
-void Frontend_CompileExtern(ExternNode* node);
typedef struct {
Node* nodes;
@@ -26,7 +22,8 @@ size_t len;
} Compiler;
void Compiler_Init(Node* nodes, size_t len);
-void Compiler_Compile(Node* node, bool inMain);
+void Compiler_CompileBodyNode(Node* node);
+void Compiler_CompileTopNode(Node* node, bool inMain);
void Compiler_Run(void);
#endif
diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c
index fff6d42e6d6368671c1bc0f6ef0a64e2bc263c36..8b10294ed608e26c89721bd58f5097465fcdd00f 100644
--- a/basic/source/frontend/c89.c
+++ b/basic/source/frontend/c89.c
@@ -69,7 +69,7 @@ CompileDec(node->dec);
fprintf(out, " {\n");
for (size_t i = 0; i < node->bodyLen; ++ i) {
- Compiler_Compile(&node->body[i], true);
+ Compiler_CompileBodyNode(&node->body[i]);
}
fprintf(out, "}\n");
@@ -79,7 +79,7 @@ static void CompileDim(DimNode* node) {
if (inMain) return;
CompileType(node->varType);
- fprintf(out, " nitron_%s;\n", node->name);
+ fprintf(out, " %s;\n", node->name);
}
static void CompileExprNode(Node* node);
@@ -102,7 +102,7 @@ static void CompileExprNode(Node* node) {
switch (node->i.type) {
case NODE_INT: fprintf(out, "%d", node->integer.value); break;
case NODE_STRING: fprintf(out, "\"%s\"", node->string.value); break;
- case NODE_IDENTIFIER: fprintf(out, "nitron_%s", node->ident.name); break;
+ case NODE_IDENTIFIER: fprintf(out, "%s", node->ident.name); break;
case NODE_BINARY_OP: {
fprintf(out, "(");
CompileExprNode(node->bin.left);
@@ -112,10 +112,11 @@ case TOKEN_ADD: fprintf(out, "+"); break;
case TOKEN_SUBTRACT: fprintf(out, "-"); break;
case TOKEN_MULTIPLY: fprintf(out, "*"); break;
case TOKEN_DIVIDE: fprintf(out, "/"); break;
- case TOKEN_MOD: fprintf(out, "%%"); break;
+ case TOKEN_MOD: fprintf(out, "%%"); break;
case TOKEN_EQUAL: fprintf(out, "=="); break;
case TOKEN_LESS: fprintf(out, "<"); break;
case TOKEN_GREATER: fprintf(out, ">"); break;
+ case TOKEN_ASSIGN: fprintf(out, "="); break;
default: assert(0);
}
@@ -180,6 +181,32 @@ }
}
}
+static void CompileIf(IfNode* node) {
+ fprintf(out, "if (");
+ CompileExprNode(node->condition);
+ fprintf(out, ") {\n");
+
+ for (size_t i = 0; i < node->bodyLen; ++ i) {
+ Compiler_CompileBodyNode(&node->body[i]);
+ }
+
+ fprintf(out, "}\n");
+ fprintf(out, "else {\n");
+
+ for (size_t i = 0; i < node->elseLen; ++ i) {
+ Compiler_CompileBodyNode(&node->elseBody[i]);
+ }
+
+ fprintf(out, "}\n");
+}
+
+static void CompileAssign(BinaryNode* node) {
+ CompileExprNode(node->left);
+ fprintf(out, " = ");
+ CompileExprNode(node->right);
+ fprintf(out, ";\n");
+}
+
Frontend Frontend_C89(void) {
out = fopen("out.c", "w");
inMain = false;
@@ -212,6 +239,8 @@ .beginMain = &BeginMain,
.compileFuncDef = &CompileFuncDef,
.compileDim = &CompileDim,
.compileFuncCall = &CompileFuncCall,
- .compileExtern = &CompileExtern
+ .compileExtern = &CompileExtern,
+ .compileIf = &CompileIf,
+ .compileAssign = &CompileAssign
};
}
diff --git a/basic/source/lexer.c b/basic/source/lexer.c
index 7051a3837f322ea88249cc246bdb5eca1d5216bf..8e53cee20d36e2e919285f51190398e5fad1a7dc 100644
--- a/basic/source/lexer.c
+++ b/basic/source/lexer.c
@@ -97,6 +97,7 @@ }
case '(': *token = TOKEN(TOKEN_LPAREN, NULL); return LEXER_TOKEN;
case ')': *token = TOKEN(TOKEN_RPAREN, NULL); return LEXER_TOKEN;
case ',': *token = TOKEN(TOKEN_COMMA, NULL); return LEXER_TOKEN;
+ case ';': *token = TOKEN(TOKEN_LINE, NULL); return LEXER_TOKEN;
case '+': *token = TOKEN(TOKEN_ADD, NULL); return LEXER_TOKEN;
case '-': *token = TOKEN(TOKEN_SUBTRACT, NULL); return LEXER_TOKEN;
case '*': *token = TOKEN(TOKEN_MULTIPLY, NULL); return LEXER_TOKEN;
@@ -165,7 +166,8 @@ {"quit", TOKEN_QUIT},
{"ptr", TOKEN_PTR},
{"end", TOKEN_END},
{"if", TOKEN_IF},
- {"then", TOKEN_THEN}
+ {"then", TOKEN_THEN},
+ {"else", TOKEN_ELSE}
};
for (size_t i = 0; i < sizeof(keywords) / sizeof(Keyword); ++ i) {
diff --git a/basic/source/lexer.h b/basic/source/lexer.h
index 795de53b9dc0571dac3cd3f59e4f283bdd9ea303..3b13d51817a87a47534307f4d0cf0b9087b8721e 100644
--- a/basic/source/lexer.h
+++ b/basic/source/lexer.h
@@ -19,6 +19,7 @@ TOKEN_PTR,
TOKEN_END,
TOKEN_IF,
TOKEN_THEN,
+ TOKEN_ELSE,
// misc
TOKEN_IDENTIFIER,
diff --git a/basic/source/parser.c b/basic/source/parser.c
index 9c576721f1b51ac606356abc0b571345566bb051..84b829dee914e7daea8e86999bf6b0330472b56f 100644
--- a/basic/source/parser.c
+++ b/basic/source/parser.c
@@ -77,6 +77,12 @@ );
}
}
+static Node* NodeToHeap(Node node) {
+ Node* ret = SafeMalloc(sizeof(Node));
+ *ret = node;
+ return ret;
+}
+
static Node ParseAtom(Parser* p) {
Token* token = &p->tokens[p->i];
Node ret;
@@ -219,8 +225,29 @@
return left;
}
+static Node ParseAssign(Parser* p) {
+ Node left = ParseComparison(p);
+
+ while (p->tokens[p->i].type == TOKEN_ASSIGN) {
+ TokenType op = p->tokens[p->i].type;
+ Advance(p);
+ Node right = ParseComparison(p);
+
+ Node* leftPtr = SafeMalloc(sizeof(Node));
+ Node* rightPtr = SafeMalloc(sizeof(Node));
+ *leftPtr = left;
+ *rightPtr = right;
+
+ left.bin = (BinaryNode) {
+ INFO(NODE_BINARY_OP), leftPtr, rightPtr, op
+ };
+ }
+
+ return left;
+}
+
static Node ParseBinary(Parser* p) {
- return ParseComparison(p);
+ return ParseAssign(p);
}
static Node ParseType(Parser* p) {
@@ -324,16 +351,12 @@
return ret;
}
-static Node ParseFuncDef(Parser* p) {
- FuncDefNode ret;
- ret.i = INFO(NODE_FUNC_DEF);
- ret.dec = ParseFuncDec(p);
- Advance(p);
-
- ret.body = NULL;
- ret.bodyLen = 0;
+static Node* ParseBody(Parser* p, size_t* size) {
+ Node* ret = SafeMalloc(8 * sizeof(Node));
+ size_t cap = 8;
+ size_t len = 0;
- while (p->tokens[p->i].type != TOKEN_END) {
+ while ((p->tokens[p->i].type != TOKEN_END) && (p->tokens[p->i].type != TOKEN_ELSE)) {
if (p->tokens[p->i].type == TOKEN_LINE) {
Advance(p);
continue;
@@ -341,10 +364,29 @@ }
Node node = ParseNode(p);
- ++ ret.bodyLen;
- ret.body = SafeRealloc(ret.body, ret.bodyLen * sizeof(Node));
- ret.body[ret.bodyLen - 1] = node;
+ ++ len;
+
+ while (len >= cap) {
+ cap += 8;
+ ret = SafeRealloc(ret, cap * sizeof(Node));
+ }
+
+ ret[len - 1] = node;
}
+
+ ret = SafeRealloc(ret, len * sizeof(Node));
+ *size = len;
+ return ret;
+}
+
+static Node ParseFuncDef(Parser* p) {
+ FuncDefNode ret;
+ ret.i = INFO(NODE_FUNC_DEF);
+ ret.dec = ParseFuncDec(p);
+ Advance(p);
+
+ ret.body = ParseBody(p, &ret.bodyLen);
+ Expect(p, TOKEN_END);
Advance(p);
Expect(p, TOKEN_LINE);
@@ -433,14 +475,51 @@ node.external = ret;
return node;
}
-// static Node ParseIf(Parser* p) {
-// Advance(p);
-//
-// IfNode ret;
-// ret.i = INFO(NODE_IF);
-//
-//
-// }
+static Node ParseIf(Parser* p) {
+ Advance(p);
+
+ IfNode ret;
+ ret.i = INFO(NODE_IF);
+
+ ret.condition = NodeToHeap(ParseBinary(p));
+
+ Expect(p, TOKEN_THEN);
+ Advance(p);
+ Expect(p, TOKEN_LINE);
+ Advance(p);
+
+ ret.body = ParseBody(p, &ret.bodyLen);
+
+ if (p->tokens[p->i].type == TOKEN_ELSE) {
+ Advance(p);
+
+ switch (p->tokens[p->i].type) {
+ case TOKEN_IF: {
+ ret.elseBody = NodeToHeap(ParseIf(p));
+ ret.elseLen = 1;
+ break;
+ }
+ case TOKEN_LINE: {
+ Advance(p);
+ ret.elseBody = ParseBody(p, &ret.elseLen);
+ break;
+ }
+ default: {
+ PrintError(
+ p->tokens[p->i].err, "Unexpected '%s'",
+ Lexer_TypeAsString(&p->tokens[p->i])
+ );
+ }
+ }
+ }
+ else {
+ ret.elseLen = 0;
+ }
+
+ Node node;
+ node.ifStat = ret;
+ return node;
+}
static Node ParseNode(Parser* p) {
switch (p->tokens[p->i].type) {
@@ -448,7 +527,7 @@ case TOKEN_FUNC:
case TOKEN_SUB: return ParseFuncDef(p);
case TOKEN_DIM: return ParseDim(p);
case TOKEN_EXTERN: return ParseExtern(p);
- // case TOKEN_IF: return ParseIf(p);
+ case TOKEN_IF: return ParseIf(p);
case TOKEN_IDENTIFIER: {
if (p->i == p->tokenNum - 1) {
PrintError(p->tokens[p->i].err, "Unexpected EOF");
@@ -500,7 +579,7 @@
void Parser_PrintNode(Node* node) {
switch (node->i.type) {
case NODE_INT: printf("%d", node->integer.value); break;
- case NODE_STRING: printf("%s", node->string.value); break;
+ case NODE_STRING: printf("\"%s\"", node->string.value); break;
case NODE_IDENTIFIER: printf("%s", node->ident.name); break;
case NODE_BINARY_OP: {
printf("(");
@@ -512,14 +591,19 @@ case TOKEN_SUBTRACT: printf("-"); break;
case TOKEN_MULTIPLY: printf("*"); break;
case TOKEN_DIVIDE: printf("/"); break;
case TOKEN_MOD: printf("%%"); break;
- case TOKEN_EQUAL: printf("="); break;
+ case TOKEN_EQUAL: printf("=="); break;
case TOKEN_LESS: printf("<"); break;
case TOKEN_GREATER: printf(">"); break;
+ case TOKEN_ASSIGN: printf("="); break;
default: assert(0);
}
Parser_PrintNode(node->bin.right);
printf(")");
+
+ if (node->bin.op == TOKEN_ASSIGN) {
+ puts("");
+ }
break;
}
case NODE_UNARY_OP: {
@@ -538,6 +622,7 @@ }
case NODE_PTR: {
printf("ptr(");
Parser_PrintNode(node->ptr.inner);
+ printf(")");
break;
}
case NODE_FUNC_DEF: {
@@ -575,6 +660,26 @@ printf("extern ");
PrintDec(node->external.dec);
break;
}
+ case NODE_IF: {
+ printf("if ");
+ Parser_PrintNode(node->ifStat.condition);
+ printf(" then\n");
+
+ for (size_t i = 0; i < node->ifStat.bodyLen; ++ i) {
+ printf(" ");
+ Parser_PrintNode(&node->ifStat.body[i]);
+ }
+
+ puts("else");
+
+ for (size_t i = 0; i < node->ifStat.elseLen; ++ i) {
+ printf(" ");
+ Parser_PrintNode(&node->ifStat.elseBody[i]);
+ }
+
+ puts("end");
+ break;
+ }
default: {
printf("unknown %d\n", node->i.type);
assert(0);
@@ -603,6 +708,14 @@ free(p->tokens);
*lenOut = len;
return ret;
+}
+
+static void FreeNodes(Node* nodes, size_t len) {
+ for (size_t i = 0; i < len; ++ i) {
+ Parser_FreeNode(&nodes[i]);
+ }
+
+ free(nodes);
}
void Parser_FreeNode(Node* node) {
@@ -660,6 +773,15 @@ }
free(node->funcCall.params);
break;
}
+ case NODE_IF: {
+ Parser_FreeNode(node->ifStat.condition);
+ FreeNodes(node->ifStat.body, node->ifStat.bodyLen);
+
+ if (node->ifStat.elseLen > 0) {
+ FreeNodes(node->ifStat.elseBody, node->ifStat.elseLen);
+ }
+ break;
+ }
default: return;
}
}
@@ -676,6 +798,8 @@ case NODE_PTR: return "ptr";
case NODE_FUNC_DEF: return "function definition";
case NODE_DIM: return "dim";
case NODE_FUNC_CALL: return "function call";
+ case NODE_EXTERN: return "extern";
+ case NODE_IF: return "if";
default: return "???";
}
}
diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c
index 40e18b6904bd1592a096fb4c8b67d602fc4acc7c..dd44ad0017c195f9bd81388f228550d749f68caf 100644
--- a/basic/source/semanticAnalysis.c
+++ b/basic/source/semanticAnalysis.c
@@ -79,6 +79,30 @@
#define GET_PRIM(NAME, PTR) \
((UsedType) {(PTR), State_GetType(NAME) - state.types, 0})
+static UsedType EvalAssign(Node* node, UsedType left, UsedType right) {
+ Type* leftType = State_GetTypeFromUsed(left);
+ Type* rightType = State_GetTypeFromUsed(right);
+
+ bool compatible = true;
+
+ if ((left.ptr != right.ptr) || (leftType->type != rightType->type)) {
+ compatible = false;
+ }
+ else if (leftType->type == TYPE_PRIM) {
+ if (leftType->primType != rightType->primType) compatible = false;
+ else if (leftType->size < rightType->size) compatible = false;
+ }
+
+ if (!compatible) {
+ PrintError(
+ node->i.err, "Type '%s' cannot be assigned to '%s' variable",
+ State_GetTypeFromUsed(left)->name, State_GetTypeFromUsed(right)->name
+ );
+ }
+
+ return GET_PRIM("unit", 0);
+}
+
static UsedType EvalBinOp(Node* node) {
UsedType left = SemanticAnalysis_EvalType(node->bin.left);
UsedType right = SemanticAnalysis_EvalType(node->bin.right);
@@ -88,6 +112,10 @@ Type* rightType = State_GetTypeFromUsed(right);
if ((leftType->type != TYPE_PRIM) || (rightType->type != TYPE_PRIM)) {
PrintError(node->i.err, "You can only use primitive types in binary expressions");
+ }
+
+ if (node->bin.op == TOKEN_ASSIGN) {
+ return EvalAssign(node, left, right);
}
if (left.ptr) {
@@ -333,41 +361,6 @@ var.name = NewString(node->dim.name);
State_AddVar(var);
return GET_PRIM("unit", 0);
}
-// case NODE_ASSIGN: {
-// Var* var = State_GetVar(node->assign.variable);
-//
-// if (!var) {
-// PrintError(
-// node->i.err, "Variable '%s' doesn't exist",
-// node->assign.variable
-// );
-// }
-//
-// UsedType left = var->type;
-// UsedType right = SemanticAnalysis_EvalType(node->assign.rValue);
-//
-// Type* leftType = State_GetTypeFromUsed(left);
-// Type* rightType = State_GetTypeFromUsed(right);
-//
-// bool compatible = true;
-//
-// if ((left.ptr != right.ptr) || (leftType->type != rightType->type)) {
-// compatible = false;
-// }
-// else if (leftType->type == TYPE_PRIM) {
-// if (leftType->primType != rightType->primType) compatible = false;
-// else if (leftType->size < rightType->size) compatible = false;
-// }
-//
-// if (!compatible) {
-// PrintError(
-// node->i.err, "Type '%s' cannot be assigned to '%s' variable",
-// State_GetTypeFromUsed(left)->name, State_GetTypeFromUsed(right)->name
-// );
-// }
-//
-// return GET_PRIM("unit", 0);
-// }
case NODE_EXTERN: {
if (inFunc) {
PrintError(node->i.err, "Nested function definitions are not allowed");
@@ -375,6 +368,24 @@ }
Function func = DecToFunc(node->funcDef.dec);
State_AddFunc(func);
+ return GET_PRIM("unit", 0);
+ }
+ case NODE_IF: {
+ Type conditionType = state.types[
+ SemanticAnalysis_EvalType(node->ifStat.condition).typeIdx
+ ];
+
+ if (!State_IsInt(conditionType)) {
+ PrintError(node->i.err, "If condition must evaluate to an integer");
+ }
+
+ for (size_t i = 0; i < node->ifStat.bodyLen; ++ i) {
+ SemanticAnalysis_EvalType(&node->ifStat.body[i]);
+ }
+ for (size_t i = 0; i < node->ifStat.elseLen; ++ i) {
+ SemanticAnalysis_EvalType(&node->ifStat.elseBody[i]);
+ }
+
return GET_PRIM("unit", 0);
}
default: {
diff --git a/basic/source/state.c b/basic/source/state.c
index e3af9ad34f6183431adfe58cb1b6f1f8a5882b05..ece1a8c4a3130ec1836438b4d24a396846640226 100644
--- a/basic/source/state.c
+++ b/basic/source/state.c
@@ -129,3 +129,9 @@
Type* State_GetTypeFromUsed(UsedType type) {
return &state.types[type.typeIdx];
}
+
+bool State_IsInt(Type type) {
+ return (type.type == TYPE_PRIM) && (
+ (type.primType == PRIM_UINT) || (type.primType == PRIM_INT)
+ );
+}
diff --git a/basic/source/state.h b/basic/source/state.h
index fcdc210ea2c966a5ad728911dd116899fd68d4b9..2af51b78e5775050144b5f848a98fbd3cfe54ebb 100644
--- a/basic/source/state.h
+++ b/basic/source/state.h
@@ -77,5 +77,6 @@ void State_MakePrimitive(const char* name, size_t size, int primType);
bool State_UsedTypeEq(UsedType a, UsedType b);
void State_DumpInfo(void);
Type* State_GetTypeFromUsed(UsedType type);
+bool State_IsInt(Type type);
#endif
diff --git a/basic/test.bas b/basic/test.bas
index d480fae239708df93bba9372fba66f3e86bd24d7..1536008312bf9bc0935fe4b9119c8a2dc5e96131 100644
--- a/basic/test.bas
+++ b/basic/test.bas
@@ -7,3 +7,14 @@ puts("Hello!")
end
SayHello()
+
+dim a as int
+a = 5
+
+if a == 5 then
+ puts("a is 5")
+else if a == 6 then
+ puts("a is 6")
+else
+ puts("a is not 5 or 6")
+end