nitron

commit c96bca3c1da46664a85d5e90abf04af145f10a92

Author: mesyeti <mesyeti@mesyeti.uk>

add function pointers

 basic/source/frontend/c89.c | 36 +++++++++++++++
 basic/source/lexer.c | 1 
 basic/source/parser.c | 75 +++++++++++++++++++++++-----------
 basic/source/parser.h | 7 ++
 basic/source/semanticAnalysis.c | 28 ++++++++----
 basic/test.bas | 11 ++++


diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c
index 79cf2fcd6e32f328a51f894e585f066d44cd2568..514925c9a69cf7a9c898a8fcecc2a2574c1e8222 100644
--- a/basic/source/frontend/c89.c
+++ b/basic/source/frontend/c89.c
@@ -57,6 +57,10 @@ 	else {
 		fprintf(out, "nitron_%s", type->name);
 	}
 
+	if ((type->type == TYPE_FUNC) && type->name) {
+		-- used.ptr;
+	}
+
 	for (size_t i = 0; i < used.ptr; ++ i) {
 		fprintf(out, "*");
 	}
@@ -420,6 +424,34 @@
 	fprintf(out, "} nitron_%s;", type->name);
 }
 
+static void CompileFuncType(Type* type) {
+	if (!type->name) return;
+
+	Function* func = &type->func;
+
+	fprintf(out, "typedef ");
+
+	if (func->sub) {
+		fprintf(out, "void ");
+	}
+	else {
+		CompileUsedType(func->ret);
+	}
+
+	fprintf(out, "(*nitron_%s)(", type->name);
+
+	for (size_t i = 0; i < func->paramsLen; ++ i) {
+		CompileUsedType(func->params[i].type);
+		fprintf(out, " nitron_%s", func->params[i].name);
+
+		if (i < func->paramsLen - 1) {
+			fprintf(out, ", ");
+		}
+	}
+
+	fprintf(out, ");\n");
+}
+
 static void CompileReturn(ReturnNode* node) {
 	fprintf(out, "return ");
 	CompileExprNode(node->node);
@@ -451,7 +483,7 @@ 		switch (type->type) {
 			case TYPE_PRIM:   CompilePrim(type); break;
 			case TYPE_UNIT:   break;
 			case TYPE_STRUCT: CompileStruct(type); break;
-			case TYPE_FUNC:   break;
+			case TYPE_FUNC:   CompileFuncType(type); break;
 			default: assert(0);
 		}
 	}
@@ -461,7 +493,7 @@ 	for (size_t i = 0; i < state.scopeSize[0]; ++ i) {
 		Var*  var     = &state.scopes[0][i];
 		Type* varType = State_GetTypeFromUsed(var->type);
 
-		if (varType->type == TYPE_FUNC) continue;
+		if ((varType->type == TYPE_FUNC) && !var->type.ptr) continue;
 
 		if (var->isStatic) {
 			fprintf(out, "static ");




diff --git a/basic/source/lexer.c b/basic/source/lexer.c
index 8919b75cefc3ede7233625bc12ff026662a6fd40..87e73856767fdf3f60f27920472111412a3a0ed2 100644
--- a/basic/source/lexer.c
+++ b/basic/source/lexer.c
@@ -266,6 +266,7 @@ 		case TOKEN_MOD:         return "mod";
 		case TOKEN_EQUAL:       return "equal";
 		case TOKEN_LESS:        return "less";
 		case TOKEN_GREATER:     return "greater";
+		case TOKEN_ASSIGN:      return "assign";
 		case TOKEN_ACCESS_XOR:  return "access/bitwise xor";
 		case TOKEN_ADDRESS_AND: return "address/bitwise and";
 		case TOKEN_NOT_EQUAL:   return "not equal";




diff --git a/basic/source/parser.c b/basic/source/parser.c
index 7983756bb3606ba39d6cb7f2a7a471404dce6517..d7f6b966306f43c378242dd7c0b73b5914721345 100644
--- a/basic/source/parser.c
+++ b/basic/source/parser.c
@@ -378,7 +378,7 @@ 		}
 	}
 }
 
-static FuncDec ParseFuncDec(Parser* p) {
+static FuncDec ParseFuncDec(Parser* p, bool parseName) {
 	FuncDecParam* params    = NULL;
 	size_t        paramsNum = 0;
 
@@ -387,10 +387,16 @@
 	Advance(p);
 	FuncDec ret;
 
-	Expect(p, TOKEN_IDENTIFIER);
-	ret.name = NewString(p->tokens[p->i].contents);
+	if (parseName) {
+		Expect(p, TOKEN_IDENTIFIER);
+		ret.name = NewString(p->tokens[p->i].contents);
 
-	Advance(p);
+		Advance(p);
+	}
+	else {
+		ret.name = NULL;
+	}
+
 	Expect(p, TOKEN_LPAREN);
 	Advance(p);
 
@@ -477,7 +483,7 @@
 static Node ParseFuncDef(Parser* p) {
 	FuncDefNode ret;
 	ret.i       = INFO(NODE_FUNC_DEF);
-	ret.dec     = ParseFuncDec(p);
+	ret.dec     = ParseFuncDec(p, true);
 	ret.private = p->private;
 	Advance(p);
 
@@ -584,7 +590,7 @@ 	Advance(p);
 
 	ExternNode ret;
 	ret.i       = INFO(NODE_EXTERN);
-	ret.dec     = ParseFuncDec(p);
+	ret.dec     = ParseFuncDec(p, true);
 	ret.private = p->private;
 
 	p->private = false;
@@ -690,11 +696,19 @@
 		TypeDefNode ret;
 		ret.i       = INFO(NODE_TYPE_DEF);
 		ret.name    = name;
-		ret.type    = NodeToHeap(ParseType(p));
 		ret.private = private;
 
-		if (ret.type->i.type == NODE_PTR) {
-			PrintError(p->tokens[p->i].err, "Cannot use pointer for type definition");
+		if ((p->tokens[p->i].type == TOKEN_FUNC) || (p->tokens[p->i].type == TOKEN_SUB)) {
+			ret.type.dec = ParseFuncDec(p, false);
+			ret.func     = true;
+		}
+		else {
+			ret.type.node = NodeToHeap(ParseType(p));
+			ret.func      = false;
+
+			if (ret.type.node->i.type == NODE_PTR) {
+				PrintError(p->tokens[p->i].err, "Cannot use pointer for type definition");
+			}
 		}
 
 		Advance(p);
@@ -1052,10 +1066,10 @@
 			puts("end");
 			break;
 		}
-		case NODE_TYPE_DEF: {
-			printf("type %s = ", node->typeDef.name);
-			Parser_PrintNode(node->typeDef.type);
-			puts("");
+		case NODE_TYPE_DEF: { // TODO
+			//printf("type %s = ", node->typeDef.name);
+			//Parser_PrintNode(node->typeDef.type);
+			//puts("");
 			break;
 		}
 		case NODE_TYPE_BLOCK: {
@@ -1136,6 +1150,20 @@
 	free(nodes);
 }
 
+static void FreeFuncDec(FuncDec* dec) {
+	if (dec->ret) {
+		Parser_FreeNode(dec->ret);
+		free(dec->ret);
+	}
+
+	for (size_t i = 0; i < dec->paramsNum; ++ i) {
+		Parser_FreeNode(dec->params[i].type);
+		free(dec->params[i].type);
+	}
+
+	free(dec->name);
+}
+
 void Parser_FreeNode(Node* node) {
 	switch (node->i.type) {
 		case NODE_STRING:     free(node->string.value); break;
@@ -1158,17 +1186,7 @@ 			free(node->ptr.inner);
 			break;
 		}
 		case NODE_FUNC_DEF: {
-			if (node->funcDef.dec.ret) {
-				Parser_FreeNode(node->funcDef.dec.ret);
-				free(node->funcDef.dec.ret);
-			}
-
-			for (size_t i = 0; i < node->funcDef.dec.paramsNum; ++ i) {
-				Parser_FreeNode(node->funcDef.dec.params[i].type);
-				free(node->funcDef.dec.params[i].type);
-			}
-
-			free(node->funcDef.dec.name);
+			FreeFuncDec(&node->funcDef.dec);
 
 			for (size_t i = 0; i < node->funcDef.bodyLen; ++ i) {
 				Parser_FreeNode(&node->funcDef.body[i]);
@@ -1209,7 +1227,14 @@ 			break;
 		}
 		case NODE_TYPE_DEF: {
 			free(node->typeDef.name);
-			Parser_FreeNode(node->typeDef.type);
+
+			if (node->typeDef.func) {
+				FreeFuncDec(&node->typeDef.type.dec);
+			}
+			else {
+				Parser_FreeNode(node->typeDef.type.node);
+				free(node->typeDef.type.node);
+			}
 			break;
 		}
 		case NODE_TYPE_BLOCK: {




diff --git a/basic/source/parser.h b/basic/source/parser.h
index b229eb5f9040b0c692cedfd91b979ac38f13626d..08b18bed1c2cdb6506389ece5c29aa3a1256f5c8 100644
--- a/basic/source/parser.h
+++ b/basic/source/parser.h
@@ -130,8 +130,13 @@
 typedef struct {
 	NodeInfo i;
 	char*    name;
-	Node*    type;
 	bool     private;
+	bool     func;
+
+	union {
+		Node*   node;
+		FuncDec dec;
+	} type;
 } TypeDefNode;
 
 typedef struct {




diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c
index 70751771fb54da5d9762b0a2b167ee8fef1243e2..27fc2a736a3eccaade7def989320d48b5612458a 100644
--- a/basic/source/semanticAnalysis.c
+++ b/basic/source/semanticAnalysis.c
@@ -508,7 +508,7 @@ 		);
 		func.params[i].name = dec.params[i].name;
 	}
 
-	func.name = NewString(dec.name);
+	func.name = dec.name? NewString(dec.name) : NULL;
 	return func;
 }
 
@@ -719,20 +719,28 @@ 			if (State_GetType(node->typeDef.name) != NULL) {
 				PrintError(node->i.err, "Type '%s' already exists", node->typeDef.name);
 			}
 
-			assert(node->typeDef.type->i.type == NODE_IDENTIFIER);
+			Type newType;
 
-			const char* fromName = node->typeDef.type->ident.name;
-			Type*       from     = State_GetType(fromName);
+			if (node->typeDef.func) {
+				newType.type    = TYPE_FUNC;
+				newType.name    = NewString(node->typeDef.name);
+				newType.private = external && node->typeDef.private;
+				newType.func    = DecToFunc(node->typeDef.type.dec);
+			}
+			else {
+				const char* fromName = node->typeDef.type.node->ident.name;
+				Type*       from     = State_GetType(fromName);
 
-			if (!from) {
-				PrintError(node->i.err, "Type '%s' does not exist", fromName);
+				if (!from) {
+					PrintError(node->i.err, "Type '%s' does not exist", fromName);
+				}
+
+				newType         = *from;
+				newType.name    = NewString(node->typeDef.name);
+				newType.private = external && node->typeDef.private;
 			}
 
-			Type newType    = *from;
-			newType.name    = NewString(node->typeDef.name);
-			newType.private = external && node->typeDef.private;
 			State_AddType(newType);
-
 			return GET_PRIM("unit", 0);
 		}
 		case NODE_TYPE_BLOCK: {




diff --git a/basic/test.bas b/basic/test.bas
index 8bc535d6d612b0c46305da9d3d2ae409e2ee3e61..ccda661712b095ec7a1980c61aa12068fe9c3a64 100644
--- a/basic/test.bas
+++ b/basic/test.bas
@@ -5,6 +5,13 @@
 private extern func puts(str as ptr(char)) i32
 private extern func printf(str as ptr(char), val as int) i32
 
-const FOO_BAR = 5
+func Add(a as int, b as int) int
+	return a + b
+end
+
+type AddFunc = func(a as int, b as int) int
+
+dim adder as ptr(AddFunc)
+adder = &Add
 
-printf("FOO_BAR = %d\n", FOO_BAR)
+printf("2 + 2 = %d\n", adder(2, 2))