nitron

commit 63aecdc98f0f2834bf4826c1c89db5371310d035

Author: mesyeti <mesyeti@mesyeti.uk>

add array accesses to NitronBASIC

 basic/source/frontend/c89.c | 39 ++++++++++++++++++++++++++--
 basic/source/lexer.c | 4 ++
 basic/source/parser.c | 6 ++++
 basic/source/semanticAnalysis.c | 48 +++++++++++++++++++++++++++++++++++
 basic/test.bas | 5 +++
 basic/test2.bas | 4 ++


diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c
index fb57b83b093a8ee2c84562b6ade60f08b24286c4..33d890c1094c16e7ac0a8ff60ecef41f9496f0d7 100644
--- a/basic/source/frontend/c89.c
+++ b/basic/source/frontend/c89.c
@@ -64,7 +64,7 @@ 	fprintf(out, "%s(", dec.name);
 
 	for (size_t i = 0; i < dec.paramsNum; ++ i) {
 		CompileType(dec.params[i].type);
-		fprintf(out, " %s", dec.params[i].name);
+		fprintf(out, " nitron_%s", dec.params[i].name);
 
 		if (i < dec.paramsNum - 1) {
 			fprintf(out, ", ");
@@ -117,7 +117,27 @@
 	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, "%s", node->ident.name); break;
+		case NODE_IDENTIFIER: {
+			Var* var = State_GetVar(node->ident.name);
+
+			bool func = false;
+
+			if (var) {
+				Type* type = State_GetTypeFromUsed(var->type);
+				
+				if ((var->type.ptr == 0) && (var->type.array == 0) && (type->type == TYPE_FUNC)) {
+					func = true;
+				}
+			}
+
+			if (func) {
+				fprintf(out, "%s", node->ident.name);
+			}
+			else {
+				fprintf(out, "nitron_%s", node->ident.name);
+			}
+			break;
+		}
 		case NODE_BINARY_OP: {
 			fprintf(out, "(");
 			CompileExprNode(node->bin.left);
@@ -145,10 +165,16 @@ 					}
 					break;
 				}
 				case TOKEN_LPAREN: break; // function call, nothing to do
+				case TOKEN_LSQUARE: fprintf(out, "["); break;
 				default: assert(0);
 			}
 
 			CompileExprNode(node->bin.right);
+
+			if (node->bin.op == TOKEN_LSQUARE) {
+				fprintf(out, "]");
+			}
+
 			fprintf(out, ")");
 			break;
 		}
@@ -314,7 +340,14 @@
 		if (varType->type == TYPE_FUNC) continue;
 
 		CompileUsedType(var->type);
-		fprintf(out, " nitron_%s;\n", var->name);
+		fprintf(out, " nitron_%s", var->name);
+
+		if (var->type.array) {
+			fprintf(out, "[%d];\n", (int) var->type.array);
+		}
+		else {
+			fprintf(out, ";\n");
+		}
 	}
 
 	// declare all functions




diff --git a/basic/source/lexer.c b/basic/source/lexer.c
index 9d5185d1937492c9c9dcf83cf7da9c350119df2a..1a385bd5a17d1a8f766f19be16866d59ebf55b6f 100644
--- a/basic/source/lexer.c
+++ b/basic/source/lexer.c
@@ -37,7 +37,9 @@ 		case '>':
 		case '\'':
 		case '^':
 		case '&':
-		case ';':  return true;
+		case ';':
+		case '[':
+		case ']':  return true;
 		default:   return false;
 	}
 }




diff --git a/basic/source/parser.c b/basic/source/parser.c
index 6f2750e3c2bb090b3e1cb9887cf3957f318fbcac..a71dc8d423b5fd1d7423df351e5a29485862c3fc 100644
--- a/basic/source/parser.c
+++ b/basic/source/parser.c
@@ -812,10 +812,16 @@ 				case TOKEN_GREATER:  printf(">");  break;
 				case TOKEN_ASSIGN:   printf("=");  break;
 				case TOKEN_DOT:      printf(".");  break;
 				case TOKEN_LPAREN:   break;
+				case TOKEN_LSQUARE:  printf("["); break;
 				default:             assert(0);
 			}
 
 			Parser_PrintNode(node->bin.right);
+
+			if (node->bin.op == TOKEN_LSQUARE) {
+				printf("]");
+			}
+
 			printf(")");
 
 			if (node->bin.op == TOKEN_ASSIGN) {




diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c
index 1a382c2409465ec9bcad45e6b8db88e0ddc5e8d2..8363fbc73b6da5348e71e8c4ce888d427084c49c 100644
--- a/basic/source/semanticAnalysis.c
+++ b/basic/source/semanticAnalysis.c
@@ -190,6 +190,39 @@ 		return func->ret;
 	}
 }
 
+static UsedType EvalArrayAccess(Node* node, UsedType left, UsedType right) {
+	Type* leftType  = State_GetTypeFromUsed(left);
+	Type* rightType = State_GetTypeFromUsed(right);
+
+	if ((left.array > 0) || (left.ptr > 0)) {
+		if (
+			(right.ptr > 0) || (right.array > 0) || (rightType->type != TYPE_PRIM)
+		) {
+			PrintError(node->i.err, "Only integers can be used to index an array");
+		}
+
+		if ((rightType->primType != PRIM_UINT) && (rightType->primType != PRIM_INT)) {
+			PrintError(node->i.err, "Only integers can be used to index an array");
+		}
+
+		UsedType ret = left;
+
+		if (left.array > 0) {
+			-- ret.array;
+		}
+		else if (left.ptr > 0) {
+			-- ret.ptr;
+		}
+
+		return ret;
+	}
+	else {
+		PrintError(node->i.err, "Cannot use array access operator on this type");
+	}
+
+	assert(0);
+}
+
 static UsedType EvalBinOp(Node* node) {
 	UsedType left = SemanticAnalysis_EvalType(node->bin.left);
 
@@ -201,6 +234,10 @@ 		return EvalFuncCall(node, left);
 	}
 
 	UsedType right = SemanticAnalysis_EvalType(node->bin.right);
+
+	if (node->bin.op == TOKEN_LSQUARE) {
+		return EvalArrayAccess(node, left, right);
+	}
 
 	Type* leftType  = State_GetTypeFromUsed(left);
 	Type* rightType = State_GetTypeFromUsed(right);
@@ -444,6 +481,17 @@ 		case NODE_DIM: {
 			Var var;
 			var.type = SemanticAnalysis_NodeAsUsedType(node->dim.varType);
 			var.name = NewString(node->dim.name);
+
+			if (node->dim.array) {
+				if (node->dim.arrayLen->i.type != NODE_INT) {
+					// this will be changed at some point
+					// TODO
+					PrintError(node->dim.arrayLen->i.err, "Array length must be a constant integer");
+				}
+
+				var.type.array = node->dim.arrayLen->integer.value;
+			}
+
 			State_AddVar(var);
 			return GET_PRIM("unit", 0);
 		}




diff --git a/basic/test.bas b/basic/test.bas
index 5efc554e8f2f83da16dc67a388ca4deac79a44ac..a42885304b30f991aedef977e1263ff2acb719e9 100644
--- a/basic/test.bas
+++ b/basic/test.bas
@@ -11,3 +11,8 @@ end
 
 printf("2 + 2 = %d\n", add(2, 2))
 printf("2 + 3 = %d\n", add(2, 3))
+
+dim myArray[5] as i32
+
+myArray[0] = 4
+printf("myArray[0] = %d\n", myArray[0])




diff --git a/basic/test2.bas b/basic/test2.bas
index cda0b34274133fe1842785c47369fd4b40b13e5e..ce689966335a9e5beb787432f296c18e3f53bf4d 100644
--- a/basic/test2.bas
+++ b/basic/test2.bas
@@ -1,3 +1,5 @@
 'NITRON
 
-print("hello")
+dim myArray[5] as u32
+
+myArray[0] = 5