aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-21 00:48:08 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-21 00:49:22 -0400
commit2055439be4f5053b9a4d631cefd8bb7c83a8e4e3 (patch)
treedb1a03b349222801e8e80270ce20ea2148389f0a
parent3c4f477b845ac6b462547da820f4550faf3cbb7c (diff)
Variables can no longer hold function pointers, only closure_t's. This
makes error reporting easier and prevents issues where some functions could be assigned, but not others. Also change outputs so Void returns don't show up when displaying types, now just: `func()`
-rw-r--r--compile.c52
-rw-r--r--environment.c8
-rw-r--r--typecheck.c2
-rw-r--r--types.c6
4 files changed, 53 insertions, 15 deletions
diff --git a/compile.c b/compile.c
index 2c509495..77ad9882 100644
--- a/compile.c
+++ b/compile.c
@@ -343,13 +343,17 @@ CORD compile_statement(env_t *env, ast_t *ast)
(int64_t)(test->expr->end - test->expr->file->text));
} else {
CORD var = CORD_all("$", Match(decl->var, Var)->name);
+ type_t *t = get_type(env, decl->value);
+ CORD val_code = compile_maybe_incref(env, decl->value);
+ if (t->tag == FunctionType) {
+ assert(promote(env, &val_code, t, Type(ClosureType, t)));
+ t = Type(ClosureType, t);
+ }
return CORD_asprintf(
"%r;\n"
"test(({ %r = %r; &%r;}), %r, %r, %r, %ld, %ld);\n",
- compile_declaration(get_type(env, decl->value), var),
- var,
- compile_maybe_incref(env, decl->value),
- var,
+ compile_declaration(t, var),
+ var, val_code, var,
compile_type_info(env, get_type(env, decl->value)),
compile(env, WrapAST(test->expr, TextLiteral, .cord=output)),
compile(env, WrapAST(test->expr, TextLiteral, .cord=test->expr->file->filename)),
@@ -454,7 +458,14 @@ CORD compile_statement(env_t *env, ast_t *ast)
type_t *t = get_type(env, decl->value);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
code_err(ast, "You can't declare a variable with a %T value", t);
- return CORD_all(compile_declaration(t, CORD_cat("$", Match(decl->var, Var)->name)), " = ", compile_maybe_incref(env, decl->value), ";");
+
+ CORD val_code = compile_maybe_incref(env, decl->value);
+ if (t->tag == FunctionType) {
+ assert(promote(env, &val_code, t, Type(ClosureType, t)));
+ t = Type(ClosureType, t);
+ }
+
+ return CORD_all(compile_declaration(t, CORD_cat("$", Match(decl->var, Var)->name)), " = ", val_code, ";");
}
}
case Assign: {
@@ -2828,20 +2839,30 @@ void compile_namespace(env_t *env, const char *ns_name, ast_t *block)
case Declare: {
auto decl = Match(ast, Declare);
type_t *t = get_type(ns_env, decl->value);
+ if (t->tag == FunctionType)
+ t = Type(ClosureType, t);
bool is_private = (Match(decl->var, Var)->name[0] == '_');
CORD name_code = CORD_all(prefix, Match(decl->var, Var)->name);
if (!is_constant(env, decl->value)) {
+ if (t->tag == FunctionType)
+ t = Type(ClosureType, t);
+
env->code->staticdefs = CORD_all(
env->code->staticdefs,
"static bool ", name_code, "$initialized = false;\n",
is_private ? "static " : CORD_EMPTY,
compile_declaration(t, name_code), ";\n");
} else {
+ CORD val_code = compile_maybe_incref(ns_env, decl->value);
+ if (t->tag == FunctionType) {
+ assert(promote(env, &val_code, t, Type(ClosureType, t)));
+ t = Type(ClosureType, t);
+ }
+
env->code->staticdefs = CORD_all(
env->code->staticdefs,
is_private ? "static " : CORD_EMPTY,
- compile_declaration(t, name_code), " = ",
- compile(ns_env, decl->value), ";\n");
+ compile_declaration(t, name_code), " = ", val_code, ";\n");
}
break;
}
@@ -3098,9 +3119,15 @@ CORD compile_file(env_t *env, ast_t *ast)
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
code_err(stmt->ast, "You can't declare a variable with a %T value", t);
if (!(decl->value->tag == Use || decl->value->tag == Import || is_constant(env, decl->value))) {
+ CORD val_code = compile_maybe_incref(env, decl->value);
+ if (t->tag == FunctionType) {
+ assert(promote(env, &val_code, t, Type(ClosureType, t)));
+ t = Type(ClosureType, t);
+ }
+
env->code->variable_initializers = CORD_all(
env->code->variable_initializers,
- full_name, " = ", compile_maybe_incref(env, decl->value), ",\n",
+ full_name, " = ", val_code, ",\n",
full_name, "$initialized = true;\n");
CORD checked_access = CORD_all("check_initialized(", full_name, ", \"", decl_name, "\")");
@@ -3125,10 +3152,15 @@ CORD compile_file(env_t *env, ast_t *ast)
is_private ? "static " : CORD_EMPTY,
compile_declaration(t, full_name), ";\n");
} else {
+ CORD val_code = compile_maybe_incref(env, decl->value);
+ if (t->tag == FunctionType) {
+ assert(promote(env, &val_code, t, Type(ClosureType, t)));
+ t = Type(ClosureType, t);
+ }
env->code->staticdefs = CORD_all(
env->code->staticdefs,
is_private ? "static " : CORD_EMPTY,
- compile_declaration(t, full_name), " = ", compile(env, decl->value), ";\n");
+ compile_declaration(t, full_name), " = ", val_code, ";\n");
}
} else if (stmt->ast->tag == InlineCCode) {
CORD code = compile_statement(env, stmt->ast);
@@ -3235,6 +3267,8 @@ CORD compile_statement_definitions(env_t *env, ast_t *ast)
return compile_statement_definitions(env, decl->value);
}
type_t *t = get_type(env, decl->value);
+ if (t->tag == FunctionType)
+ t = Type(ClosureType, t);
assert(t->tag != ModuleType);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
code_err(ast, "You can't declare a variable with a %T value", t);
diff --git a/environment.c b/environment.c
index 460ec0df..c81e1921 100644
--- a/environment.c
+++ b/environment.c
@@ -269,10 +269,10 @@ env_t *new_compilation_unit(CORD *libname)
{"without", "Text$without", "func(text:Text, target:Text, where=Where.Anywhere)->Text"},
)},
{"Thread", THREAD_TYPE, "pthread_t*", "Thread", TypedArray(ns_entry_t,
- {"new", "Thread$new", "func(fn:func()->Void)->Thread"},
- {"cancel", "Thread$cancel", "func(thread:Thread)->Void"},
- {"join", "Thread$join", "func(thread:Thread)->Void"},
- {"detach", "Thread$detach", "func(thread:Thread)->Void"},
+ {"new", "Thread$new", "func(fn:func())->Thread"},
+ {"cancel", "Thread$cancel", "func(thread:Thread)"},
+ {"join", "Thread$join", "func(thread:Thread)"},
+ {"detach", "Thread$detach", "func(thread:Thread)"},
)},
};
diff --git a/typecheck.c b/typecheck.c
index 43be2b97..410619a5 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -262,6 +262,8 @@ void bind_statement(env_t *env, ast_t *statement)
bind_statement(env, decl->value);
}
type_t *type = get_type(env, decl->value);
+ if (type->tag == FunctionType)
+ type = Type(ClosureType, type);
CORD prefix = namespace_prefix(env->libname, env->namespace);
CORD code = CORD_cat(prefix ? prefix : "$", name);
set_binding(env, name, new(binding_t, .type=type, .code=code));
diff --git a/types.c b/types.c
index 5fb591ca..cc35d792 100644
--- a/types.c
+++ b/types.c
@@ -51,8 +51,10 @@ CORD type_to_cord(type_t *t) {
c = CORD_cat(c, type_to_cord(arg->type));
if (arg->next) c = CORD_cat(c, ", ");
}
- c = CORD_cat(c, ")->");
- c = CORD_cat(c, type_to_cord(fn->ret));
+ if (fn->ret && fn->ret->tag != VoidType)
+ c = CORD_all(c, ")->", type_to_cord(fn->ret));
+ else
+ c = CORD_all(c, ")");
return c;
}
case StructType: {