aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-04-10 11:49:43 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-04-10 11:49:43 -0400
commit4f514378accd7a5ed8774d008761efa94f383148 (patch)
tree1682ac995b84327bee6ac29cd379aea4f02fa5ae
parent438edf45c27da9aa2503a5bcf50f34475c8bc63d (diff)
Fix corecursive functions and global variables
-rw-r--r--ast.c23
-rw-r--r--ast.h1
-rw-r--r--compile.c26
3 files changed, 46 insertions, 4 deletions
diff --git a/ast.c b/ast.c
index 80681e10..25309e93 100644
--- a/ast.c
+++ b/ast.c
@@ -196,4 +196,27 @@ bool is_idempotent(ast_t *ast)
}
}
+bool is_constant(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->next;
+ }
+ case Not: return is_constant(Match(ast, Not)->value);
+ case Negative: return is_constant(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(binop->lhs) && is_constant(binop->rhs);
+ }
+ }
+ default: return false;
+ }
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/ast.h b/ast.h
index 658f44c5..1f0eb5a4 100644
--- a/ast.h
+++ b/ast.h
@@ -279,5 +279,6 @@ 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);
+bool is_constant(ast_t *ast);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/compile.c b/compile.c
index 335134e8..0e23c948 100644
--- a/compile.c
+++ b/compile.c
@@ -443,7 +443,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
code = CORD_cat("public ", code);
}
- env_t *body_scope = global_scope(env);
+ env_t *body_scope = fresh_scope(env);
for (arg_ast_t *arg = fndef->args; arg; arg = arg->next) {
type_t *arg_type = get_arg_ast_type(env, arg);
set_binding(body_scope, arg->name, new(binding_t, .type=arg_type, .code=arg->name));
@@ -1887,9 +1887,27 @@ module_code_t compile_file(ast_t *ast)
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
bind_statement(env, stmt->ast);
- CORD code = compile_statement(env, stmt->ast);
- if (code)
- CORD_appendf(&env->code->main, "%r\n", code);
+ }
+ for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
+ if (stmt->ast->tag == Declare) {
+ auto decl = Match(stmt->ast, Declare);
+ type_t *t = get_type(env, decl->value);
+ if (t->tag == AbortType || t->tag == VoidType)
+ code_err(stmt->ast, "You can't declare a variable with a %T value", t);
+ if (!is_constant(decl->value))
+ code_err(decl->value, "This value is not a valid constant initializer.");
+ env->code->fndefs = CORD_all(
+ env->code->fndefs,
+ compile_declaration(env, t, Match(decl->var, Var)->name), ";\n");
+ env->code->staticdefs = CORD_all(
+ env->code->staticdefs,
+ "extern ", compile_type(env, t), " ", Match(decl->var, Var)->name, " = ",
+ compile(env, decl->value), ";\n");
+ } else {
+ CORD code = compile_statement(env, stmt->ast);
+ if (code)
+ CORD_appendf(&env->code->main, "%r\n", code);
+ }
}
return (module_code_t){