aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compile/assertions.c2
-rw-r--r--src/compile/assignments.c4
-rw-r--r--src/compile/binops.c42
-rw-r--r--src/compile/comparisons.c4
-rw-r--r--src/compile/conditionals.c4
-rw-r--r--src/compile/declarations.c4
-rw-r--r--src/compile/enums.c5
-rw-r--r--src/compile/expressions.c6
-rw-r--r--src/compile/fieldaccess.c4
-rw-r--r--src/compile/files.c4
-rw-r--r--src/compile/functions.c14
-rw-r--r--src/compile/headers.c4
-rw-r--r--src/compile/indexing.c4
-rw-r--r--src/compile/integers.c4
-rw-r--r--src/compile/loops.c2
-rw-r--r--src/compile/optionals.c6
-rw-r--r--src/compile/pointers.c2
-rw-r--r--src/compile/promotions.c2
-rw-r--r--src/compile/reductions.c2
-rw-r--r--src/compile/statements.c4
-rw-r--r--src/compile/structs.c4
-rw-r--r--src/compile/tables.c2
-rw-r--r--src/compile/text.c6
-rw-r--r--src/compile/types.c4
-rw-r--r--src/compile/whens.c6
-rw-r--r--src/environment.c2
-rw-r--r--src/tomo.c2
-rw-r--r--src/typecheck.c130
-rw-r--r--src/types.c33
-rw-r--r--src/types.h1
30 files changed, 161 insertions, 152 deletions
diff --git a/src/compile/assertions.c b/src/compile/assertions.c
index 0f1d27b6..3ea6bf1e 100644
--- a/src/compile/assertions.c
+++ b/src/compile/assertions.c
@@ -43,7 +43,7 @@ Text_t compile_assertion(env_t *env, ast_t *ast) {
} else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
operand_t = rhs_t;
} else {
- code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
}
ast_t *lhs_var = FakeAST(InlineCCode, .chunks = new (ast_list_t, .ast = FakeAST(TextLiteral, Text("_lhs"))),
diff --git a/src/compile/assignments.c b/src/compile/assignments.c
index 6848e298..921b5320 100644
--- a/src/compile/assignments.c
+++ b/src/compile/assignments.c
@@ -142,9 +142,9 @@ Text_t compile_lvalue(env_t *env, ast_t *ast) {
} else if (ast->tag == FieldAccess) {
ast_t *subject = Match(ast, FieldAccess)->fielded;
type_t *t = get_type(env, subject);
- code_err(subject, "This is an immutable ", type_to_str(t), " value, you can't assign to its fields");
+ code_err(subject, "This is an immutable ", type_to_text(t), " value, you can't assign to its fields");
} else {
- code_err(ast, "This is a value of type ", type_to_str(get_type(env, ast)),
+ code_err(ast, "This is a value of type ", type_to_text(get_type(env, ast)),
" and can't be used as an assignment target");
}
}
diff --git a/src/compile/binops.c b/src/compile/binops.c
index ed4aaeba..9710019b 100644
--- a/src/compile/binops.c
+++ b/src/compile/binops.c
@@ -88,8 +88,8 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
if (is_incomplete_type(rhs_t)) {
type_t *complete = most_complete_type(rhs_t, Match(lhs_t, OptionalType)->type);
if (complete == NULL)
- code_err(binop.rhs, "I don't know how to convert a ", type_to_str(rhs_t), " to a ",
- type_to_str(Match(lhs_t, OptionalType)->type));
+ code_err(binop.rhs, "I don't know how to convert a ", type_to_text(rhs_t), " to a ",
+ type_to_text(Match(lhs_t, OptionalType)->type));
rhs_t = complete;
}
@@ -103,8 +103,8 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
} else if (rhs_t->tag == BoolType) {
return Texts("((!", check_none(lhs_t, compile(env, binop.lhs)), ") || ", compile(env, binop.rhs), ")");
} else {
- code_err(ast, "I don't know how to do an 'or' operation between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I don't know how to do an 'or' operation between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
}
@@ -114,7 +114,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
switch (ast->tag) {
case Power: {
if (overall_t->tag != NumType)
- code_err(ast, "Exponentiation is only supported for Num types, not ", type_to_str(overall_t));
+ code_err(ast, "Exponentiation is only supported for Num types, not ", type_to_text(overall_t));
if (overall_t->tag == NumType && Match(overall_t, NumType)->bits == TYPE_NBITS32)
return Texts("powf(", lhs, ", ", rhs, ")");
else return Texts("pow(", lhs, ", ", rhs, ")");
@@ -124,7 +124,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " * ", rhs, ")");
}
case Divide: {
@@ -132,7 +132,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " / ", rhs, ")");
}
case Mod: {
@@ -140,7 +140,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " % ", rhs, ")");
}
case Mod1: {
@@ -148,7 +148,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("((((", lhs, ")-1) % (", rhs, ")) + 1)");
}
case Plus: {
@@ -156,7 +156,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " + ", rhs, ")");
}
case Minus: {
@@ -166,7 +166,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " - ", rhs, ")");
}
case LeftShift: {
@@ -174,7 +174,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " << ", rhs, ")");
}
case RightShift: {
@@ -182,7 +182,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", lhs, " >> ", rhs, ")");
}
case UnsignedLeftShift: {
@@ -190,7 +190,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", compile_type(overall_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " << ", rhs, ")");
}
case UnsignedRightShift: {
@@ -198,7 +198,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
code_err(ast,
"Math operations are only supported for values of the same "
"numeric type, not ",
- type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ type_to_text(lhs_t), " and ", type_to_text(rhs_t));
return Texts("(", compile_type(overall_t), ")((", compile_unsigned_type(lhs_t), ")", lhs, " >> ", rhs, ")");
}
case And: {
@@ -207,8 +207,8 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
else if (overall_t->tag == SetType)
return Texts("Table$overlap(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
else
- code_err(ast, "The 'and' operator isn't supported between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t), " values");
+ code_err(ast, "The 'and' operator isn't supported between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t), " values");
}
case Compare: {
return Texts("generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(overall_t), ")");
@@ -221,7 +221,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
} else if (overall_t->tag == SetType) {
return Texts("Table$with(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
} else {
- code_err(ast, "The 'or' operator isn't supported between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t),
+ code_err(ast, "The 'or' operator isn't supported between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t),
" values");
}
}
@@ -232,8 +232,8 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
else if (overall_t->tag == SetType)
return Texts("Table$xor(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
else
- code_err(ast, "The 'xor' operator isn't supported between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t), " values");
+ code_err(ast, "The 'xor' operator isn't supported between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t), " values");
}
case Concat: {
if (overall_t == PATH_TYPE) return Texts("Path$concat(", lhs, ", ", rhs, ")");
@@ -246,7 +246,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
compile_type(Match(overall_t, ListType)->item_type), "))");
}
default:
- code_err(ast, "Concatenation isn't supported between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t),
+ code_err(ast, "Concatenation isn't supported between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t),
" values");
}
}
diff --git a/src/compile/comparisons.c b/src/compile/comparisons.c
index d7531261..0f9a7ddd 100644
--- a/src/compile/comparisons.c
+++ b/src/compile/comparisons.c
@@ -38,7 +38,7 @@ Text_t compile_comparison(env_t *env, ast_t *ast) {
} else if (can_compile_to_type(env, binop.lhs, rhs_t)) {
operand_t = rhs_t;
} else {
- code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
}
Text_t lhs, rhs;
@@ -78,7 +78,7 @@ Text_t compile_comparison(env_t *env, ast_t *ast) {
} else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
operand_t = rhs_t;
} else {
- code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
}
Text_t lhs = compile_to_type(env, cmp.lhs, operand_t);
diff --git a/src/compile/conditionals.c b/src/compile/conditionals.c
index f9dfa751..7fcd6cc8 100644
--- a/src/compile/conditionals.c
+++ b/src/compile/conditionals.c
@@ -26,7 +26,7 @@ Text_t compile_condition(env_t *env, ast_t *ast) {
code_err(ast, "This pointer will always be non-none, so it should not be "
"used in a conditional.");
} else {
- code_err(ast, type_to_str(t), " values cannot be used for conditionals");
+ code_err(ast, type_to_text(t), " values cannot be used for conditionals");
}
return EMPTY_TEXT;
}
@@ -102,7 +102,7 @@ Text_t compile_if_expression(env_t *env, ast_t *ast) {
"This `if var := ...:` declaration should be an "
"optional "
"type, not ",
- type_to_str(condition_type));
+ type_to_text(condition_type));
if (is_incomplete_type(condition_type)) code_err(condition, "This type is incomplete!");
diff --git a/src/compile/declarations.c b/src/compile/declarations.c
index 3f2164af..f1c59f73 100644
--- a/src/compile/declarations.c
+++ b/src/compile/declarations.c
@@ -32,7 +32,7 @@ Text_t compile_declared_value(env_t *env, ast_t *declare_ast) {
type_t *t = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
- code_err(declare_ast, "You can't declare a variable with a ", type_to_str(t), " value");
+ code_err(declare_ast, "You can't declare a variable with a ", type_to_text(t), " value");
if (decl->value) {
Text_t val_code = compile_maybe_incref(env, decl->value, t);
@@ -44,7 +44,7 @@ Text_t compile_declared_value(env_t *env, ast_t *declare_ast) {
} else {
Text_t val_code = compile_empty(t);
if (val_code.length == 0)
- code_err(declare_ast, "This type (", type_to_str(t),
+ code_err(declare_ast, "This type (", type_to_text(t),
") cannot be uninitialized. You must provide a value.");
return val_code;
}
diff --git a/src/compile/enums.c b/src/compile/enums.c
index f8a3994e..ec7a1755 100644
--- a/src/compile/enums.c
+++ b/src/compile/enums.c
@@ -30,7 +30,7 @@ Text_t compile_enum_typeinfo(env_t *env, const char *name, tag_ast_t *tags) {
Text_t info = namespace_name(env, env->namespace, Texts(name, "$$info"));
Text_t typeinfo =
Texts("public const TypeInfo_t ", info, " = {", (int64_t)type_size(t), "u, ", (int64_t)type_align(t),
- "u, .metamethods=", metamethods, ", {.tag=EnumInfo, .EnumInfo={.name=\"", name,
+ "u, .metamethods=", metamethods, ", {.tag=EnumInfo, .EnumInfo={.name=\"", type_to_text(t),
"\", "
".num_tags=",
(int64_t)num_tags, ", .tags=(NamedType_t[]){");
@@ -78,6 +78,7 @@ Text_t compile_enum_header(env_t *env, const char *name, tag_ast_t *tags) {
Text_t none_name = namespace_name(env, env->namespace, Texts(name, "$none"));
Text_t enum_name = namespace_name(env, env->namespace, Texts(name, "$$enum"));
Text_t enum_tags = Texts("{ ", none_name, "=0, ");
+ assert(Table$str_get(*env->types, name));
bool has_any_tags_with_fields = false;
for (tag_ast_t *tag = tags; tag; tag = tag->next) {
@@ -167,5 +168,5 @@ Text_t compile_enum_field_access(env_t *env, ast_t *ast) {
}
}
}
- code_err(ast, "The field '", f->field, "' is not a valid tag name of ", type_to_str(value_t));
+ code_err(ast, "The field '", f->field, "' is not a valid tag name of ", type_to_text(value_t));
}
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index e888ce16..16b94d73 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -98,7 +98,7 @@ Text_t compile(env_t *env, ast_t *ast) {
else if (t->tag == TextType) return Texts("(", compile(env, value), ".length == 0)");
else if (t->tag == OptionalType) return check_none(t, compile(env, value));
- code_err(ast, "I don't know how to negate values of type ", type_to_str(t));
+ code_err(ast, "I don't know how to negate values of type ", type_to_text(t));
}
case Negative: {
ast_t *value = Match(ast, Negative)->value;
@@ -112,7 +112,7 @@ Text_t compile(env_t *env, ast_t *ast) {
if (t->tag == IntType || t->tag == NumType) return Texts("-(", compile(env, value), ")");
- code_err(ast, "I don't know how to get the negative value of type ", type_to_str(t));
+ code_err(ast, "I don't know how to get the negative value of type ", type_to_text(t));
}
case HeapAllocate:
case StackReference: return compile_typed_allocation(env, ast, get_type(env, ast));
@@ -218,7 +218,7 @@ Text_t compile(env_t *env, ast_t *ast) {
ast_t *value = Match(ast, Deserialize)->value;
type_t *value_type = get_type(env, value);
if (!type_eq(value_type, Type(ListType, Type(ByteType))))
- code_err(value, "This value should be a list of bytes, not a ", type_to_str(value_type));
+ code_err(value, "This value should be a list of bytes, not a ", type_to_text(value_type));
type_t *t = parse_type_ast(env, Match(ast, Deserialize)->type);
return Texts("({ ", compile_declaration(t, Text("deserialized")),
";\n"
diff --git a/src/compile/fieldaccess.c b/src/compile/fieldaccess.c
index f1780fc9..24e091f0 100644
--- a/src/compile/fieldaccess.c
+++ b/src/compile/fieldaccess.c
@@ -35,7 +35,7 @@ Text_t compile_field_access(env_t *env, ast_t *ast) {
} else if (streq(f->field, "length")) {
return Texts("Int$from_int64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").length)");
}
- code_err(ast, "There is no '", f->field, "' field on ", type_to_str(value_t), " values");
+ code_err(ast, "There is no '", f->field, "' field on ", type_to_text(value_t), " values");
}
case StructType: {
return compile_struct_field_access(env, ast);
@@ -83,6 +83,6 @@ Text_t compile_field_access(env_t *env, ast_t *ast) {
env_t *module_env = Table$str_get(*env->imports, name);
return compile(module_env, WrapAST(ast, Var, f->field));
}
- default: code_err(ast, "Field accesses are not supported on ", type_to_str(fielded_t), " values");
+ default: code_err(ast, "Field accesses are not supported on ", type_to_text(fielded_t), " values");
}
}
diff --git a/src/compile/files.c b/src/compile/files.c
index 7ff252c2..bd1e9cc3 100644
--- a/src/compile/files.c
+++ b/src/compile/files.c
@@ -111,7 +111,7 @@ Text_t compile_top_level_code(env_t *env, ast_t *ast) {
code_err(ast,
"Conversions are only supported for text, struct, and enum "
"types, not ",
- type_to_str(type));
+ type_to_text(type));
Text_t name_code =
namespace_name(env, env->namespace, Texts(name, "$", get_line_number(ast->file, ast->start)));
return compile_function(env, name_code, ast, &env->code->staticdefs);
@@ -170,6 +170,8 @@ typedef struct {
static void add_type_infos(type_ast_t *type_ast, void *userdata) {
if (type_ast && type_ast->tag == EnumTypeAST) {
compile_info_t *info = (compile_info_t *)userdata;
+ // Force the type to get defined:
+ (void)parse_type_ast(info->env, type_ast);
*info->code = Texts(
*info->code,
compile_enum_typeinfo(info->env, String("enum$", (int64_t)(type_ast->start - type_ast->file->text)),
diff --git a/src/compile/functions.c b/src/compile/functions.c
index 1e0fa106..d113316b 100644
--- a/src/compile/functions.c
+++ b/src/compile/functions.c
@@ -55,7 +55,7 @@ Text_t compile_convert_declaration(env_t *env, ast_t *ast) {
code_err(ast,
"Conversions are only supported for text, struct, and enum "
"types, not ",
- type_to_str(ret_t));
+ type_to_text(ret_t));
Text_t name_code = namespace_name(env, env->namespace, Texts(name, "$", get_line_number(ast->file, ast->start)));
return Texts(ret_type_code, " ", name_code, arg_signature, ";\n");
}
@@ -216,7 +216,7 @@ Text_t compile_function_call(env_t *env, ast_t *ast) {
code_err(ast,
"I could not find a constructor matching these arguments "
"for ",
- type_to_str(t));
+ type_to_text(t));
} else if (fn_t->tag == ClosureType) {
fn_t = Match(fn_t, ClosureType)->fn;
arg_t *type_args = Match(fn_t, FunctionType)->args;
@@ -241,7 +241,7 @@ Text_t compile_function_call(env_t *env, ast_t *ast) {
"closure.userdata); })");
}
} else {
- code_err(call->fn, "This is not a function, it's a ", type_to_str(fn_t));
+ code_err(call->fn, "This is not a function, it's a ", type_to_text(fn_t));
}
}
@@ -268,7 +268,7 @@ Text_t compile_lambda(env_t *env, ast_t *ast) {
binding_t *b;
} *entry = closed_vars.entries.data + closed_vars.entries.stride * i;
if (has_stack_memory(entry->b->type))
- code_err(ast, "This function is holding onto a reference to ", type_to_str(entry->b->type),
+ code_err(ast, "This function is holding onto a reference to ", type_to_text(entry->b->type),
" stack memory in the variable `", entry->name,
"`, but the function may outlive the stack memory");
if (entry->b->type->tag == ModuleType) continue;
@@ -510,7 +510,7 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t
if (clause->pattern->tag == Var) clause_tag_name = Match(clause->pattern, Var)->name;
else if (clause->pattern->tag == FunctionCall && Match(clause->pattern, FunctionCall)->fn->tag == Var)
clause_tag_name = Match(Match(clause->pattern, FunctionCall)->fn, Var)->name;
- else code_err(clause->pattern, "This is not a valid pattern for a ", type_to_str(subject_t), " enum");
+ else code_err(clause->pattern, "This is not a valid pattern for a ", type_to_text(subject_t), " enum");
type_t *tag_type = NULL;
for (tag_t *tag = enum_t->tags; tag; tag = tag->next) {
@@ -634,7 +634,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
code_err(ast,
"Conversions are only supported for text, struct, and enum "
"types, not ",
- type_to_str(ret_t));
+ type_to_text(ret_t));
body = convertdef->body;
cache = convertdef->cache;
is_inline = convertdef->is_inline;
@@ -693,7 +693,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
code_err(ast,
"This function looks like it can reach the end without "
"returning a ",
- type_to_str(ret_t),
+ type_to_text(ret_t),
" value! \n "
"If this is not the case, please add a call to "
"`fail(\"Unreachable\")` at the end of the function to "
diff --git a/src/compile/headers.c b/src/compile/headers.c
index 77040445..f6313cd6 100644
--- a/src/compile/headers.c
+++ b/src/compile/headers.c
@@ -79,7 +79,7 @@ Text_t compile_statement_namespace_header(env_t *env, Path_t header_path, ast_t
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 ", type_to_str(t), " value");
+ code_err(ast, "You can't declare a variable with a ", type_to_text(t), " value");
return Texts(decl->value ? compile_statement_type_header(env, header_path, decl->value) : EMPTY_TEXT, "extern ",
compile_declaration(t, namespace_name(env, env->namespace, Text$from_str(decl_name))), ";\n");
@@ -151,6 +151,8 @@ static void add_type_headers(type_ast_t *type_ast, void *userdata) {
if (type_ast->tag == EnumTypeAST) {
compile_typedef_info_t *info = (compile_typedef_info_t *)userdata;
+ // Force the type to get defined:
+ (void)parse_type_ast(info->env, type_ast);
DeclareMatch(enum_, type_ast, EnumTypeAST);
bool has_any_tags_with_fields = false;
for (tag_ast_t *tag = enum_->tags; tag; tag = tag->next) {
diff --git a/src/compile/indexing.c b/src/compile/indexing.c
index bb7bf6b9..771e9acd 100644
--- a/src/compile/indexing.c
+++ b/src/compile/indexing.c
@@ -33,7 +33,7 @@ Text_t compile_indexing(env_t *env, ast_t *ast, bool checked) {
type_t *index_t = get_type(env, indexing->index);
if (container_t->tag == ListType) {
if (index_t->tag != IntType && index_t->tag != BigIntType && index_t->tag != ByteType)
- code_err(indexing->index, "Lists can only be indexed by integers, not ", type_to_str(index_t));
+ code_err(indexing->index, "Lists can only be indexed by integers, not ", type_to_text(index_t));
type_t *item_type = Match(container_t, ListType)->item_type;
Text_t list = compile_to_pointer_depth(env, indexing->indexed, 0, false);
Text_t index_code =
@@ -82,6 +82,6 @@ Text_t compile_indexing(env_t *env, ast_t *ast, bool checked) {
compile_to_type(env, indexing->index, Type(BigIntType)), ")");
}
} else {
- code_err(ast, "Indexing is not supported for type: ", type_to_str(container_t));
+ code_err(ast, "Indexing is not supported for type: ", type_to_text(container_t));
}
}
diff --git a/src/compile/integers.c b/src/compile/integers.c
index 9ebb8818..4747f8ba 100644
--- a/src/compile/integers.c
+++ b/src/compile/integers.c
@@ -18,7 +18,7 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) {
Text_t code = compile(env, ast);
type_t *actual_type = get_type(env, ast);
if (!promote(env, ast, &code, actual_type, target))
- code_err(ast, "I couldn't promote this ", type_to_str(actual_type), " to a ", type_to_str(target));
+ code_err(ast, "I couldn't promote this ", type_to_text(actual_type), " to a ", type_to_text(target));
return code;
}
@@ -72,7 +72,7 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) {
}
code_err(ast, "This integer cannot fit in a ", target_bits, "-bit value");
} else {
- code_err(ast, "I don't know how to compile this to a ", type_to_str(target));
+ code_err(ast, "I don't know how to compile this to a ", type_to_text(target));
}
return EMPTY_TEXT;
}
diff --git a/src/compile/loops.c b/src/compile/loops.c
index 332024f4..b68c908f 100644
--- a/src/compile/loops.c
+++ b/src/compile/loops.c
@@ -355,7 +355,7 @@ Text_t compile_for_loop(env_t *env, ast_t *ast) {
return code;
}
- default: code_err(for_->iter, "Iteration is not implemented for type: ", type_to_str(iter_t));
+ default: code_err(for_->iter, "Iteration is not implemented for type: ", type_to_text(iter_t));
}
}
diff --git a/src/compile/optionals.c b/src/compile/optionals.c
index 8340ecaa..234a1cd2 100644
--- a/src/compile/optionals.c
+++ b/src/compile/optionals.c
@@ -32,7 +32,7 @@ Text_t promote_to_optional(type_t *t, Text_t code) {
case TYPE_IBITS16: return Texts("((OptionalInt16_t){.value=", code, "})");
case TYPE_IBITS32: return Texts("((OptionalInt32_t){.value=", code, "})");
case TYPE_IBITS64: return Texts("((OptionalInt64_t){.value=", code, "})");
- default: errx(1, "Unsupported in type: %s", type_to_str(t));
+ default: errx(1, "Unsupported in type: %s", type_to_text(t));
}
return code;
} else if (t->tag == ByteType) {
@@ -83,7 +83,7 @@ Text_t compile_none(type_t *t) {
env_t *enum_env = Match(t, EnumType)->env;
return Texts("((", compile_type(t), "){", namespace_name(enum_env, enum_env->namespace, Text("none")), "})");
}
- default: compiler_err(NULL, NULL, NULL, "none isn't implemented for this type: ", type_to_str(t));
+ default: compiler_err(NULL, NULL, NULL, "none isn't implemented for this type: ", type_to_text(t));
}
return EMPTY_TEXT;
}
@@ -109,7 +109,7 @@ Text_t check_none(type_t *t, Text_t value) {
if (enum_has_fields(t)) return Texts("((", value, ").$tag == 0)");
else return Texts("((", value, ") == 0)");
}
- print_err("Optional check not implemented for: ", type_to_str(t));
+ print_err("Optional check not implemented for: ", type_to_text(t));
return EMPTY_TEXT;
}
diff --git a/src/compile/pointers.c b/src/compile/pointers.c
index 644b3bc7..31687d78 100644
--- a/src/compile/pointers.c
+++ b/src/compile/pointers.c
@@ -27,7 +27,7 @@ Text_t compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bo
while (depth != target_depth) {
if (depth < target_depth) {
if (ast->tag == Var && target_depth == 1) val = Texts("(&", val, ")");
- else code_err(ast, "This should be a pointer, not ", type_to_str(get_type(env, ast)));
+ else code_err(ast, "This should be a pointer, not ", type_to_text(get_type(env, ast)));
t = Type(PointerType, .pointed = t, .is_stack = true);
++depth;
} else {
diff --git a/src/compile/promotions.c b/src/compile/promotions.c
index 26f3af9f..3441632e 100644
--- a/src/compile/promotions.c
+++ b/src/compile/promotions.c
@@ -191,5 +191,5 @@ Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t) {
return Texts(constructor->code, "(", compile_arguments(env, ast, arg_spec, constructor_args), ")");
}
- code_err(ast, "I expected a ", type_to_str(t), " here, but this is a ", type_to_str(actual));
+ code_err(ast, "I expected a ", type_to_text(t), " here, but this is a ", type_to_text(actual));
}
diff --git a/src/compile/reductions.c b/src/compile/reductions.c
index 438e072b..159158e3 100644
--- a/src/compile/reductions.c
+++ b/src/compile/reductions.c
@@ -17,7 +17,7 @@ Text_t compile_reduction(env_t *env, ast_t *ast) {
type_t *iter_t = get_type(env, reduction->iter);
type_t *item_t = get_iterated_type(iter_t);
if (!item_t)
- code_err(reduction->iter, "I couldn't figure out how to iterate over this type: ", type_to_str(iter_t));
+ code_err(reduction->iter, "I couldn't figure out how to iterate over this type: ", type_to_text(iter_t));
static int64_t next_id = 1;
ast_t *item = FakeAST(Var, String("$it", next_id++));
diff --git a/src/compile/statements.c b/src/compile/statements.c
index 3fc44ac4..db8f5b1f 100644
--- a/src/compile/statements.c
+++ b/src/compile/statements.c
@@ -48,7 +48,7 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) {
type_t *t = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value);
if (t->tag == FunctionType) t = Type(ClosureType, t);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
- code_err(ast, "You can't declare a variable with a ", type_to_str(t), " value");
+ code_err(ast, "You can't declare a variable with a ", type_to_text(t), " value");
Text_t val_code = compile_declared_value(env, ast);
return Texts(compile_declaration(t, Texts("_$", name)), " = ", val_code, ";");
@@ -214,7 +214,7 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) {
// print("Is discardable: ", ast_to_sexp_str(ast), " ==> ",
// is_discardable(env, ast));
if (!is_discardable(env, ast))
- code_err(ast, "The ", type_to_str(get_type(env, ast)), " result of this statement cannot be discarded");
+ code_err(ast, "The ", type_to_text(get_type(env, ast)), " result of this statement cannot be discarded");
return Texts("(void)", compile(env, ast), ";");
}
}
diff --git a/src/compile/structs.c b/src/compile/structs.c
index 8560a790..aaebef22 100644
--- a/src/compile/structs.c
+++ b/src/compile/structs.c
@@ -111,7 +111,7 @@ Text_t compile_struct_field_access(env_t *env, ast_t *ast) {
}
}
}
- code_err(ast, "The field '", f->field, "' is not a valid field name of ", type_to_str(value_t));
+ code_err(ast, "The field '", f->field, "' is not a valid field name of ", type_to_text(value_t));
}
public
@@ -129,5 +129,5 @@ Text_t compile_struct_literal(env_t *env, ast_t *ast, type_t *t, arg_ast_t *args
&& is_valid_call(env, struct_->fields, args, (call_opts_t){.promotion = true, .underscores = true})) {
code_err(ast, "This constructor uses private fields that are not exposed.");
}
- code_err(ast, "I could not find a constructor matching these arguments for the struct ", type_to_str(t));
+ code_err(ast, "I could not find a constructor matching these arguments for the struct ", type_to_text(t));
}
diff --git a/src/compile/tables.c b/src/compile/tables.c
index dde8669a..b6efdecd 100644
--- a/src/compile/tables.c
+++ b/src/compile/tables.c
@@ -26,7 +26,7 @@ Text_t compile_typed_table(env_t *env, ast_t *ast, type_t *table_type) {
type_t *value_t = Match(table_type, TableType)->value_type;
if (value_t->tag == OptionalType)
- code_err(ast, "Tables whose values are optional (", type_to_str(value_t), ") are not currently supported.");
+ code_err(ast, "Tables whose values are optional (", type_to_text(value_t), ") are not currently supported.");
for (ast_list_t *entry = table->entries; entry; entry = entry->next) {
if (entry->ast->tag == Comprehension) goto table_comprehension;
diff --git a/src/compile/text.c b/src/compile/text.c
index 0e0b41f8..afb412e9 100644
--- a/src/compile/text.c
+++ b/src/compile/text.c
@@ -38,7 +38,7 @@ Text_t expr_as_text(Text_t expr, type_t *t, Text_t color) {
case OptionalType: return Texts("Optional$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
case StructType:
case EnumType: return Texts("generic_as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
- default: compiler_err(NULL, NULL, NULL, "Stringifying is not supported for ", type_to_str(t));
+ default: compiler_err(NULL, NULL, NULL, "Stringifying is not supported for ", type_to_text(t));
}
return EMPTY_TEXT;
}
@@ -136,8 +136,8 @@ Text_t compile_text_ast(env_t *env, ast_t *ast) {
if (chunk_t->tag == TextType) chunk_code = compile(env, chunk->ast);
else chunk_code = compile_text(env, chunk->ast, colorize);
} else {
- code_err(chunk->ast, "I don't know how to convert ", type_to_str(chunk_t), " to ",
- type_to_str(text_t));
+ code_err(chunk->ast, "I don't know how to convert ", type_to_text(chunk_t), " to ",
+ type_to_text(text_t));
}
}
code = Texts(code, chunk_code);
diff --git a/src/compile/types.c b/src/compile/types.c
index f6f276a5..6b6f48f8 100644
--- a/src/compile/types.c
+++ b/src/compile/types.c
@@ -79,7 +79,7 @@ Text_t compile_type(type_t *t) {
DeclareMatch(s, nonnull, StructType);
return namespace_name(s->env, s->env->namespace->parent, Texts("$Optional", s->name, "$$type"));
}
- default: compiler_err(NULL, NULL, NULL, "Optional types are not supported for: ", type_to_str(t));
+ default: compiler_err(NULL, NULL, NULL, "Optional types are not supported for: ", type_to_text(t));
}
}
case TypeInfoType: return Text("TypeInfo_t");
@@ -147,7 +147,7 @@ Text_t compile_type_info(type_t *t) {
case TypeInfoType: return Texts("Type$info(", quoted_text(type_to_text(Match(t, TypeInfoType)->type)), ")");
case MemoryType: return Text("&Memory$info");
case VoidType: return Text("&Void$info");
- default: compiler_err(NULL, 0, 0, "I couldn't convert to a type info: ", type_to_str(t));
+ default: compiler_err(NULL, 0, 0, "I couldn't convert to a type info: ", type_to_text(t));
}
return EMPTY_TEXT;
}
diff --git a/src/compile/whens.c b/src/compile/whens.c
index d9bef9e1..4f6a2a40 100644
--- a/src/compile/whens.c
+++ b/src/compile/whens.c
@@ -61,7 +61,7 @@ Text_t compile_when_statement(env_t *env, ast_t *ast) {
}
if (clause->pattern->tag != FunctionCall || Match(clause->pattern, FunctionCall)->fn->tag != Var)
- code_err(clause->pattern, "This is not a valid pattern for a ", type_to_str(subject_t), " enum type");
+ code_err(clause->pattern, "This is not a valid pattern for a ", type_to_text(subject_t), " enum type");
const char *clause_tag_name = Match(Match(clause->pattern, FunctionCall)->fn, Var)->name;
code = Texts(code, "case ", namespace_name(enum_t->env, enum_t->env->namespace, Texts("tag$", clause_tag_name)),
@@ -93,9 +93,9 @@ Text_t compile_when_statement(env_t *env, ast_t *ast) {
arg_t *field = tag_struct->fields;
for (arg_ast_t *arg = args; arg || field; arg = arg->next) {
if (!arg)
- code_err(ast, "The field ", type_to_str(subject_t), ".", clause_tag_name, ".", field->name,
+ code_err(ast, "The field ", type_to_text(subject_t), ".", clause_tag_name, ".", field->name,
" wasn't accounted for");
- if (!field) code_err(arg->value, "This is one more field than ", type_to_str(subject_t), " has");
+ if (!field) code_err(arg->value, "This is one more field than ", type_to_text(subject_t), " has");
if (arg->name) code_err(arg->value, "Named arguments are not currently supported");
const char *var_name = Match(arg->value, Var)->name;
diff --git a/src/environment.c b/src/environment.c
index b551abf1..045cf6d7 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -659,7 +659,7 @@ env_t *for_scope(env_t *env, ast_t *ast) {
}
return scope;
}
- default: code_err(for_->iter, "Iteration is not implemented for type: ", type_to_str(iter_t));
+ default: code_err(for_->iter, "Iteration is not implemented for type: ", type_to_text(iter_t));
}
return NULL;
}
diff --git a/src/tomo.c b/src/tomo.c
index 6b80e71b..2f1d5651 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -788,7 +788,7 @@ void transpile_code(env_t *base_env, Path_t path) {
type_t *ret = Match(main_binding->type, FunctionType)->ret;
if (ret->tag != VoidType && ret->tag != AbortType)
compiler_err(ast->file, ast->start, ast->end, "The main() function in this file has a return type of ",
- type_to_str(ret), ", but it should not have any return value!");
+ type_to_text(ret), ", but it should not have any return value!");
Text$print(c_file, Texts("int parse_and_run$$", main_binding->code, "(int argc, char *argv[]) {\n",
module_env->do_source_mapping ? Text("#line 1\n") : EMPTY_TEXT, "tomo_init();\n",
diff --git a/src/typecheck.c b/src/typecheck.c
index 806cf1bf..87ed474a 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -117,15 +117,18 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast) {
DeclareMatch(opt, ast, OptionalTypeAST);
type_t *t = parse_type_ast(env, opt->type);
if (t->tag == VoidType || t->tag == AbortType || t->tag == ReturnType)
- code_err(ast, "Optional ", type_to_str(t), " types are not supported.");
+ code_err(ast, "Optional ", type_to_text(t), " types are not supported.");
else if (t->tag == OptionalType) code_err(ast, "Nested optional types are not currently supported");
return Type(OptionalType, .type = t);
}
case EnumTypeAST: {
+ const char *enum_name = Text$as_c_string(Match(ast, EnumTypeAST)->name);
+ type_t *cached = Table$str_get(*env->types, enum_name);
+ if (cached) return cached;
+
tag_ast_t *tag_asts = Match(ast, EnumTypeAST)->tags;
tag_t *tags = NULL;
int64_t tag_value = 1;
- const char *enum_name = Text$as_c_string(Match(ast, EnumTypeAST)->name);
env_t *ns_env = namespace_env(env, enum_name);
type_t *enum_type = Type(EnumType, .name = enum_name, .env = ns_env, .tags = NULL);
@@ -213,7 +216,7 @@ PUREFUNC type_t *get_math_type(env_t *env, ast_t *ast, type_t *lhs_t, type_t *rh
case NUM_PRECISION_MORE: return lhs_t;
case NUM_PRECISION_LESS: return rhs_t;
default:
- code_err(ast, "Math operations between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t),
+ code_err(ast, "Math operations between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t),
" are not supported");
}
return NULL;
@@ -283,7 +286,7 @@ void prebind_statement(env_t *env, ast_t *statement) {
case StructDef: {
DeclareMatch(def, statement, StructDef);
if (get_binding(env, def->name))
- code_err(statement, "A ", type_to_str(get_binding(env, def->name)->type), " called ", quoted(def->name),
+ code_err(statement, "A ", type_to_text(get_binding(env, def->name)->type), " called ", quoted(def->name),
" has already been defined");
env_t *ns_env = namespace_env(env, def->name);
@@ -300,7 +303,7 @@ void prebind_statement(env_t *env, ast_t *statement) {
case EnumDef: {
DeclareMatch(def, statement, EnumDef);
if (get_binding(env, def->name))
- code_err(statement, "A ", type_to_str(get_binding(env, def->name)->type), " called ", quoted(def->name),
+ code_err(statement, "A ", type_to_text(get_binding(env, def->name)->type), " called ", quoted(def->name),
" has already been defined");
env_t *ns_env = namespace_env(env, def->name);
@@ -316,7 +319,7 @@ void prebind_statement(env_t *env, ast_t *statement) {
case LangDef: {
DeclareMatch(def, statement, LangDef);
if (get_binding(env, def->name))
- code_err(statement, "A ", type_to_str(get_binding(env, def->name)->type), " called ", quoted(def->name),
+ code_err(statement, "A ", type_to_text(get_binding(env, def->name)->type), " called ", quoted(def->name),
" has already been defined");
env_t *ns_env = namespace_env(env, def->name);
@@ -348,8 +351,8 @@ void prebind_statement(env_t *env, ast_t *statement) {
binding_t *clobbered = Table$str_get(*ns_env->locals, entry->name);
if (clobbered && !type_eq(clobbered->type, entry->binding->type))
code_err(statement, "This `extend` block overwrites the binding for ", quoted(entry->name),
- " in the original namespace (with type ", type_to_str(clobbered->type),
- ") with a new binding with type ", type_to_str(entry->binding->type));
+ " in the original namespace (with type ", type_to_text(clobbered->type),
+ ") with a new binding with type ", type_to_text(entry->binding->type));
Table$str_set(ns_env->locals, entry->name, entry->binding);
}
break;
@@ -374,7 +377,7 @@ void bind_statement(env_t *env, ast_t *statement) {
if (streq(name, "_")) // Explicit discard
return;
if (get_binding(env, name))
- code_err(decl->var, "A ", type_to_str(get_binding(env, name)->type), " called ", quoted(name),
+ code_err(decl->var, "A ", type_to_text(get_binding(env, name)->type), " called ", quoted(name),
" has already been defined");
if (decl->value) bind_statement(env, decl->value);
type_t *type = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value);
@@ -400,7 +403,7 @@ void bind_statement(env_t *env, ast_t *statement) {
const char *name = get_type_name(ret_t);
if (!name)
code_err(statement, "Conversions are only supported for text, struct, and enum types, not ",
- type_to_str(ret_t));
+ type_to_text(ret_t));
Text_t code =
namespace_name(env, env->namespace, Texts(name, "$", get_line_number(statement->file, statement->start)));
@@ -435,20 +438,20 @@ void bind_statement(env_t *env, ast_t *statement) {
compiler_err(file, start, end,
"This is a recursive struct that would be infinitely large. Maybe you meant to "
"use an optional '@",
- type_to_str(type), "?' pointer instead?");
+ type_to_text(type), "?' pointer instead?");
else if (non_opt_field_t->tag == StructType && Match(non_opt_field_t, StructType)->external)
compiler_err(
file, start, end,
"This is an opaque externally defined struct.\n"
"I can't use it as a member without knowing what its fields are.\n"
"Either specify its fields and remove the `opaque` qualifier, or use something like a @",
- type_to_str(non_opt_field_t), " pointer.");
+ type_to_text(non_opt_field_t), " pointer.");
else
compiler_err(file, start, end, "I'm still in the process of defining the fields of ",
- type_to_str(field_t),
+ type_to_text(field_t),
", so I don't know how to use it as a member."
"\nTry using a @",
- type_to_str(field_t), " pointer for this field.");
+ type_to_text(field_t), " pointer for this field.");
}
fields = new (arg_t, .name = field_ast->name, .alias = field_ast->alias, .type = field_t,
.default_val = field_ast->value, .next = fields);
@@ -491,20 +494,20 @@ void bind_statement(env_t *env, ast_t *statement) {
compiler_err(file, start, end,
"This is a recursive enum that would be infinitely large. Maybe you meant to use "
"an optional '@",
- type_to_str(type), "?' pointer instead?");
+ type_to_text(type), "?' pointer instead?");
else if (non_opt_field_t->tag == StructType && Match(non_opt_field_t, StructType)->external)
compiler_err(
file, start, end,
"This is an opaque externally defined struct.\n"
"I can't use it as a member without knowing what its fields are.\n"
"Either specify its fields and remove the `opaque` qualifier, or use something like a @",
- type_to_str(non_opt_field_t), " pointer.");
+ type_to_text(non_opt_field_t), " pointer.");
else
compiler_err(file, start, end, "I'm still in the process of defining the fields of ",
- type_to_str(field_t),
+ type_to_text(field_t),
", so I don't know how to use it as a member."
"\nTry using a @",
- type_to_str(field_t), " pointer for this field.");
+ type_to_text(field_t), " pointer for this field.");
}
fields = new (arg_t, .name = field_ast->name, .alias = field_ast->alias, .type = field_t,
.default_val = field_ast->value, .next = fields);
@@ -577,8 +580,8 @@ void bind_statement(env_t *env, ast_t *statement) {
binding_t *clobbered = Table$str_get(*ns_env->locals, entry->name);
if (clobbered && !type_eq(clobbered->type, entry->binding->type))
code_err(statement, "This `extend` block overwrites the binding for ", quoted(entry->name),
- " in the original namespace (with type ", type_to_str(clobbered->type),
- ") with a new binding with type ", type_to_str(entry->binding->type));
+ " in the original namespace (with type ", type_to_text(clobbered->type),
+ ") with a new binding with type ", type_to_text(entry->binding->type));
Table$str_set(ns_env->locals, entry->name, entry->binding);
}
break;
@@ -673,8 +676,8 @@ type_t *get_function_type(env_t *env, ast_t *ast) {
type_t *declared = parse_type_ast(env, ret_ast);
if (can_promote(ret_t, declared)) ret_t = declared;
else
- code_err(ast, "This function was declared to return a value of type ", type_to_str(declared),
- ", but actually returns a value of type ", type_to_str(ret_t));
+ code_err(ast, "This function was declared to return a value of type ", type_to_text(declared),
+ ", but actually returns a value of type ", type_to_text(ret_t));
}
if (has_stack_memory(ret_t))
@@ -696,7 +699,7 @@ type_t *get_function_return_type(env_t *env, ast_t *ast) {
type_t *get_method_type(env_t *env, ast_t *self, const char *name) {
binding_t *b = get_namespace_binding(env, self, name);
- if (!b || !b->type) code_err(self, "No such method: ", type_to_str(get_type(env, self)), ".", name, "(...)");
+ if (!b || !b->type) code_err(self, "No such method: ", type_to_text(get_type(env, self)), ".", name, "(...)");
return b->type;
}
@@ -705,7 +708,7 @@ env_t *when_clause_scope(env_t *env, type_t *subject_t, when_clause_t *clause) {
if (clause->pattern->tag != FunctionCall || Match(clause->pattern, FunctionCall)->fn->tag != Var)
code_err(clause->pattern, "I only support variables and constructors for pattern matching ",
- type_to_str(subject_t), " types in a 'when' block");
+ type_to_text(subject_t), " types in a 'when' block");
DeclareMatch(fn, clause->pattern, FunctionCall);
const char *tag_name = Match(fn->fn, Var)->name;
@@ -719,7 +722,7 @@ env_t *when_clause_scope(env_t *env, type_t *subject_t, when_clause_t *clause) {
}
if (!tag_type)
- code_err(clause->pattern, "There is no tag ", quoted(tag_name), " for the type ", type_to_str(subject_t));
+ code_err(clause->pattern, "There is no tag ", quoted(tag_name), " for the type ", type_to_text(subject_t));
if (!fn->args) return env;
@@ -734,9 +737,9 @@ env_t *when_clause_scope(env_t *env, type_t *subject_t, when_clause_t *clause) {
arg_t *field = tag_struct->fields;
for (arg_ast_t *var = fn->args; var || field; var = var ? var->next : var) {
if (!var)
- code_err(clause->pattern, "The field ", type_to_str(subject_t), ".", tag_name, ".", field->name,
+ code_err(clause->pattern, "The field ", type_to_text(subject_t), ".", tag_name, ".", field->name,
" wasn't accounted for");
- if (!field) code_err(var->value, "This is one more field than ", type_to_str(subject_t), " has");
+ if (!field) code_err(var->value, "This is one more field than ", type_to_text(subject_t), " has");
if (var->value->tag != Var)
code_err(var->value, "I expected this to be a plain variable so I could bind it to a value");
if (!streq(Match(var->value, Var)->name, "_"))
@@ -971,7 +974,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
return b->type;
}
type_t *field_t = get_field_type(fielded_t, access->field);
- if (!field_t) code_err(ast, type_to_str(fielded_t), " objects don't have a field called '", access->field, "'");
+ if (!field_t)
+ code_err(ast, type_to_text(fielded_t), " objects don't have a field called '", access->field, "'");
return field_t;
}
case Index: {
@@ -988,7 +992,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *index_t = get_type(env, indexing->index);
if (index_t->tag == IntType || index_t->tag == BigIntType || index_t->tag == ByteType)
return Type(OptionalType, Match(value_t, ListType)->item_type);
- code_err(indexing->index, "I only know how to index lists using integers, not ", type_to_str(index_t));
+ code_err(indexing->index, "I only know how to index lists using integers, not ", type_to_text(index_t));
} else if (value_t->tag == TableType) {
DeclareMatch(table_type, value_t, TableType);
if (table_type->default_value) return table_type->value_type;
@@ -996,7 +1000,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
} else if (value_t->tag == TextType) {
return Type(OptionalType, value_t);
} else {
- code_err(ast, "I don't know how to index ", type_to_str(indexed_t), " values");
+ code_err(ast, "I don't know how to index ", type_to_text(indexed_t), " values");
}
}
case FunctionCall: {
@@ -1023,7 +1027,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
}
if (fn_type_t->tag == ClosureType) fn_type_t = Match(fn_type_t, ClosureType)->fn;
if (fn_type_t->tag != FunctionType)
- code_err(call->fn, "This isn't a function, it's a ", type_to_str(fn_type_t));
+ code_err(call->fn, "This isn't a function, it's a ", type_to_text(fn_type_t));
DeclareMatch(fn_type, fn_type_t, FunctionType);
return fn_type->ret;
}
@@ -1099,7 +1103,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
else if (streq(call->name, "set")) return Type(VoidType);
else if (streq(call->name, "sorted")) return self_value_t;
else if (streq(call->name, "with_fallback")) return self_value_t;
- code_err(ast, "There is no '", call->name, "' method for ", type_to_str(self_value_t), " tables");
+ code_err(ast, "There is no '", call->name, "' method for ", type_to_text(self_value_t), " tables");
}
default: {
if (call->name[0] == '_') {
@@ -1114,7 +1118,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (field_type && field_type->tag == FunctionType) return Match(field_type, FunctionType)->ret;
type_t *fn_type_t = get_method_type(env, call->self, call->name);
if (!fn_type_t) code_err(ast, "No such method!");
- if (fn_type_t->tag != FunctionType) code_err(ast, "This isn't a method, it's a ", type_to_str(fn_type_t));
+ if (fn_type_t->tag != FunctionType) code_err(ast, "This isn't a method, it's a ", type_to_text(fn_type_t));
DeclareMatch(fn_type, fn_type_t, FunctionType);
return fn_type->ret;
}
@@ -1203,7 +1207,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (fn->args && type_eq(t, get_arg_type(env, fn->args)) && type_eq(t, fn->ret)) return t;
}
- code_err(ast, "I don't know how to get the negative value of type ", type_to_str(t));
+ code_err(ast, "I don't know how to get the negative value of type ", type_to_text(t));
}
case Not: {
type_t *t = get_type(env, Match(ast, Not)->value);
@@ -1217,7 +1221,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (fn->args && type_eq(t, get_arg_type(env, fn->args)) && type_eq(t, fn->ret)) return t;
}
code_err(ast, "I only know how to get 'not' of boolean, numeric, and optional pointer types, not ",
- type_to_str(t));
+ type_to_text(t));
}
case Or: {
binary_operands_t binop = BINARY_OPERANDS(ast);
@@ -1245,8 +1249,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (rhs_t->tag == OptionalType) {
type_t *result = most_complete_type(lhs_t, rhs_t);
if (result == NULL)
- code_err(ast, "I could not determine the type of ", type_to_str(lhs_t), " `or` ",
- type_to_str(rhs_t));
+ code_err(ast, "I could not determine the type of ", type_to_text(lhs_t), " `or` ",
+ type_to_text(rhs_t));
return result;
} else if (rhs_t->tag == AbortType || rhs_t->tag == ReturnType) {
return Match(lhs_t, OptionalType)->type;
@@ -1262,7 +1266,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
} else if (lhs_t->tag == SetType && rhs_t->tag == SetType && type_eq(lhs_t, rhs_t)) {
return lhs_t;
}
- code_err(ast, "I couldn't figure out how to do `or` between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I couldn't figure out how to do `or` between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
case And: {
binary_operands_t binop = BINARY_OPERANDS(ast);
@@ -1294,8 +1299,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
} else if (lhs_t->tag == SetType && rhs_t->tag == SetType && type_eq(lhs_t, rhs_t)) {
return lhs_t;
}
- code_err(ast, "I couldn't figure out how to do `and` between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I couldn't figure out how to do `and` between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
case Xor: {
binary_operands_t binop = BINARY_OPERANDS(ast);
@@ -1327,8 +1332,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
} else if (lhs_t->tag == SetType && rhs_t->tag == SetType && type_eq(lhs_t, rhs_t)) {
return lhs_t;
}
- code_err(ast, "I couldn't figure out how to do `xor` between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I couldn't figure out how to do `xor` between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
case Compare:
case Equals:
@@ -1345,7 +1350,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
|| can_compile_to_type(env, binop.rhs, lhs_t) || can_compile_to_type(env, binop.lhs, rhs_t))
return ast->tag == Compare ? Type(IntType, .bits = TYPE_IBITS32) : Type(BoolType);
- code_err(ast, "I don't know how to compare ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I don't know how to compare ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
}
case Power:
case Multiply:
@@ -1370,7 +1375,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (ast->tag == LeftShift || ast->tag == UnsignedLeftShift || ast->tag == RightShift
|| ast->tag == UnsignedRightShift) {
if (!is_int_type(rhs_t))
- code_err(binop.rhs, "I only know how to do bit shifting by integer amounts, not ", type_to_str(rhs_t));
+ code_err(binop.rhs, "I only know how to do bit shifting by integer amounts, not ", type_to_text(rhs_t));
}
if (is_numeric_type(lhs_t) && binop.rhs->tag == Int) {
@@ -1426,16 +1431,16 @@ type_t *get_type(env_t *env, ast_t *ast) {
(can_compile_to_type(env, binop.rhs, lhs_t) ? lhs_t
: (can_compile_to_type(env, binop.lhs, rhs_t) ? rhs_t : NULL));
if (overall_t == NULL)
- code_err(ast, "I don't know how to do math operations between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I don't know how to do math operations between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
binding_t *b = get_metamethod_binding(env, ast->tag, binop.lhs, binop.rhs, overall_t);
if (b) return overall_t;
if (is_numeric_type(lhs_t) && is_numeric_type(rhs_t)) return overall_t;
- code_err(ast, "I don't know how to do math operations between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I don't know how to do math operations between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
case Concat: {
binary_operands_t binop = BINARY_OPERANDS(ast);
@@ -1446,15 +1451,16 @@ type_t *get_type(env_t *env, ast_t *ast) {
(can_compile_to_type(env, binop.rhs, lhs_t) ? lhs_t
: (can_compile_to_type(env, binop.lhs, rhs_t) ? rhs_t : NULL));
if (overall_t == NULL)
- code_err(ast, "I don't know how to do operations between ", type_to_str(lhs_t), " and ",
- type_to_str(rhs_t));
+ code_err(ast, "I don't know how to do operations between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
binding_t *b = get_metamethod_binding(env, ast->tag, binop.lhs, binop.rhs, overall_t);
if (b) return overall_t;
if (overall_t->tag == ListType || overall_t->tag == SetType || overall_t->tag == TextType) return overall_t;
- code_err(ast, "I don't know how to do concatenation between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ code_err(ast, "I don't know how to do concatenation between ", type_to_text(lhs_t), " and ",
+ type_to_text(rhs_t));
}
case Reduction: {
@@ -1468,7 +1474,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *iterated = get_iterated_type(iter_t);
if (!iterated)
- code_err(reduction->iter, "I don't know how to do a reduction over ", type_to_str(iter_t), " values");
+ code_err(reduction->iter, "I don't know how to do a reduction over ", type_to_text(iter_t), " values");
if (reduction->key && !(reduction->op == Min || reduction->op == Max)) {
env_t *item_scope = fresh_scope(env);
const char *op_str = binop_info[reduction->op].operator;
@@ -1487,8 +1493,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *lhs_t = get_type(env, lhs), *rhs_t = get_type(env, rhs);
type_t *t = type_or_type(lhs_t, rhs_t);
if (!t)
- code_err(ast, "The two sides of this operation are not compatible: ", type_to_str(lhs_t), " vs ",
- type_to_str(rhs_t));
+ code_err(ast, "The two sides of this operation are not compatible: ", type_to_text(lhs_t), " vs ",
+ type_to_text(rhs_t));
return t;
}
@@ -1533,8 +1539,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *false_t = get_type(falsey_scope, if_->else_body);
type_t *t_either = type_or_type(true_t, false_t);
if (!t_either)
- code_err(if_->else_body, "I was expecting this block to have a ", type_to_str(true_t),
- " value (based on earlier clauses), but it actually has a ", type_to_str(false_t), " value.");
+ code_err(if_->else_body, "I was expecting this block to have a ", type_to_text(true_t),
+ " value (based on earlier clauses), but it actually has a ", type_to_text(false_t), " value.");
return t_either;
}
@@ -1568,7 +1574,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
if (clause->pattern->tag == Var) tag_name = Match(clause->pattern, Var)->name;
else if (clause->pattern->tag == FunctionCall && Match(clause->pattern, FunctionCall)->fn->tag == Var)
tag_name = Match(Match(clause->pattern, FunctionCall)->fn, Var)->name;
- else code_err(clause->pattern, "This is not a valid pattern for a ", type_to_str(subject_t), " enum");
+ else code_err(clause->pattern, "This is not a valid pattern for a ", type_to_text(subject_t), " enum");
Text_t valid_tags = EMPTY_TEXT;
for (match_t *m = matches; m; m = m->next) {
@@ -1581,7 +1587,7 @@ type_t *get_type(env_t *env, ast_t *ast) {
valid_tags = Texts(valid_tags, m->tag->name);
}
- code_err(clause->pattern, "There is no tag '", tag_name, "' for the type ", type_to_str(subject_t),
+ code_err(clause->pattern, "There is no tag '", tag_name, "' for the type ", type_to_text(subject_t),
" (valid tags: ", valid_tags, ")");
found_matching_tag:;
}
@@ -1591,8 +1597,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *clause_type = get_type(clause_scope, clause->body);
type_t *merged = type_or_type(overall_t, clause_type);
if (!merged)
- code_err(clause->body, "The type of this branch is ", type_to_str(clause_type),
- ", which conflicts with the earlier branch type of ", type_to_str(overall_t));
+ code_err(clause->body, "The type of this branch is ", type_to_text(clause_type),
+ ", which conflicts with the earlier branch type of ", type_to_text(overall_t));
overall_t = merged;
}
@@ -1612,8 +1618,8 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *else_t = get_type(env, when->else_body);
type_t *merged = type_or_type(overall_t, else_t);
if (!merged)
- code_err(when->else_body, "I was expecting this block to have a ", type_to_str(overall_t),
- " value (based on earlier clauses), but it actually has a ", type_to_str(else_t), " value.");
+ code_err(when->else_body, "I was expecting this block to have a ", type_to_text(overall_t),
+ " value (based on earlier clauses), but it actually has a ", type_to_text(else_t), " value.");
return merged;
} else {
Text_t unhandled = EMPTY_TEXT;
diff --git a/src/types.c b/src/types.c
index a670f212..7db46b27 100644
--- a/src/types.c
+++ b/src/types.c
@@ -68,21 +68,22 @@ Text_t type_to_text(type_t *t) {
}
case EnumType: {
DeclareMatch(enum_, t, EnumType);
- return Text$from_str(enum_->name);
- // Text_t text = Text("enum(");
- // for (tag_t *tag = enum_->tags; tag; tag = tag->next) {
- // text = Texts(text, Text$from_str(tag->name));
- // if (tag->type && Match(tag->type, StructType)->fields) {
- // text = Texts(text, "(");
- // for (arg_t *field = Match(tag->type, StructType)->fields; field; field = field->next) {
- // text = Texts(text, Text$from_str(field->name), ":", type_to_text(field->type));
- // if (field->next) text = Texts(text, ", ");
- // }
- // text = Texts(text, ")");
- // }
- // if (tag->next) text = Texts(text, ", ");
- // }
- // return enum_->name ? Text$from_str(enum_->name) : Text("enum");
+ if (enum_->name != NULL && strncmp(enum_->name, "enum$", strlen("enum$")) != 0)
+ return Text$from_str(enum_->name);
+ Text_t text = Text("enum(");
+ for (tag_t *tag = enum_->tags; tag; tag = tag->next) {
+ text = Texts(text, Text$from_str(tag->name));
+ if (tag->type && Match(tag->type, StructType)->fields) {
+ text = Texts(text, "(");
+ for (arg_t *field = Match(tag->type, StructType)->fields; field; field = field->next) {
+ text = Texts(text, Text$from_str(field->name), ":", type_to_text(field->type));
+ if (field->next) text = Texts(text, ", ");
+ }
+ text = Texts(text, ")");
+ }
+ if (tag->next) text = Texts(text, ", ");
+ }
+ return Texts(text, ")");
}
case OptionalType: {
type_t *opt = Match(t, OptionalType)->type;
@@ -102,8 +103,6 @@ Text_t type_to_text(type_t *t) {
}
}
-const char *type_to_str(type_t *t) { return Text$as_c_string(type_to_text(t)); }
-
PUREFUNC const char *get_type_name(type_t *t) {
switch (t->tag) {
case TextType: return Match(t, TextType)->lang;
diff --git a/src/types.h b/src/types.h
index 5b5c4fb9..24c4e621 100644
--- a/src/types.h
+++ b/src/types.h
@@ -139,7 +139,6 @@ struct type_s {
_make_function_type(ret, sizeof((arg_t[]){__VA_ARGS__}) / sizeof(arg_t), (arg_t[]){__VA_ARGS__})
Text_t type_to_text(type_t *t);
-const char *type_to_str(type_t *t);
const char *get_type_name(type_t *t);
PUREFUNC bool type_eq(type_t *a, type_t *b);
PUREFUNC bool type_is_a(type_t *t, type_t *req);