diff options
| -rw-r--r-- | ast.c | 30 | ||||
| -rw-r--r-- | ast.h | 2 | ||||
| -rw-r--r-- | compile.c | 2 | ||||
| -rw-r--r-- | interfaces.c | 13 | ||||
| -rw-r--r-- | parse.c | 5 | ||||
| -rw-r--r-- | typecheck.c | 17 |
6 files changed, 21 insertions, 48 deletions
@@ -136,7 +136,7 @@ CORD ast_to_xml(ast_t *ast) T(StructDef, "<StructDef name=\"%s\">%r<namespace>%r</namespace></StructDef>", data.name, arg_list_to_xml(data.fields), ast_to_xml(data.namespace)) T(EnumDef, "<EnumDef name=\"%s\"><tags>%r</tags><namespace>%r</namespace></EnumDef>", data.name, tags_to_xml(data.tags), ast_to_xml(data.namespace)) T(LangDef, "<LangDef name=\"%s\">%r</LangDef>", data.name, ast_to_xml(data.namespace)) - T(InterfaceDef, "<InterfaceDef name=\"%s\">%r%r</InterfaceDef>", data.name, type_ast_to_xml(data.type_parameter), arg_list_to_xml(data.fields)) + T(InterfaceDef, "<InterfaceDef name=\"%s\">%r</InterfaceDef>", data.name, arg_list_to_xml(data.fields)) T(Index, "<Index>%r%r</Index>", optional_tagged("indexed", data.indexed), optional_tagged("index", data.index)) T(FieldAccess, "<FieldAccess field=\"%s\">%r</FieldAccess>", data.field, ast_to_xml(data.fielded)) T(Optional, "<Optional>%r</Optional>", ast_to_xml(data.value)) @@ -236,32 +236,4 @@ bool type_ast_eq(type_ast_t *x, type_ast_t *y) return true; } -type_ast_t *replace_type_ast(type_ast_t *t, type_ast_t *target, type_ast_t *replacement) -{ - if (!t) return t; - if (type_ast_eq(t, target)) - return replacement; - -#define REPLACED_MEMBER(t, tag, member) ({ t = memcpy(GC_MALLOC(sizeof(type_ast_t)), (t), sizeof(type_ast_t)); Match((struct type_ast_s*)(t), tag)->member = replace_type_ast(Match((t), tag)->member, target, replacement); t; }) - switch (t->tag) { - case UnknownTypeAST: - case VarTypeAST: return t; - case PointerTypeAST: return REPLACED_MEMBER(t, PointerTypeAST, pointed); - case ArrayTypeAST: return REPLACED_MEMBER(t, ArrayTypeAST, item); - case TableTypeAST: { - t = REPLACED_MEMBER(t, TableTypeAST, key); - return REPLACED_MEMBER(t, TableTypeAST, value); - } - case FunctionTypeAST: { - auto fn = Match(t, FunctionTypeAST); - t = REPLACED_MEMBER(t, FunctionTypeAST, ret); - arg_ast_t *args = LIST_MAP(fn->args, old_arg, .type=replace_type_ast(old_arg->type, target, replacement)); - Match((struct type_ast_s*)t, FunctionTypeAST)->args = args; - return t; - } - } - return t; -#undef REPLACED_MEMBER -} - // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 @@ -251,7 +251,6 @@ struct ast_s { } LangDef; struct { const char *name; - type_ast_t *type_parameter; arg_ast_t *fields; ast_t *namespace; } InterfaceDef; @@ -290,6 +289,5 @@ CORD type_ast_to_xml(type_ast_t *ast); int printf_ast(FILE *stream, const struct printf_info *info, const void *const args[]); ast_list_t *get_ast_children(ast_t *ast); bool is_idempotent(ast_t *ast); -type_ast_t *replace_type_ast(type_ast_t *t, type_ast_t *target, type_ast_t *replacement); // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 @@ -1662,8 +1662,6 @@ CORD compile(env_t *env, ast_t *ast) arg_t *type_args = Match(field_t, FunctionType)->args; CORD args = compile_arguments(env, ast, type_args->next, methodcall->args); - if (Match(field_t, FunctionType)->args->type->tag != PointerType) - code_err(ast, "Interface methods that take value types can't be called"); return CORD_all("({ ", compile_type(env, self_value_t), " $self = ", compile_to_pointer_depth(env, methodcall->self, 0, false), "; ", "$self.", methodcall->name, "($self.$obj", diff --git a/interfaces.c b/interfaces.c index db587cba..6406a9ce 100644 --- a/interfaces.c +++ b/interfaces.c @@ -63,14 +63,17 @@ void compile_interface_def(env_t *env, ast_t *ast) CORD_appendf(&env->code->typedefs, "#define %r(...) ((%r_t){__VA_ARGS__})\n", full_name, full_name); CORD_appendf(&env->code->typecode, "struct %r_s {\nvoid *$obj;\n", full_name); - type_ast_t *replacement_type_ast = NewTypeAST(ast->file, ast->start, ast->end, VarTypeAST, .name=def->name); for (arg_ast_t *field = def->fields; field; field = field->next) { - type_ast_t *field_type = replace_type_ast(field->type, def->type_parameter, replacement_type_ast); - type_t *field_t = parse_type_ast(env, field_type); - if (field_t->tag == ClosureType) + type_t *field_t = parse_type_ast(env, field->type); + if (field_t->tag == ClosureType) { field_t = Match(field_t, ClosureType)->fn; - if (field_t->tag != FunctionType) + // Convert to method: + field_t = Type(FunctionType, .args=new(arg_t, .name="$obj", .type=Type(PointerType, .pointed=Type(MemoryType)), + .next=Match(field_t, FunctionType)->args), + .ret=Match(field_t, FunctionType)->ret); + } else { field_t = Type(PointerType, .pointed=field_t); + } CORD decl = compile_declaration(env, field_t, field->name); CORD_appendf(&env->code->typecode, "%r%s;\n", decl, field_t->tag == BoolType ? ":1" : ""); @@ -1825,10 +1825,9 @@ PARSER(parse_interface_def) { if (!match(&pos, "(")) parser_err(ctx, pos, pos, "I expected a '(' and a list of fields here"); - type_ast_t *type_param = expect(ctx, start, &pos, parse_type, "I couldn't parse the type parameter for this interface"); whitespace(&pos); - expect_str(ctx, start, &pos, ";", "I expected a ';' here"); arg_ast_t *fields = parse_args(ctx, &pos, false); + whitespace(&pos); expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this interface definition"); ast_t *namespace = NULL; @@ -1844,7 +1843,7 @@ PARSER(parse_interface_def) { if (!namespace) namespace = NewAST(ctx->file, pos, pos, Block, .statements=NULL); - return NewAST(ctx->file, start, pos, InterfaceDef, .name=name, .type_parameter=type_param, .fields=fields, .namespace=namespace); + return NewAST(ctx->file, start, pos, InterfaceDef, .name=name, .fields=fields, .namespace=namespace); } arg_ast_t *parse_args(parse_ctx_t *ctx, const char **pos, bool allow_unnamed) diff --git a/typecheck.c b/typecheck.c index fa8e3003..c4184579 100644 --- a/typecheck.c +++ b/typecheck.c @@ -272,20 +272,23 @@ void bind_statement(env_t *env, ast_t *statement) arg_t *fields = new(arg_t, .name="$obj", .type=Type(PointerType, .pointed=Type(MemoryType))); // interface implementor type_t *type = Type(InterfaceType, .name=def->name, .fields=fields, .opaque=true, .env=ns_env); // placeholder - type_ast_t *replacement_type_ast = NewTypeAST(statement->file, statement->start, statement->end, VarTypeAST, .name=def->name); Table$str_set(env->types, def->name, type); for (arg_ast_t *field_ast = def->fields; field_ast; field_ast = field_ast->next) { if (!field_ast->type) code_err(field_ast->value, "Interface fields must have defined types, not default values"); - type_ast_t *field_type = replace_type_ast(field_ast->type, def->type_parameter, replacement_type_ast); - type_t *field_t = parse_type_ast(env, field_type); - if (field_t->tag == ClosureType) + type_t *field_t = parse_type_ast(env, field_ast->type); + if (field_t->tag == ClosureType) { field_t = Match(field_t, ClosureType)->fn; - if ((field_t->tag == InterfaceType && Match(field_t, InterfaceType)->opaque) - || (field_t->tag == EnumType && Match(field_t, EnumType)->opaque)) + // Convert to method: + field_t = Type(FunctionType, .args=new(arg_t, .name="$obj", .type=Type(PointerType, .pointed=Type(MemoryType)), + .next=Match(field_t, FunctionType)->args), + .ret=Match(field_t, FunctionType)->ret); + } else if ((field_t->tag == InterfaceType && Match(field_t, InterfaceType)->opaque) + || (field_t->tag == EnumType && Match(field_t, EnumType)->opaque)) { code_err(field_ast->type, "This type is recursive and would create an infinitely sized interface. Try using a pointer."); - if (field_t->tag != FunctionType) + } else { field_t = Type(PointerType, .pointed=field_t); + } fields = new(arg_t, .name=field_ast->name, .type=field_t, .default_val=field_ast->value, .next=fields); } REVERSE_LIST(fields); |
