aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-03-08 14:23:16 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-03-08 14:23:16 -0500
commit07c2b0ec26600d8609870d9f5c0867d48b801db4 (patch)
tree9c7f5cf8c394312e3da4a2371081d2a64b622b6e /typecheck.c
parent8e62018546cd9beb357b0452535cf216c7cfa0cc (diff)
Array methods
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/typecheck.c b/typecheck.c
index ac6ed811..47fe8c64 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -403,13 +403,41 @@ type_t *get_type(env_t *env, ast_t *ast)
}
case MethodCall: {
auto call = Match(ast, MethodCall);
- type_t *fn_type_t = get_method_type(env, call->self, call->name);
- if (!fn_type_t)
- code_err(ast, "No such method!");
- if (fn_type_t->tag != FunctionType)
- code_err(ast, "This isn't a method, it's a %T", fn_type_t);
- auto fn_type = Match(fn_type_t, FunctionType);
- return fn_type->ret;
+ type_t *self_value_t = value_type(get_type(env, call->self));
+ switch (self_value_t->tag) {
+ case ArrayType: {
+ if (streq(call->name, "insert")) return Type(VoidType);
+ else if (streq(call->name, "insert_all")) return Type(VoidType);
+ else if (streq(call->name, "remove")) return Type(VoidType);
+ else if (streq(call->name, "sort")) return Type(VoidType);
+ else if (streq(call->name, "shuffle")) return Type(VoidType);
+ else if (streq(call->name, "random"))
+ return Type(PointerType, .pointed=Match(self_value_t, ArrayType)->item_type, .is_optional=true, .is_readonly=true);
+ else if (streq(call->name, "clear")) return Type(VoidType);
+ else if (streq(call->name, "compact")) return Type(VoidType);
+ else if (streq(call->name, "contains")) return Type(VoidType);
+ else if (streq(call->name, "slice")) return self_value_t;
+ else if (streq(call->name, "concat")) return self_value_t;
+ else code_err(ast, "There is no '%s' method for arrays", call->name);
+ }
+ case TableType: {
+ auto table = Match(self_value_t, TableType);
+ if (streq(call->name, "get")) return Type(PointerType, .pointed=table->value_type, .is_readonly=true, .is_optional=true);
+ else if (streq(call->name, "set")) return Type(VoidType);
+ else if (streq(call->name, "remove")) return Type(VoidType);
+ else if (streq(call->name, "clear")) return Type(VoidType);
+ else code_err(ast, "There is no '%s' method for tables", call->name);
+ }
+ default: {
+ type_t *fn_type_t = get_method_type(env, call->self, call->name);
+ if (!fn_type_t)
+ code_err(ast, "No such method!");
+ if (fn_type_t->tag != FunctionType)
+ code_err(ast, "This isn't a method, it's a %T", fn_type_t);
+ auto fn_type = Match(fn_type_t, FunctionType);
+ return fn_type->ret;
+ }
+ }
}
case Block: {
auto block = Match(ast, Block);