aboutsummaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-07-04 13:37:23 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-07-04 13:37:23 -0400
commit22063462a90b5c290f5f71319b259fca80da8097 (patch)
tree67d403f893415de9202477608ae9972b9171df88 /compile.c
parentdc1616a3bf7d075e0b50f783313ea6a5b1076fb4 (diff)
Add __length and __negative metamethods
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/compile.c b/compile.c
index bfd23925..d314e40c 100644
--- a/compile.c
+++ b/compile.c
@@ -1131,7 +1131,16 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("I64((", table, ").entries.length)");
}
}
- default: code_err(ast, "Length is only supported for strings, arrays, and tables, not: %T", t);
+ default: {
+ binding_t *b = get_namespace_binding(env, expr, "__length");
+ if (b && b->type->tag == FunctionType) {
+ auto fn = Match(b->type, FunctionType);
+ if (type_eq(fn->ret, INT_TYPE) && fn->args && can_promote(t, get_arg_type(env, fn->args)))
+ return CORD_all(b->code, "(", compile_arguments(env, ast, fn->args, new(arg_ast_t, .value=expr)), ")");
+ }
+
+ code_err(ast, "Length is not implemented for %T values", t);
+ }
}
break;
}
@@ -1149,7 +1158,22 @@ CORD compile(env_t *env, ast_t *ast)
else
code_err(ast, "I don't know how to negate values of type %T", t);
}
- case Negative: return CORD_asprintf("-(%r)", compile(env, Match(ast, Negative)->value));
+ case Negative: {
+ ast_t *value = Match(ast, Negative)->value;
+ type_t *t = get_type(env, value);
+ if (t->tag == IntType || t->tag == NumType)
+ return CORD_all("-(", compile(env, value), ")");
+
+ binding_t *b = get_namespace_binding(env, value, "__negative");
+ if (b && b->type->tag == FunctionType) {
+ auto fn = Match(b->type, FunctionType);
+ if (fn->args && can_promote(t, get_arg_type(env, fn->args)))
+ return CORD_all(b->code, "(", compile_arguments(env, ast, fn->args, new(arg_ast_t, .value=value)), ")");
+ }
+
+ code_err(ast, "I don't know how to get the negative value of type %T", t);
+
+ }
case HeapAllocate: return CORD_asprintf("heap(%r)", compile(env, Match(ast, HeapAllocate)->value));
case StackReference: {
ast_t *subject = Match(ast, StackReference)->value;