Tweak set_binding()
API
This commit is contained in:
parent
be87d8169d
commit
66eca49d18
66
compile.c
66
compile.c
@ -292,7 +292,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
|
||||
auto lambda = Match(ast, Lambda);
|
||||
env_t *lambda_scope = fresh_scope(env);
|
||||
for (arg_ast_t *arg = lambda->args; arg; arg = arg->next)
|
||||
set_binding(lambda_scope, arg->name, new(binding_t, .type=get_arg_ast_type(env, arg)));
|
||||
set_binding(lambda_scope, arg->name, get_arg_ast_type(env, arg), CORD_all("_$", arg->name));
|
||||
add_closed_vars(closed_vars, enclosing_scope, lambda_scope, lambda->body);
|
||||
break;
|
||||
}
|
||||
@ -339,7 +339,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
|
||||
type_t *cond_t = get_type(truthy_scope, var);
|
||||
if (cond_t->tag == OptionalType) {
|
||||
set_binding(truthy_scope, Match(var, Var)->name,
|
||||
new(binding_t, .type=Match(cond_t, OptionalType)->type));
|
||||
Match(cond_t, OptionalType)->type, CORD_EMPTY);
|
||||
}
|
||||
add_closed_vars(closed_vars, enclosing_scope, truthy_scope, if_->body);
|
||||
add_closed_vars(closed_vars, enclosing_scope, env, if_->else_body);
|
||||
@ -349,7 +349,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
|
||||
if (condition->tag == Var && cond_t->tag == OptionalType) {
|
||||
truthy_scope = fresh_scope(env);
|
||||
set_binding(truthy_scope, Match(condition, Var)->name,
|
||||
new(binding_t, .type=Match(cond_t, OptionalType)->type));
|
||||
Match(cond_t, OptionalType)->type, CORD_EMPTY);
|
||||
}
|
||||
add_closed_vars(closed_vars, enclosing_scope, truthy_scope, if_->body);
|
||||
add_closed_vars(closed_vars, enclosing_scope, env, if_->else_body);
|
||||
@ -377,7 +377,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
|
||||
auto tag_struct = Match(tag_type, StructType);
|
||||
if (clause->args && !clause->args->next && tag_struct->fields && tag_struct->fields->next) {
|
||||
scope = fresh_scope(scope);
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, new(binding_t, .type=tag_type));
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, tag_type, CORD_EMPTY);
|
||||
} else if (clause->args) {
|
||||
scope = fresh_scope(scope);
|
||||
ast_list_t *var = clause->args;
|
||||
@ -387,7 +387,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
|
||||
code_err(clause->tag_name, "The field %T.%s.%s wasn't accounted for", subject_t, clause_tag_name, field->name);
|
||||
if (!field)
|
||||
code_err(var->ast, "This is one more field than %T has", subject_t);
|
||||
set_binding(scope, Match(var->ast, Var)->name, new(binding_t, .type=field->type));
|
||||
set_binding(scope, Match(var->ast, Var)->name, field->type, CORD_EMPTY);
|
||||
var = var->next;
|
||||
field = field->next;
|
||||
}
|
||||
@ -458,7 +458,7 @@ static Table_t get_closed_vars(env_t *env, arg_ast_t *args, ast_t *block)
|
||||
env_t *body_scope = fresh_scope(env);
|
||||
for (arg_ast_t *arg = 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=CORD_cat("_$", arg->name)));
|
||||
set_binding(body_scope, arg->name, arg_type, CORD_cat("_$", arg->name));
|
||||
}
|
||||
|
||||
Table_t closed_vars = {};
|
||||
@ -774,7 +774,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
if (clause->args && !clause->args->next && tag_struct->fields && tag_struct->fields->next) {
|
||||
code = CORD_all(code, compile_declaration(tag_type, compile(env, clause->args->ast)), " = subject.$", clause_tag_name, ";\n");
|
||||
scope = fresh_scope(scope);
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, new(binding_t, .type=tag_type));
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, tag_type, CORD_EMPTY);
|
||||
} else if (clause->args) {
|
||||
scope = fresh_scope(scope);
|
||||
ast_list_t *var = clause->args;
|
||||
@ -785,7 +785,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
if (!field)
|
||||
code_err(var->ast, "This is one more field than %T has", subject_t);
|
||||
code = CORD_all(code, compile_declaration(field->type, compile(env, var->ast)), " = subject.$", clause_tag_name, ".$", field->name, ";\n");
|
||||
set_binding(scope, Match(var->ast, Var)->name, new(binding_t, .type=field->type));
|
||||
set_binding(scope, Match(var->ast, Var)->name, field->type, CORD_EMPTY);
|
||||
var = var->next;
|
||||
field = field->next;
|
||||
}
|
||||
@ -1201,7 +1201,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
body_scope->namespace = NULL;
|
||||
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=CORD_cat("_$", arg->name)));
|
||||
set_binding(body_scope, arg->name, arg_type, CORD_cat("_$", arg->name));
|
||||
}
|
||||
|
||||
body_scope->fn_ret = ret_t;
|
||||
@ -1387,12 +1387,12 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
if (entry->b->type->tag == ModuleType)
|
||||
continue;
|
||||
if (CORD_ncmp(entry->b->code, 0, "userdata->", 0, strlen("userdata->")) == 0) {
|
||||
set_binding(defer_env, entry->name, entry->b);
|
||||
Table$str_set(defer_env->locals, entry->name, entry->b);
|
||||
} else {
|
||||
CORD defer_name = CORD_asprintf("defer$%d$%s", ++defer_id, entry->name);
|
||||
code = CORD_all(
|
||||
code, compile_declaration(entry->b->type, defer_name), " = ", entry->b->code, ";\n");
|
||||
set_binding(defer_env, entry->name, new(binding_t, .type=entry->b->type, .code=defer_name));
|
||||
set_binding(defer_env, entry->name, entry->b->type, defer_name);
|
||||
}
|
||||
}
|
||||
env->deferred = new(deferral_t, .defer_env=defer_env, .block=body, .next=env->deferred);
|
||||
@ -1493,8 +1493,8 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
.next=body_scope->deferred);
|
||||
if (held->tag == Var) {
|
||||
CORD held_var = CORD_all(Match(held, Var)->name, "$held");
|
||||
set_binding(body_scope, Match(held, Var)->name, new(binding_t, .type=Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true),
|
||||
.code=held_var));
|
||||
set_binding(body_scope, Match(held, Var)->name,
|
||||
Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true), held_var);
|
||||
code = CORD_all(code, compile_declaration(Type(PointerType, .pointed=Match(held_type, MutexedType)->type), held_var),
|
||||
" = (", compile_type(Type(PointerType, .pointed=Match(held_type, MutexedType)->type)), ")mutexed->data;\n");
|
||||
}
|
||||
@ -1795,8 +1795,8 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
type_t *cond_t = get_type(truthy_scope, var);
|
||||
if (cond_t->tag == OptionalType) {
|
||||
set_binding(truthy_scope, Match(var, Var)->name,
|
||||
new(binding_t, .type=Match(cond_t, OptionalType)->type,
|
||||
.code=optional_into_nonnone(cond_t, compile(truthy_scope, var))));
|
||||
Match(cond_t, OptionalType)->type,
|
||||
optional_into_nonnone(cond_t, compile(truthy_scope, var)));
|
||||
}
|
||||
code = CORD_all(code, compile_statement(truthy_scope, if_->body), ")");
|
||||
if (if_->else_body)
|
||||
@ -1809,8 +1809,8 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
|
||||
if (condition->tag == Var && cond_t->tag == OptionalType) {
|
||||
truthy_scope = fresh_scope(env);
|
||||
set_binding(truthy_scope, Match(condition, Var)->name,
|
||||
new(binding_t, .type=Match(cond_t, OptionalType)->type,
|
||||
.code=optional_into_nonnone(cond_t, compile(truthy_scope, condition))));
|
||||
Match(cond_t, OptionalType)->type,
|
||||
optional_into_nonnone(cond_t, compile(truthy_scope, condition)));
|
||||
}
|
||||
code = CORD_all(code, compile_statement(truthy_scope, if_->body));
|
||||
if (if_->else_body)
|
||||
@ -1988,7 +1988,7 @@ env_t *with_enum_scope(env_t *env, type_t *t)
|
||||
continue;
|
||||
binding_t *b = get_binding(ns_env, tag->name);
|
||||
assert(b);
|
||||
set_binding(env, tag->name, b);
|
||||
Table$str_set(env->locals, tag->name, b);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
@ -2465,8 +2465,8 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
.next=body_scope->deferred);
|
||||
if (held->tag == Var) {
|
||||
CORD held_var = CORD_all(Match(held, Var)->name, "$held");
|
||||
set_binding(body_scope, Match(held, Var)->name, new(binding_t, .type=Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true),
|
||||
.code=held_var));
|
||||
set_binding(body_scope, Match(held, Var)->name,
|
||||
Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true), held_var);
|
||||
code = CORD_all(code, compile_declaration(Type(PointerType, .pointed=Match(held_type, MutexedType)->type), held_var),
|
||||
" = (", compile_type(Type(PointerType, .pointed=Match(held_type, MutexedType)->type)), ")mutexed->data;\n");
|
||||
}
|
||||
@ -2856,10 +2856,10 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
if (key == NULL) key = FakeAST(Var, key_name);
|
||||
|
||||
env_t *expr_env = fresh_scope(env);
|
||||
set_binding(expr_env, key_name, new(binding_t, .type=t, .code="ternary$lhs"));
|
||||
set_binding(expr_env, key_name, t, "ternary$lhs");
|
||||
CORD lhs_key = compile(expr_env, key);
|
||||
|
||||
set_binding(expr_env, key_name, new(binding_t, .type=t, .code="ternary$rhs"));
|
||||
set_binding(expr_env, key_name, t, "ternary$rhs");
|
||||
CORD rhs_key = compile(expr_env, key);
|
||||
|
||||
type_t *key_t = get_type(expr_env, key);
|
||||
@ -2915,7 +2915,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
Closure_t comp_action = {.fn=add_to_array_comprehension, .userdata=comprehension_var};
|
||||
scope->comprehension_action = &comp_action;
|
||||
CORD code = CORD_all("({ Array_t ", comprehension_name, " = {};");
|
||||
// set_binding(scope, comprehension_name, new(binding_t, .type=array_type, .code=comprehension_name));
|
||||
// set_binding(scope, comprehension_name, array_type, comprehension_name);
|
||||
for (ast_list_t *item = array->items; item; item = item->next) {
|
||||
if (item->ast->tag == Comprehension)
|
||||
code = CORD_all(code, "\n", compile_statement(scope, item->ast));
|
||||
@ -3070,7 +3070,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
body_scope->deferred = NULL;
|
||||
for (arg_ast_t *arg = lambda->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=CORD_all("_$", arg->name)));
|
||||
set_binding(body_scope, arg->name, arg_type, CORD_all("_$", arg->name));
|
||||
}
|
||||
|
||||
type_t *ret_t = get_type(body_scope, lambda->body);
|
||||
@ -3098,7 +3098,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
entry->b->type, entry->name);
|
||||
if (entry->b->type->tag == ModuleType)
|
||||
continue;
|
||||
set_binding(body_scope, entry->name, new(binding_t, .type=entry->b->type, .code=CORD_cat("userdata->", entry->name)));
|
||||
set_binding(body_scope, entry->name, entry->b->type, CORD_cat("userdata->", entry->name));
|
||||
def = CORD_all(def, compile_declaration(entry->b->type, entry->name), "; ");
|
||||
}
|
||||
def = CORD_all(def, "} ", name, "$userdata_t;");
|
||||
@ -3644,7 +3644,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
|
||||
type_t *t = get_type(env, ast);
|
||||
env_t *when_env = fresh_scope(env);
|
||||
set_binding(when_env, "when", new(binding_t, .type=t, .code="when"));
|
||||
set_binding(when_env, "when", t, "when");
|
||||
return CORD_all(
|
||||
"({ ", compile_declaration(t, "when"), ";\n",
|
||||
compile_statement(when_env, WrapAST(ast, When, .subject=original->subject, .clauses=new_clauses, .else_body=else_body)),
|
||||
@ -3668,16 +3668,16 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
bind_statement(truthy_scope, condition);
|
||||
condition_code = compile_condition(truthy_scope, var);
|
||||
set_binding(truthy_scope, Match(var, Var)->name,
|
||||
new(binding_t, .type=Match(condition_type, OptionalType)->type,
|
||||
.code=optional_into_nonnone(condition_type, compile(truthy_scope, var))));
|
||||
Match(condition_type, OptionalType)->type,
|
||||
optional_into_nonnone(condition_type, compile(truthy_scope, var)));
|
||||
} else if (condition->tag == Var) {
|
||||
type_t *condition_type = get_type(env, condition);
|
||||
condition_code = compile_condition(env, condition);
|
||||
if (condition_type->tag == OptionalType) {
|
||||
truthy_scope = fresh_scope(env);
|
||||
set_binding(truthy_scope, Match(condition, Var)->name,
|
||||
new(binding_t, .type=Match(condition_type, OptionalType)->type,
|
||||
.code=optional_into_nonnone(condition_type, compile(truthy_scope, condition))));
|
||||
Match(condition_type, OptionalType)->type,
|
||||
optional_into_nonnone(condition_type, compile(truthy_scope, condition)));
|
||||
}
|
||||
} else {
|
||||
condition_code = compile_condition(env, condition);
|
||||
@ -3747,7 +3747,7 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
binop_e cmp_op = op == BINOP_MIN ? BINOP_LT : BINOP_GT;
|
||||
if (reduction->key) {
|
||||
env_t *key_scope = fresh_scope(env);
|
||||
set_binding(key_scope, "$", new(binding_t, .type=item_t, .code=item_code));
|
||||
set_binding(key_scope, "$", item_t, item_code);
|
||||
type_t *key_type = get_type(key_scope, reduction->key);
|
||||
const char *superlative_key = op == BINOP_MIN ? "min_key" : "max_key";
|
||||
code = CORD_all(code, compile_declaration(key_type, superlative_key), ";\n");
|
||||
@ -4031,7 +4031,7 @@ void compile_namespace(env_t *env, const char *ns_name, ast_t *block)
|
||||
name_code, "$initialized = true;\n")));
|
||||
|
||||
CORD checked_access = CORD_all("check_initialized(", name_code, ", \"", Match(decl->var, Var)->name, "\")");
|
||||
set_binding(ns_env, Match(decl->var, Var)->name, new(binding_t, .type=t, .code=checked_access));
|
||||
set_binding(ns_env, Match(decl->var, Var)->name, t, checked_access);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4293,7 +4293,7 @@ CORD compile_file(env_t *env, ast_t *ast)
|
||||
full_name, "$initialized = true;\n")));
|
||||
|
||||
CORD checked_access = CORD_all("check_initialized(", full_name, ", \"", decl_name, "\")");
|
||||
set_binding(env, decl_name, new(binding_t, .type=t, .code=checked_access));
|
||||
set_binding(env, decl_name, t, checked_access);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -468,26 +468,25 @@ env_t *new_compilation_unit(CORD libname)
|
||||
type_t *type = parse_type_string(ns_env, entry->type_str);
|
||||
if (!type) compiler_err(NULL, NULL, NULL, "Couldn't parse type string: %s", entry->type_str);
|
||||
if (type->tag == ClosureType) type = Match(type, ClosureType)->fn;
|
||||
binding_t *b = new(binding_t, .code=entry->code, .type=type);
|
||||
set_binding(ns_env, entry->name, b);
|
||||
set_binding(ns_env, entry->name, type, entry->code);
|
||||
}
|
||||
}
|
||||
|
||||
set_binding(namespace_env(env, "Shell"), "without_escaping",
|
||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Shell", .env=namespace_env(env, "Shell"))),
|
||||
.code="(Shell_t)"));
|
||||
Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Shell", .env=namespace_env(env, "Shell"))),
|
||||
"(Shell_t)");
|
||||
|
||||
set_binding(namespace_env(env, "Path"), "without_escaping",
|
||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Path", .env=namespace_env(env, "Path"))),
|
||||
.code="Path$cleanup"));
|
||||
Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Path", .env=namespace_env(env, "Path"))),
|
||||
"Path$cleanup");
|
||||
|
||||
|
||||
set_binding(namespace_env(env, "Pattern"), "without_escaping",
|
||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern"))),
|
||||
.code="(Pattern_t)"));
|
||||
Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern"))),
|
||||
"(Pattern_t)");
|
||||
|
||||
Table$str_set(env->globals, "random", new(binding_t, .type=RNG_TYPE, .code="default_rng"));
|
||||
|
||||
@ -553,7 +552,7 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
if (for_->vars->next)
|
||||
code_err(for_->vars->next->ast, "This is too many variables for this loop");
|
||||
const char *var = Match(for_->vars->ast, Var)->name;
|
||||
set_binding(scope, var, new(binding_t, .type=INT_TYPE, .code=CORD_cat("_$", var)));
|
||||
set_binding(scope, var, INT_TYPE, CORD_cat("_$", var));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -569,10 +568,10 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
vars[num_vars++] = Match(var->ast, Var)->name;
|
||||
}
|
||||
if (num_vars == 1) {
|
||||
set_binding(scope, vars[0], new(binding_t, .type=item_t, .code=CORD_cat("_$", vars[0])));
|
||||
set_binding(scope, vars[0], item_t, CORD_cat("_$", vars[0]));
|
||||
} else if (num_vars == 2) {
|
||||
set_binding(scope, vars[0], new(binding_t, .type=INT_TYPE, .code=CORD_cat("_$", vars[0])));
|
||||
set_binding(scope, vars[1], new(binding_t, .type=item_t, .code=CORD_cat("_$", vars[1])));
|
||||
set_binding(scope, vars[0], INT_TYPE, CORD_cat("_$", vars[0]));
|
||||
set_binding(scope, vars[1], item_t, CORD_cat("_$", vars[1]));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -582,7 +581,7 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
code_err(for_->vars->next->ast, "This is too many variables for this loop");
|
||||
type_t *item_type = Match(iter_t, SetType)->item_type;
|
||||
const char *name = Match(for_->vars->ast, Var)->name;
|
||||
set_binding(scope, name, new(binding_t, .type=item_type, .code=CORD_cat("_$", name)));
|
||||
set_binding(scope, name, item_type, CORD_cat("_$", name));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -597,11 +596,11 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
|
||||
type_t *key_t = Match(iter_t, TableType)->key_type;
|
||||
if (num_vars == 1) {
|
||||
set_binding(scope, vars[0], new(binding_t, .type=key_t, .code=CORD_cat("_$", vars[0])));
|
||||
set_binding(scope, vars[0], key_t, CORD_cat("_$", vars[0]));
|
||||
} else if (num_vars == 2) {
|
||||
set_binding(scope, vars[0], new(binding_t, .type=key_t, .code=CORD_cat("_$", vars[0])));
|
||||
set_binding(scope, vars[0], key_t, CORD_cat("_$", vars[0]));
|
||||
type_t *value_t = Match(iter_t, TableType)->value_type;
|
||||
set_binding(scope, vars[1], new(binding_t, .type=value_t, .code=CORD_cat("_$", vars[1])));
|
||||
set_binding(scope, vars[1], value_t, CORD_cat("_$", vars[1]));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -610,7 +609,7 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
if (for_->vars->next)
|
||||
code_err(for_->vars->next->ast, "This is too many variables for this loop");
|
||||
const char *var = Match(for_->vars->ast, Var)->name;
|
||||
set_binding(scope, var, new(binding_t, .type=INT_TYPE, .code=CORD_cat("_$", var)));
|
||||
set_binding(scope, var, INT_TYPE, CORD_cat("_$", var));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -624,7 +623,7 @@ env_t *for_scope(env_t *env, ast_t *ast)
|
||||
code_err(for_->vars->next->ast, "This is too many variables for this loop");
|
||||
const char *var = Match(for_->vars->ast, Var)->name;
|
||||
type_t *non_opt_type = fn->ret->tag == OptionalType ? Match(fn->ret, OptionalType)->type : fn->ret;
|
||||
set_binding(scope, var, new(binding_t, .type=non_opt_type, .code=CORD_cat("_$", var)));
|
||||
set_binding(scope, var, non_opt_type, CORD_cat("_$", var));
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
@ -711,10 +710,10 @@ PUREFUNC binding_t *get_lang_escape_function(env_t *env, const char *lang_name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void set_binding(env_t *env, const char *name, binding_t *binding)
|
||||
void set_binding(env_t *env, const char *name, type_t *type, CORD code)
|
||||
{
|
||||
if (name && binding)
|
||||
Table$str_set(env->locals, name, binding);
|
||||
assert(name);
|
||||
Table$str_set(env->locals, name, new(binding_t, .type=type, .code=code));
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 4, 5)))
|
||||
|
@ -66,7 +66,7 @@ __attribute__((format(printf, 4, 5)))
|
||||
_Noreturn void compiler_err(file_t *f, const char *start, const char *end, const char *fmt, ...);
|
||||
binding_t *get_binding(env_t *env, const char *name);
|
||||
binding_t *get_lang_escape_function(env_t *env, const char *lang_name, type_t *type_to_escape);
|
||||
void set_binding(env_t *env, const char *name, binding_t *binding);
|
||||
void set_binding(env_t *env, const char *name, type_t *type, CORD code);
|
||||
binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name);
|
||||
#define code_err(ast, ...) compiler_err((ast)->file, (ast)->start, (ast)->end, __VA_ARGS__)
|
||||
extern type_t *TEXT_TYPE;
|
||||
|
48
typecheck.c
48
typecheck.c
@ -207,7 +207,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast)
|
||||
struct {
|
||||
const char *name; binding_t *binding;
|
||||
} *entry = subenv->locals->entries.data + j*subenv->locals->entries.stride;
|
||||
set_binding(module_env, entry->name, entry->binding);
|
||||
Table$str_set(module_env->locals, entry->name, entry->binding);
|
||||
}
|
||||
}
|
||||
globfree(&tm_files);
|
||||
@ -232,8 +232,8 @@ void prebind_statement(env_t *env, ast_t *statement)
|
||||
env_t *ns_env = namespace_env(env, def->name);
|
||||
type_t *type = Type(StructType, .name=def->name, .opaque=true, .env=ns_env); // placeholder
|
||||
Table$str_set(env->types, def->name, type);
|
||||
set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
.code=CORD_all(namespace_prefix(env, env->namespace), def->name)));
|
||||
set_binding(env, def->name, Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
CORD_all(namespace_prefix(env, env->namespace), def->name));
|
||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||
prebind_statement(ns_env, stmt->ast);
|
||||
break;
|
||||
@ -246,8 +246,8 @@ void prebind_statement(env_t *env, ast_t *statement)
|
||||
env_t *ns_env = namespace_env(env, def->name);
|
||||
type_t *type = Type(EnumType, .name=def->name, .opaque=true, .env=ns_env); // placeholder
|
||||
Table$str_set(env->types, def->name, type);
|
||||
set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
.code=CORD_all(namespace_prefix(env, env->namespace), def->name)));
|
||||
set_binding(env, def->name, Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
CORD_all(namespace_prefix(env, env->namespace), def->name));
|
||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||
prebind_statement(ns_env, stmt->ast);
|
||||
break;
|
||||
@ -260,8 +260,8 @@ void prebind_statement(env_t *env, ast_t *statement)
|
||||
env_t *ns_env = namespace_env(env, def->name);
|
||||
type_t *type = Type(TextType, .lang=def->name, .env=ns_env);
|
||||
Table$str_set(env->types, def->name, type);
|
||||
set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
.code=CORD_all(namespace_prefix(env, env->namespace), def->name)));
|
||||
set_binding(env, def->name, Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env),
|
||||
CORD_all(namespace_prefix(env, env->namespace), def->name));
|
||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||
prebind_statement(ns_env, stmt->ast);
|
||||
break;
|
||||
@ -292,7 +292,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
type = Type(ClosureType, type);
|
||||
CORD prefix = namespace_prefix(env, env->namespace);
|
||||
CORD code = CORD_cat(prefix ? prefix : "$", name);
|
||||
set_binding(env, name, new(binding_t, .type=type, .code=code));
|
||||
set_binding(env, name, type, code);
|
||||
break;
|
||||
}
|
||||
case FunctionDef: {
|
||||
@ -302,7 +302,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
code_err(def->name, "A %T called '%s' has already been defined", get_binding(env, name)->type, name);
|
||||
type_t *type = get_function_def_type(env, statement);
|
||||
CORD code = CORD_all(namespace_prefix(env, env->namespace), name);
|
||||
set_binding(env, name, new(binding_t, .type=type, .code=code));
|
||||
set_binding(env, name, type, code);
|
||||
break;
|
||||
}
|
||||
case StructDef: {
|
||||
@ -370,10 +370,10 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
for (tag_t *tag = tags; tag; tag = tag->next) {
|
||||
if (Match(tag->type, StructType)->fields) { // Constructor:
|
||||
type_t *constructor_t = Type(FunctionType, .args=Match(tag->type, StructType)->fields, .ret=type);
|
||||
set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(namespace_prefix(env, env->namespace), def->name, "$tagged$", tag->name)));
|
||||
set_binding(ns_env, tag->name, constructor_t, CORD_all(namespace_prefix(env, env->namespace), def->name, "$tagged$", tag->name));
|
||||
} else { // Empty singleton value:
|
||||
CORD code = CORD_all("(", namespace_prefix(env, env->namespace), def->name, "_t){", namespace_prefix(env, env->namespace), def->name, "$tag$", tag->name, "}");
|
||||
set_binding(ns_env, tag->name, new(binding_t, .type=type, .code=code));
|
||||
set_binding(ns_env, tag->name, type, code);
|
||||
}
|
||||
Table$str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type);
|
||||
}
|
||||
@ -390,8 +390,8 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
Table$str_set(env->types, def->name, type);
|
||||
|
||||
set_binding(ns_env, "without_escaping",
|
||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
|
||||
.code=CORD_all("(", namespace_prefix(env, env->namespace), def->name, "_t)")));
|
||||
Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type),
|
||||
CORD_all("(", namespace_prefix(env, env->namespace), def->name, "_t)"));
|
||||
|
||||
for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next)
|
||||
bind_statement(ns_env, stmt->ast);
|
||||
@ -426,7 +426,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
if (var) {
|
||||
type_t *type = get_type(env, statement);
|
||||
assert(type);
|
||||
set_binding(env, Match(var, Var)->name, new(binding_t, .type=type));
|
||||
set_binding(env, Match(var, Var)->name, type, CORD_EMPTY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -435,7 +435,7 @@ void bind_statement(env_t *env, ast_t *statement)
|
||||
type_t *t = parse_type_ast(env, ext->type);
|
||||
if (t->tag == ClosureType)
|
||||
t = Match(t, ClosureType)->fn;
|
||||
set_binding(env, ext->name, new(binding_t, .type=t, .code=ext->name));
|
||||
set_binding(env, ext->name, t, ext->name);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@ -450,7 +450,7 @@ type_t *get_function_def_type(env_t *env, ast_t *ast)
|
||||
for (arg_ast_t *arg = fn->args; arg; arg = arg->next) {
|
||||
type_t *t = arg->type ? parse_type_ast(env, arg->type) : get_type(env, arg->value);
|
||||
args = new(arg_t, .name=arg->name, .type=t, .default_val=arg->value, .next=args);
|
||||
set_binding(scope, arg->name, new(binding_t, .type=t));
|
||||
set_binding(scope, arg->name, t, CORD_EMPTY);
|
||||
}
|
||||
REVERSE_LIST(args);
|
||||
|
||||
@ -492,7 +492,7 @@ type_t *get_clause_type(env_t *env, type_t *subject_t, when_clause_t *clause)
|
||||
env_t *scope = fresh_scope(env);
|
||||
auto tag_struct = Match(tag_type, StructType);
|
||||
if (!clause->args->next && tag_struct->fields && tag_struct->fields->next) {
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, new(binding_t, .type=tag_type));
|
||||
set_binding(scope, Match(clause->args->ast, Var)->name, tag_type, CORD_EMPTY);
|
||||
} else {
|
||||
ast_list_t *var = clause->args;
|
||||
arg_t *field = tag_struct->fields;
|
||||
@ -501,7 +501,7 @@ type_t *get_clause_type(env_t *env, type_t *subject_t, when_clause_t *clause)
|
||||
code_err(clause->tag_name, "The field %T.%s.%s wasn't accounted for", subject_t, tag_name, field->name);
|
||||
if (!field)
|
||||
code_err(var->ast, "This is one more field than %T has", subject_t);
|
||||
set_binding(scope, Match(var->ast, Var)->name, new(binding_t, .type=field->type));
|
||||
set_binding(scope, Match(var->ast, Var)->name, field->type, CORD_EMPTY);
|
||||
var = var->next;
|
||||
field = field->next;
|
||||
}
|
||||
@ -917,7 +917,7 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
continue;
|
||||
binding_t *b = get_binding(ns_env, tag->name);
|
||||
assert(b);
|
||||
set_binding(env, tag->name, b);
|
||||
Table$str_set(env->locals, tag->name, b);
|
||||
}
|
||||
}
|
||||
return Type(ReturnType, .ret=(val ? get_type(env, val) : Type(VoidType)));
|
||||
@ -968,7 +968,7 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
code_err(held, "This is a %t, not a mutexed value", held_type);
|
||||
if (held->tag == Var) {
|
||||
env = fresh_scope(env);
|
||||
set_binding(env, Match(held, Var)->name, new(binding_t, .type=Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true)));
|
||||
set_binding(env, Match(held, Var)->name, Type(PointerType, .pointed=Match(held_type, MutexedType)->type, .is_stack=true), CORD_EMPTY);
|
||||
}
|
||||
return get_type(env, Match(ast, Holding)->body);
|
||||
}
|
||||
@ -1165,7 +1165,7 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
for (arg_ast_t *arg = lambda->args; arg; arg = arg->next) {
|
||||
type_t *t = get_arg_ast_type(env, arg);
|
||||
args = new(arg_t, .name=arg->name, .type=t, .next=args);
|
||||
set_binding(scope, arg->name, new(binding_t, .type=t));
|
||||
set_binding(scope, arg->name, t, CORD_EMPTY);
|
||||
}
|
||||
REVERSE_LIST(args);
|
||||
|
||||
@ -1212,16 +1212,16 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
truthy_scope = fresh_scope(env);
|
||||
if (condition_type->tag == OptionalType)
|
||||
set_binding(truthy_scope, varname,
|
||||
new(binding_t, .type=Match(condition_type, OptionalType)->type));
|
||||
Match(condition_type, OptionalType)->type, CORD_EMPTY);
|
||||
else
|
||||
set_binding(truthy_scope, varname, new(binding_t, .type=condition_type));
|
||||
set_binding(truthy_scope, varname, condition_type, CORD_EMPTY);
|
||||
} else if (if_->condition->tag == Var) {
|
||||
type_t *condition_type = get_type(env, if_->condition);
|
||||
if (condition_type->tag == OptionalType) {
|
||||
truthy_scope = fresh_scope(env);
|
||||
const char *varname = Match(if_->condition, Var)->name;
|
||||
set_binding(truthy_scope, varname,
|
||||
new(binding_t, .type=Match(condition_type, OptionalType)->type));
|
||||
Match(condition_type, OptionalType)->type, CORD_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user