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))