diff options
| -rw-r--r-- | ast.h | 2 | ||||
| -rw-r--r-- | compile.c | 20 | ||||
| -rw-r--r-- | parse.c | 28 | ||||
| -rw-r--r-- | test/extern.tm | 3 | ||||
| -rw-r--r-- | typecheck.c | 13 |
5 files changed, 39 insertions, 27 deletions
@@ -194,7 +194,6 @@ struct ast_s { struct { ast_t *fn; arg_ast_t *args; - type_ast_t *extern_return_type; } FunctionCall; struct { const char *name; @@ -231,7 +230,6 @@ struct ast_s { struct { const char *name; type_ast_t *type; - bool address; } Extern; struct { const char *name; @@ -58,7 +58,6 @@ static bool promote(env_t *env, CORD *code, type_t *actual, type_t *needed) return false; } - CORD compile_declaration(env_t *env, type_t *t, const char *name) { if (t->tag == FunctionType) { @@ -735,6 +734,25 @@ CORD compile_statement(env_t *env, ast_t *ast) return compile_statement(env, loop); } } + case Extern: { + auto ext = Match(ast, Extern); + type_t *t = parse_type_ast(env, ext->type); + CORD decl; + if (t->tag == ClosureType) { + t = Match(t, ClosureType)->fn; + auto fn = Match(t, FunctionType); + decl = CORD_all(compile_type(env, fn->ret), " ", ext->name, "("); + for (arg_t *arg = fn->args; arg; arg = arg->next) { + decl = CORD_all(decl, compile_type(env, arg->type)); + if (arg->next) decl = CORD_cat(decl, ", "); + } + decl = CORD_cat(decl, ")"); + } else { + decl = compile_declaration(env, t, ext->name); + } + env->code->fndefs = CORD_all(env->code->fndefs, "extern ", decl, ";\n"); + return CORD_EMPTY; + } case InlineCCode: return Match(ast, InlineCCode)->code; default: return CORD_asprintf("(void)%r;", compile(env, ast)); @@ -65,7 +65,7 @@ static inline const char* get_id(const char **pos); static inline bool comment(const char **pos); static inline bool indent(parse_ctx_t *ctx, const char **pos); static inline binop_e match_binary_operator(const char **pos); -static ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn, bool is_extern); +static ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn); static ast_t *parse_method_call_suffix(parse_ctx_t *ctx, ast_t *self); static ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs); static ast_t *parse_index_suffix(parse_ctx_t *ctx, ast_t *lhs); @@ -753,7 +753,7 @@ PARSER(parse_reduction) { || (new_term=parse_index_suffix(ctx, key)) || (new_term=parse_field_suffix(ctx, key)) || (new_term=parse_method_call_suffix(ctx, key)) - || (new_term=parse_fncall_suffix(ctx, key, NORMAL_FUNCTION)) + || (new_term=parse_fncall_suffix(ctx, key)) ); if (progress) key = new_term; } @@ -1211,7 +1211,7 @@ PARSER(parse_term) { || (new_term=parse_index_suffix(ctx, term)) || (new_term=parse_field_suffix(ctx, term)) || (new_term=parse_method_call_suffix(ctx, term)) - || (new_term=parse_fncall_suffix(ctx, term, NORMAL_FUNCTION)) + || (new_term=parse_fncall_suffix(ctx, term)) ); if (progress) term = new_term; } @@ -1260,7 +1260,7 @@ ast_t *parse_method_call_suffix(parse_ctx_t *ctx, ast_t *self) { return NewAST(ctx->file, start, pos, MethodCall, .self=self, .name=fn, .args=args); } -ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn, bool is_extern) { +ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn) { if (!fn) return NULL; const char *start = fn->start; @@ -1296,15 +1296,8 @@ ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn, bool is_extern) { if (!match(&pos, ")")) parser_err(ctx, start, pos, "This parenthesis is unclosed"); - type_ast_t *extern_return_type = NULL; - if (is_extern) { - if (match(&pos, ":")) - extern_return_type = expect(ctx, start, &pos, parse_type, "I couldn't parse the return type of this external function call"); - else - extern_return_type = NewTypeAST(ctx->file, pos, pos, VarTypeAST, .name="Void"); - } REVERSE_LIST(args); - return NewAST(ctx->file, start, pos, FunctionCall, .fn=fn, .args=args, .extern_return_type=extern_return_type); + return NewAST(ctx->file, start, pos, FunctionCall, .fn=fn, .args=args); } binop_e match_binary_operator(const char **pos) @@ -1355,7 +1348,7 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn || (new_term=parse_index_suffix(ctx, key)) || (new_term=parse_field_suffix(ctx, key)) || (new_term=parse_method_call_suffix(ctx, key)) - || (new_term=parse_fncall_suffix(ctx, key, NORMAL_FUNCTION)) + || (new_term=parse_fncall_suffix(ctx, key)) ); if (progress) key = new_term; } @@ -1469,7 +1462,7 @@ PARSER(parse_statement) { if (stmt->tag == Var) progress = (false || (new_stmt=parse_method_call_suffix(ctx, stmt)) - || (new_stmt=parse_fncall_suffix(ctx, stmt, NORMAL_FUNCTION)) + || (new_stmt=parse_fncall_suffix(ctx, stmt)) ); if (progress) stmt = new_stmt; @@ -1828,17 +1821,12 @@ PARSER(parse_extern) { const char *start = pos; if (!match_word(&pos, "extern")) return NULL; spaces(&pos); - bool address = (match(&pos, "&") != 0); const char* name = get_id(&pos); spaces(&pos); - // extern function call: - if (match(&pos, "(")) { - return parse_fncall_suffix(ctx, NewAST(ctx->file, start, pos-1, Var, .name=name), EXTERN_FUNCTION); - } if (!match(&pos, ":")) parser_err(ctx, start, pos, "I couldn't get a type for this extern"); type_ast_t *type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this extern"); - return NewAST(ctx->file, start, pos, Extern, .name=name, .type=type, .address=address); + return NewAST(ctx->file, start, pos, Extern, .name=name, .type=type); } PARSER(parse_doctest) { diff --git a/test/extern.tm b/test/extern.tm new file mode 100644 index 00000000..a02a6a85 --- /dev/null +++ b/test/extern.tm @@ -0,0 +1,3 @@ +extern CORD_cat:func(a:Text, b:Text)->Text +>> CORD_cat("hello ", "world") += "hello world" diff --git a/typecheck.c b/typecheck.c index 615abe74..5a05d122 100644 --- a/typecheck.c +++ b/typecheck.c @@ -233,6 +233,14 @@ void bind_statement(env_t *env, ast_t *statement) Table_str_set(env->imports, name, module_env); break; } + case Extern: { + auto ext = Match(statement, Extern); + type_t *t = parse_type_ast(env, ext->type); + if (t->tag == ClosureType) + t = Match(t, ClosureType)->fn; + set_binding(env, ext->name, new(binding_t, .type=t, .code=ext->name)); + break; + } default: break; } } @@ -471,8 +479,6 @@ type_t *get_type(env_t *env, ast_t *ast) } case FunctionCall: { auto call = Match(ast, FunctionCall); - if (call->extern_return_type) - return parse_type_ast(env, call->extern_return_type); type_t *fn_type_t = get_type(env, call->fn); if (!fn_type_t) code_err(call->fn, "I couldn't find this function"); @@ -547,8 +553,7 @@ type_t *get_type(env_t *env, ast_t *ast) return get_type(block_env, last->ast); } case Extern: { - type_t *t = parse_type_ast(env, Match(ast, Extern)->type); - return Match(ast, Extern)->address ? Type(PointerType, .pointed=t, .is_optional=false) : t; + return parse_type_ast(env, Match(ast, Extern)->type); } case Declare: case Assign: case DocTest: case LinkerDirective: { return Type(VoidType); |
