aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-04-23 12:50:30 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-04-23 12:50:30 -0400
commitfbb25decf062349b0f28b3027d6be34a11f2a812 (patch)
treeecbbf62e677833fcaff5e4033d92f43099fa6049 /typecheck.c
parent803995aea2b1012355c929a7e148d500cd253997 (diff)
Support struct literals as constants
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/typecheck.c b/typecheck.c
index 72551d97..38071c21 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -953,4 +953,40 @@ type_t *parse_type_string(env_t *env, const char *str)
return ast ? parse_type_ast(env, ast) : NULL;
}
+bool is_constant(env_t *env, ast_t *ast)
+{
+ switch (ast->tag) {
+ case Bool: case Int: case Num: case Nil: case TextLiteral: return true;
+ case TextJoin: {
+ auto text = Match(ast, TextJoin);
+ return !text->children || !text->children->next;
+ }
+ case Not: return is_constant(env, Match(ast, Not)->value);
+ case Negative: return is_constant(env, Match(ast, Negative)->value);
+ case BinaryOp: {
+ auto binop = Match(ast, BinaryOp);
+ switch (binop->op) {
+ case BINOP_UNKNOWN: case BINOP_POWER: case BINOP_CONCAT: case BINOP_MIN: case BINOP_MAX: case BINOP_CMP:
+ return false;
+ default:
+ return is_constant(env, binop->lhs) && is_constant(env, binop->rhs);
+ }
+ }
+ case Use: return true;
+ case FunctionCall: {
+ // Constructors are allowed:
+ auto call = Match(ast, FunctionCall);
+ if (call->fn->tag != Var) return false;
+ binding_t *b = get_binding(env, Match(call->fn, Var)->name);
+ if (b == NULL || b->type->tag != TypeInfoType) return false;
+ for (arg_ast_t *arg = call->args; arg; arg = arg->next) {
+ if (!is_constant(env, arg->value))
+ return false;
+ }
+ return true;
+ }
+ default: return false;
+ }
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0