aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-05-12 20:13:19 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-05-12 20:13:19 -0400
commit02fe49a7646807964d214605a478c90d82d2c8a3 (patch)
treef732f3db3b6d7e2eebed68dc4c6f1af57a313279 /typecheck.c
parent934fd8a173ccad9aa1291c658dbac712eef78b4b (diff)
Deprecate interfaces (RIP)
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c73
1 files changed, 4 insertions, 69 deletions
diff --git a/typecheck.c b/typecheck.c
index 3b70e26e..87f7544c 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -263,46 +263,6 @@ void bind_statement(env_t *env, ast_t *statement)
bind_statement(ns_env, stmt->ast);
break;
}
- case InterfaceDef: {
- auto def = Match(statement, InterfaceDef);
- if (get_binding(env, def->name))
- code_err(statement, "A %T called '%s' has already been defined", get_binding(env, def->name)->type, def->name);
-
- env_t *ns_env = namespace_env(env, def->name);
-
- 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
- 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_t *field_t = parse_type_ast(env, field_ast->type);
- if (field_t->tag == ClosureType) {
- field_t = Match(field_t, ClosureType)->fn;
- // 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.");
- } 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);
- type->__data.InterfaceType.fields = fields; // populate placeholder
- type->__data.InterfaceType.opaque = false;
-
- type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env);
- Table$str_set(env->locals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name)));
-
- for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) {
- bind_statement(ns_env, stmt->ast);
- }
- break;
- }
case Use: {
env_t *module_env = load_module(env, statement);
for (table_t *bindings = module_env->locals; bindings != module_env->globals; bindings = bindings->fallback) {
@@ -593,7 +553,7 @@ type_t *get_type(env_t *env, ast_t *ast)
if (fn_type_t->tag == TypeInfoType) {
type_t *t = Match(fn_type_t, TypeInfoType)->type;
- if (t->tag == StructType || t->tag == InterfaceType || t->tag == IntType || t->tag == NumType)
+ if (t->tag == StructType || t->tag == IntType || t->tag == NumType)
return t; // Constructor
code_err(call->fn, "This is not a type that has a constructor");
}
@@ -634,31 +594,6 @@ type_t *get_type(env_t *env, ast_t *ast)
else if (streq(call->name, "clear")) return Type(VoidType);
else code_err(ast, "There is no '%s' method for tables", call->name);
}
- case InterfaceType: {
- auto methodcall = Match(ast, MethodCall);
- binding_t *b = get_namespace_binding(env, methodcall->self, methodcall->name);
- if (b) {
- if (b->type->tag != FunctionType)
- code_err(ast, "'%s' is not a function, it's a %T", methodcall->name, b->type);
- return Match(b->type, FunctionType)->ret;
- } else {
- auto interface = Match(self_value_t, InterfaceType);
- for (arg_t *field = interface->fields; field; field = field->next) {
- if (streq(field->name, methodcall->name)) {
- env_t tmp_env = *env;
- tmp_env.types = new(table_t, .fallback=tmp_env.types);
- Table$str_set(tmp_env.types, interface->type_parameter, self_value_t);
- type_t *field_t = field->type;
- if (field_t->tag == ClosureType)
- field_t = Match(field_t, ClosureType)->fn;
- if (field_t->tag != FunctionType)
- code_err(ast, "'%s' is not a function, it's a %T", methodcall->name, b->type);
- return Match(field_t, FunctionType)->ret;
- }
- }
- code_err(ast, "There is no method called '%s' on the interface type %s", methodcall->name, interface->name);
- }
- }
default: {
type_t *fn_type_t = get_method_type(env, call->self, call->name);
if (!fn_type_t)
@@ -680,7 +615,7 @@ type_t *get_type(env_t *env, ast_t *ast)
// Early out if the type is knowable without any context from the block:
switch (last->ast->tag) {
- case UpdateAssign: case Assign: case Declare: case FunctionDef: case StructDef: case EnumDef: case LangDef: case InterfaceDef:
+ case UpdateAssign: case Assign: case Declare: case FunctionDef: case StructDef: case EnumDef: case LangDef:
return Type(VoidType);
default: break;
}
@@ -857,7 +792,7 @@ type_t *get_type(env_t *env, ast_t *ast)
return Type(ClosureType, Type(FunctionType, .args=args, .ret=ret));
}
- case FunctionDef: case StructDef: case EnumDef: case LangDef: case InterfaceDef: {
+ case FunctionDef: case StructDef: case EnumDef: case LangDef: {
return Type(VoidType);
}
@@ -996,7 +931,7 @@ type_t *get_type(env_t *env, ast_t *ast)
bool is_discardable(env_t *env, ast_t *ast)
{
switch (ast->tag) {
- case UpdateAssign: case Assign: case Declare: case FunctionDef: case StructDef: case EnumDef: case LangDef: case InterfaceDef: case Use:
+ case UpdateAssign: case Assign: case Declare: case FunctionDef: case StructDef: case EnumDef: case LangDef: case Use:
return true;
default: break;
}