diff --git a/src/ast.c b/src/ast.c index 8c12fdf..702acd2 100644 --- a/src/ast.c +++ b/src/ast.c @@ -57,7 +57,7 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v } else if(n->nodeKind == AST_EXPR_CALL) { generic_visitor(&n->exprCall.what, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); - for(size_t i = 0; i < n->exprCall.what->expression.type->function.argCount; i++) { + for(size_t i = 0; i < n->exprCall.what->expression.type->pointer.of->function.argCount; i++) { generic_visitor(&n->exprCall.args[i], stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); } } else if(n->nodeKind == AST_EXPR_CAST) { @@ -421,7 +421,7 @@ static void ast_usedef_pass(struct UsedefPassState *state, AST *tlc, AST *a, AST } else if(a->nodeKind == AST_EXPR_CALL) { ast_usedef_pass(state, tlc, a->exprCall.what, wholestmt); - for(size_t p = 0; p < a->exprCall.what->expression.type->function.argCount; p++) { + for(size_t p = 0; p < a->exprCall.what->expression.type->pointer.of->function.argCount; p++) { ast_usedef_pass(state, tlc, a->exprCall.args[p], wholestmt); } } else if(a->nodeKind == AST_EXPR_PRIMITIVE) { @@ -698,7 +698,7 @@ static char *ast_dumpe(AST *tlc, AST *e) { char *w = ast_dumpe(tlc, e->exprCall.what); char *out = malp("%s(", w); free(w); - size_t argCount = e->exprCall.what->expression.type->function.argCount; + size_t argCount = e->exprCall.what->expression.type->pointer.of->function.argCount; for(size_t i = 0; i < argCount; i++) { char *a = ast_dumpe(tlc, e->exprCall.args[i]); char *out2 = malp(i == argCount - 1 ? "%s%s)" : "%s%s, ", out, a); diff --git a/src/parse.c b/src/parse.c index 45f4c8e..9c38dd0 100644 --- a/src/parse.c +++ b/src/parse.c @@ -406,13 +406,24 @@ AST *nct_parse_expression(Parser *P, int lOP) { while(peek(P, 0).type == TOKEN_PAREN_L || peek(P, 0).type == TOKEN_SQUAREN_L) { if(maybe(P, TOKEN_PAREN_L)) { - if(ret->expression.type->type != TYPE_TYPE_FUNCTION) { - stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Only function types may be called."); + if(ret->expression.type->type == TYPE_TYPE_FUNCTION) { + ASTExprUnaryOp *ref = alloc_node(P, sizeof(*ref)); + ref->nodeKind = AST_EXPR_UNARY_OP; + ref->type = type_pointer_wrap(ret->expression.type); + ref->operator = UNOP_REF; + ref->operand = ret; + ret = (AST*) ref; } + if(ret->expression.type->type != TYPE_TYPE_POINTER || ret->expression.type->pointer.of->type != TYPE_TYPE_FUNCTION) { + stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Only function types or function pointers may be called."); + } + + Type *ftype = ret->expression.type->pointer.of; + ASTExprCall *call = alloc_node(P, sizeof(*call)); call->nodeKind = AST_EXPR_CALL; - call->type = ret->expression.type->function.ret; + call->type = ftype->function.ret; call->what = ret; call->args = NULL; @@ -421,7 +432,7 @@ AST *nct_parse_expression(Parser *P, int lOP) { if(!maybe(P, TOKEN_PAREN_R)) { while(peek(P, 0).type != TOKEN_PAREN_R && peek(P, 0).type != TOKEN_COMMA) { call->args = realloc(call->args, (argCount + 1) * sizeof(AST*)); - call->args[argCount] = ast_cast_expr(nct_parse_expression(P, 0), ret->expression.type->function.args[argCount]); + call->args[argCount] = ast_cast_expr(nct_parse_expression(P, 0), ftype->function.args[argCount]); argCount++; @@ -431,7 +442,7 @@ AST *nct_parse_expression(Parser *P, int lOP) { } } - if(argCount != call->what->expression.type->function.argCount) { + if(argCount != ftype->function.argCount) { stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Mismatched number of arguments"); } diff --git a/src/x86/cg.c b/src/x86/cg.c index e0908c6..484c2f5 100644 --- a/src/x86/cg.c +++ b/src/x86/cg.c @@ -322,7 +322,7 @@ void cg_chunk(CGState *cg, AST *a) { puts("push ecx"); puts("push edx"); - int argCount = e->exprCall.what->expression.type->function.argCount; + int argCount = e->exprCall.what->expression.type->pointer.of->function.argCount; size_t argSize = 0; @@ -332,9 +332,11 @@ void cg_chunk(CGState *cg, AST *a) { argSize += (type_size(e->exprCall.args[i]->expression.type) + 3) & ~3; } - assert(e->exprCall.what->nodeKind == AST_EXPR_VAR && e->exprCall.what->exprVar.thing->kind == SCOPEITEM_SYMBOL); - - printf("call %s\n", e->exprCall.what->exprVar.thing->data.symbol.name); + if(e->exprCall.what->nodeKind == AST_EXPR_VAR && e->exprCall.what->exprVar.thing->kind == SCOPEITEM_SYMBOL) { + printf("call %s\n", e->exprCall.what->exprVar.thing->data.symbol.name); + } else { + printf("call %s\n", xop(cg->tlc, e->exprCall.what)); + } if(argSize) printf("add esp, %lu\n", argSize); diff --git a/src/x86/dumberdowner.c b/src/x86/dumberdowner.c index 2bf28c2..ac73863 100644 --- a/src/x86/dumberdowner.c +++ b/src/x86/dumberdowner.c @@ -215,7 +215,7 @@ static void dumben_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST * } else if(s->stmtAssign.what && s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == SCOPEITEM_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_CALL) { ASTExprCall *call = &s->stmtAssign.to->exprCall; - int argCount = call->what->expression.type->function.argCount; + int argCount = call->what->expression.type->pointer.of->function.argCount; for(int i = 0; i < argCount; i++) { if(is_xop(call->args[i]) == XOP_NOT_XOP) {