nitron

commit 7303b8c8dc4c49a545c6e19d04599e2e0af0c402

Author: mesyeti <mesyeti@mesyeti.uk>

basic: new call syntax

 basic/Makefile | 5 -
 basic/source/compiler.c | 5 -
 basic/source/compiler.h | 2 
 basic/source/frontend/c89.c | 7 --
 basic/source/lexer.c | 89 ++++++++++++++++++----------------
 basic/source/lexer.h | 5 +
 basic/source/parser.c | 72 ++++++++++++---------------
 basic/source/parser.h | 19 ++++---
 basic/source/semanticAnalysis.c | 70 +++++++++++++-------------
 basic/test.bas | 9 --
 basic/test2.bas | 1 


diff --git a/basic/Makefile b/basic/Makefile
index aaa0971a94f97fc700755b58b2d98a4def96ddee..5b435b6bc5dc69fc055a668e2e953e4edd546546 100644
--- a/basic/Makefile
+++ b/basic/Makefile
@@ -28,9 +28,6 @@
 all: $(OUT)
 	@:
 
-run: $(OUT)
-	'$(dir $<)$(notdir $<)' $(RUNFLAGS)
-
 $(OUT): $(OBJECTS)
 	$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@
 
@@ -49,4 +46,4 @@
 distclean: clean
 	rm $(OUT)
 
-.PHONY: all run clean distclean
+.PHONY: all clean distclean




diff --git a/basic/source/compiler.c b/basic/source/compiler.c
index 14f961a18c1d900f442908e119a41f5e2b0761ee..df9f561f0e56efa6adbd4548a02c6b99380b2c33 100644
--- a/basic/source/compiler.c
+++ b/basic/source/compiler.c
@@ -27,10 +27,6 @@ void Frontend_CompileFuncCall(FuncCallNode* node) {
 	frontend.compileFuncCall(node);
 }
 
-void Frontend_CompileAssign(AssignNode* node) {
-	frontend.compileAssign(node);
-}
-
 void Frontend_CompileExtern(ExternNode* node) {
 	frontend.compileExtern(node);
 }
@@ -47,7 +43,6 @@ 			case NODE_FUNC_DEF:  break;
 			case NODE_DIM:       break;
 			case NODE_EXTERN:    break;
 			case NODE_FUNC_CALL: Frontend_CompileFuncCall(&node->funcCall); break;
-			case NODE_ASSIGN:    Frontend_CompileAssign(&node->assign); break;
 			default: {
 				PrintError(node->i.err, "Unexpected '%s'", Parser_TypeStr(node->i.type));
 			}




diff --git a/basic/source/compiler.h b/basic/source/compiler.h
index 6d00872338df8c25bdd2f28c73284b786324b51a..5279ef5f9a599baf99af6686f11eeced12cad581 100644
--- a/basic/source/compiler.h
+++ b/basic/source/compiler.h
@@ -9,7 +9,6 @@ 	void (*beginMain)(void);
 	void (*compileFuncDef)(FuncDefNode* node);
 	void (*compileDim)(DimNode* node);
 	void (*compileFuncCall)(FuncCallNode* node);
-	void (*compileAssign)(AssignNode* node);
 	void (*compileExtern)(ExternNode* node);
 } Frontend;
 
@@ -19,7 +18,6 @@ void Frontend_BeginMain(void);
 void Frontend_CompileFuncDef(FuncDefNode* node);
 void Frontend_CompileDim(DimNode* node);
 void Frontend_CompileFuncCall(FuncCallNode* node);
-void Frontend_CompileAssign(AssignNode* node);
 void Frontend_CompileExtern(ExternNode* node);
 
 typedef struct {




diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c
index 870cfea38a9d6c858c427349ec368ee25b560d6a..fff6d42e6d6368671c1bc0f6ef0a64e2bc263c36 100644
--- a/basic/source/frontend/c89.c
+++ b/basic/source/frontend/c89.c
@@ -145,12 +145,6 @@ 	CompileFuncCallExpr(node);
 	fprintf(out, ";\n");
 }
 
-static void CompileAssign(AssignNode* node) {
-	fprintf(out, "nitron_%s = ", node->variable);
-	CompileExprNode(node->rValue);
-	fprintf(out, ";\n");
-}
-
 static void CompileExtern(ExternNode* node) {
 	CompileDec(node->dec);
 	fprintf(out, ";\n");
@@ -218,7 +212,6 @@ 		.beginMain       = &BeginMain,
 		.compileFuncDef  = &CompileFuncDef,
 		.compileDim      = &CompileDim,
 		.compileFuncCall = &CompileFuncCall,
-		.compileAssign   = &CompileAssign,
 		.compileExtern   = &CompileExtern
 	};
 }




diff --git a/basic/source/lexer.c b/basic/source/lexer.c
index 06ae344d28b518f6745713a23d6a05af98a2075c..7051a3837f322ea88249cc246bdb5eca1d5216bf 100644
--- a/basic/source/lexer.c
+++ b/basic/source/lexer.c
@@ -70,6 +70,11 @@
 #define TOKEN(TYPE, CONTENTS) ((Token) \
 	{(TYPE), (ErrorInfo) {lexer->fileName, lexer->line}, (CONTENTS)})
 
+typedef struct {
+	const char* name;
+	TokenType   token;
+} Keyword;
+
 int Lexer_Next(Lexer* lexer, Token* token) {
 	char ch;
 
@@ -97,10 +102,26 @@ 		case '-':  *token = TOKEN(TOKEN_SUBTRACT, NULL); return LEXER_TOKEN;
 		case '*':  *token = TOKEN(TOKEN_MULTIPLY, NULL); return LEXER_TOKEN;
 		case '/':  *token = TOKEN(TOKEN_DIVIDE,   NULL); return LEXER_TOKEN;
 		case '%':  *token = TOKEN(TOKEN_MOD,      NULL); return LEXER_TOKEN;
-		case '=':  *token = TOKEN(TOKEN_EQUAL,    NULL); return LEXER_TOKEN;
-		case '<':  *token = TOKEN(TOKEN_LESS,     NULL); return LEXER_TOKEN;
-		case '>':  *token = TOKEN(TOKEN_GREATER,  NULL); return LEXER_TOKEN;
-		case '\n': *token = TOKEN(TOKEN_LINE,     NULL); return LEXER_TOKEN;
+		case '=':  {
+			char next;
+			GET_CHAR(next);
+
+			if (next == '=') {
+				*token = TOKEN(TOKEN_EQUAL, NULL);
+			}
+			else {
+				*token = TOKEN(TOKEN_ASSIGN, NULL);
+
+				if (next == '\n') {
+					-- lexer->line;
+				}
+				fseek(lexer->file, -1, SEEK_CUR);
+			}
+			return LEXER_TOKEN;
+		}
+		case '<':  *token = TOKEN(TOKEN_LESS,    NULL); return LEXER_TOKEN;
+		case '>':  *token = TOKEN(TOKEN_GREATER, NULL); return LEXER_TOKEN;
+		case '\n': *token = TOKEN(TOKEN_LINE,    NULL); return LEXER_TOKEN;
 		case '\'': {
 			while (true) {
 				GET_CHAR(ch);
@@ -132,45 +153,27 @@ 			if (IsNumeric(string.contents)) {
 				*token = TOKEN(TOKEN_INT, string.contents);
 				return LEXER_TOKEN;
 			}
-			if (!strcmp(string.contents, "extern")) {
-				*token = TOKEN(TOKEN_EXTERN, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "func") || !strcmp(string.contents, "function")) {
-				*token = TOKEN(TOKEN_FUNC, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "sub")) {
-				*token = TOKEN(TOKEN_SUB, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "dim")) {
-				*token = TOKEN(TOKEN_DIM, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "as")) {
-				*token = TOKEN(TOKEN_AS, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "quit")) {
-				*token = TOKEN(TOKEN_QUIT, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "ptr")) {
-				*token = TOKEN(TOKEN_PTR, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
-			}
-			if (!strcmp(string.contents, "end")) {
-				*token = TOKEN(TOKEN_END, NULL);
-				String_Free(&string);
-				return LEXER_TOKEN;
+
+			static const Keyword keywords[] = {
+				{"extern",   TOKEN_EXTERN},
+				{"func",     TOKEN_FUNC},
+				{"function", TOKEN_FUNC},
+				{"sub",      TOKEN_SUB},
+				{"dim",      TOKEN_DIM},
+				{"as",       TOKEN_AS},
+				{"quit",     TOKEN_QUIT},
+				{"ptr",      TOKEN_PTR},
+				{"end",      TOKEN_END},
+				{"if",       TOKEN_IF},
+				{"then",     TOKEN_THEN}
+			};
+
+			for (size_t i = 0; i < sizeof(keywords) / sizeof(Keyword); ++ i) {
+				if (!strcmp(string.contents, keywords[i].name)) {
+					*token = TOKEN(keywords[i].token, NULL);
+					String_Free(&string);
+					return LEXER_TOKEN;
+				}
 			}
 
 			*token = TOKEN(TOKEN_IDENTIFIER, string.contents);




diff --git a/basic/source/lexer.h b/basic/source/lexer.h
index 0f3e15fa515f4e38f3882d1480fa461bb3e6a706..795de53b9dc0571dac3cd3f59e4f283bdd9ea303 100644
--- a/basic/source/lexer.h
+++ b/basic/source/lexer.h
@@ -17,6 +17,8 @@ 	TOKEN_AS,
 	TOKEN_QUIT,
 	TOKEN_PTR,
 	TOKEN_END,
+	TOKEN_IF,
+	TOKEN_THEN,
 
 	// misc
 	TOKEN_IDENTIFIER,
@@ -37,7 +39,8 @@ 	TOKEN_DIVIDE,
 	TOKEN_MOD,
 	TOKEN_EQUAL,
 	TOKEN_LESS,
-	TOKEN_GREATER
+	TOKEN_GREATER,
+	TOKEN_ASSIGN
 } TokenType;
 
 enum {




diff --git a/basic/source/parser.c b/basic/source/parser.c
index 1212e859a6a468c68afb69a25fd51f243e79d937..9c576721f1b51ac606356abc0b571345566bb051 100644
--- a/basic/source/parser.c
+++ b/basic/source/parser.c
@@ -55,6 +55,7 @@ #define INFO(TYPE) ((NodeInfo) {TYPE, p->tokens[p->i].err})
 
 static Node ParseBinary(Parser* p);
 static Node ParseNode(Parser* p);
+static Node ParseFuncCall(Parser* p);
 
 static void Advance(Parser* p) {
 	++ p->i;
@@ -84,6 +85,11 @@ 	Advance(p);
 
 	switch (token->type) {
 		case TOKEN_IDENTIFIER: {
+			if (p->tokens[p->i].type == TOKEN_LPAREN) {
+				-- p->i;
+				return ParseFuncCall(p);
+			}
+
 			ret.ident = (IdentifierNode) {INFO(NODE_IDENTIFIER), NewString(token->contents)};
 			return ret;
 		}
@@ -378,10 +384,13 @@ 	ret.i    = INFO(NODE_FUNC_CALL);
 	ret.func = NewString(p->tokens[p->i].contents);
 
 	Advance(p);
+	Expect(p, TOKEN_LPAREN);
+
+	Advance(p);
 	Node*  params    = NULL;
 	size_t paramsNum = 0;
 
-	while (p->tokens[p->i].type != TOKEN_LINE) {
+	while (p->tokens[p->i].type != TOKEN_RPAREN) {
 		Node param = ParseBinary(p);
 
 		++ paramsNum;
@@ -389,7 +398,7 @@ 		params                = SafeRealloc(params, paramsNum * sizeof(Node));
 		params[paramsNum - 1] = param;
 
 		if (
-			(p->tokens[p->i].type != TOKEN_LINE) &&
+			(p->tokens[p->i].type != TOKEN_RPAREN) &&
 			(p->tokens[p->i].type != TOKEN_COMMA)
 		) {
 			PrintError(
@@ -402,6 +411,8 @@ 			Advance(p);
 		}
 	}
 
+	Advance(p);
+
 	ret.params    = params;
 	ret.paramsNum = paramsNum;
 
@@ -410,25 +421,6 @@ 	node.funcCall = ret;
 	return node;
 }
 
-static Node ParseAssign(Parser* p) {
-	AssignNode ret;
-	ret.i        = INFO(NODE_ASSIGN);
-	ret.variable = NewString(p->tokens[p->i].contents);
-
-	Advance(p);
-	Expect(p, TOKEN_EQUAL);
-	Advance(p);
-
-	ret.rValue  = SafeMalloc(sizeof(Node));
-	*ret.rValue = ParseBinary(p);
-
-	Expect(p, TOKEN_LINE);
-
-	Node node;
-	node.assign = ret;
-	return node;
-}
-
 static Node ParseExtern(Parser* p) {
 	Advance(p);
 
@@ -441,22 +433,37 @@ 	node.external = ret;
 	return node;
 }
 
+// static Node ParseIf(Parser* p) {
+// 	Advance(p);
+// 
+// 	IfNode ret;
+// 	ret.i = INFO(NODE_IF);
+// 
+// 	
+// }
+
 static Node ParseNode(Parser* p) {
 	switch (p->tokens[p->i].type) {
 		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_IDENTIFIER: {
 			if (p->i == p->tokenNum - 1) {
 				PrintError(p->tokens[p->i].err, "Unexpected EOF");
 			}
 
-			if (p->tokens[p->i + 1].type == TOKEN_EQUAL) {
-				return ParseAssign(p);
+			Node ret = ParseBinary(p);
+
+			if (
+				((ret.i.type == NODE_BINARY_OP) && (ret.bin.op != TOKEN_ASSIGN)) ||
+				((ret.i.type != NODE_BINARY_OP) && (ret.i.type != NODE_FUNC_CALL))
+			) {
+				PrintError(p->tokens[p->i].err, "Unexpected %s", Parser_TypeStr(ret.i.type));
 			}
 
-			return ParseFuncCall(p);
+			return ret;
 		}
 		default: {
 			PrintError(
@@ -551,7 +558,7 @@ 			puts("");
 			break;
 		}
 		case NODE_FUNC_CALL: {
-			printf("%s ", node->funcCall.func);
+			printf("%s(", node->funcCall.func);
 
 			for (size_t i = 0; i < node->funcCall.paramsNum; ++ i) {
 				Parser_PrintNode(&node->funcCall.params[i]);
@@ -560,13 +567,7 @@ 				if (i < node->funcCall.paramsNum - 1) {
 					printf(", ");
 				}
 			}
-			puts("");
-			break;
-		}
-		case NODE_ASSIGN: {
-			printf("%s = ", node->assign.variable);
-			Parser_PrintNode(node->assign.rValue);
-			puts("");
+			puts(")");
 			break;
 		}
 		case NODE_EXTERN: {
@@ -659,12 +660,6 @@ 			}
 			free(node->funcCall.params);
 			break;
 		}
-		case NODE_ASSIGN: {
-			free(node->assign.variable);
-			Parser_FreeNode(node->assign.rValue);
-			free(node->assign.rValue);
-			break;
-		}
 		default: return;
 	}
 }
@@ -681,7 +676,6 @@ 		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_ASSIGN:     return "assignment";
 		default:              return "???";
 	}
 }




diff --git a/basic/source/parser.h b/basic/source/parser.h
index 2a3183738fdda807fa4471325c70c89e02a7ce9b..83a7a494083d44d595164b4e308c2719daba5907 100644
--- a/basic/source/parser.h
+++ b/basic/source/parser.h
@@ -16,8 +16,8 @@ 	NODE_PTR,
 	NODE_FUNC_DEF,
 	NODE_DIM,
 	NODE_FUNC_CALL,
-	NODE_ASSIGN,
-	NODE_EXTERN
+	NODE_EXTERN,
+	NODE_IF
 } NodeType;
 
 typedef struct {
@@ -94,14 +94,17 @@ } FuncCallNode;
 
 typedef struct {
 	NodeInfo i;
-	char*    variable;
-	Node*    rValue;
-} AssignNode;
+	FuncDec  dec;
+} ExternNode;
 
 typedef struct {
 	NodeInfo i;
-	FuncDec  dec;
-} ExternNode;
+	Node*    condition;
+	Node*    body;
+	size_t   bodyLen;
+	Node*    elseBody;
+	size_t   elseLen;
+} IfNode;
 
 union Node {
 	NodeInfo       i;
@@ -114,8 +117,8 @@ 	PtrNode        ptr;
 	FuncDefNode    funcDef;
 	DimNode        dim;
 	FuncCallNode   funcCall;
-	AssignNode     assign;
 	ExternNode     external;
+	IfNode         ifStat;
 };
 
 typedef struct {




diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c
index 309607c7ec259e7dec820f4647bbb7b9dd6550b4..40e18b6904bd1592a096fb4c8b67d602fc4acc7c 100644
--- a/basic/source/semanticAnalysis.c
+++ b/basic/source/semanticAnalysis.c
@@ -333,41 +333,41 @@ 			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_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");




diff --git a/basic/test.bas b/basic/test.bas
index 4d55461d8e4b380d153580b33028dd90be5a5e96..d480fae239708df93bba9372fba66f3e86bd24d7 100644
--- a/basic/test.bas
+++ b/basic/test.bas
@@ -1,14 +1,9 @@
 'NITRON
 
 extern func puts(str as ptr(char)) int
-extern func printf(str as ptr(char), val as int) int
 
 sub SayHello()
-	puts "Hello!"
+	puts("Hello!")
 end
 
-dim a as int
-a = 4 * 16
-
-printf "My number is %d\n", a
-SayHello
+SayHello()




diff --git a/basic/test2.bas b/basic/test2.bas
new file mode 100644
index 0000000000000000000000000000000000000000..4c7113ece9ee44c670e0a45d674efc1c6b7fc0cd
--- /dev/null
+++ b/basic/test2.bas
@@ -0,0 +1 @@
+print a / 2 / 3