aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-04-28 16:05:09 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-04-28 16:05:09 -0400
commit9da5949b953ae5424afb77ff4280399eacf414d4 (patch)
tree4db2b1ec3abe4f4e63d0fd57c3efbf588c8f92f4 /src
parenta49610246e12d8e2947f8ce2bc981acbbb88a901 (diff)
Remove remaining printf references
Diffstat (limited to 'src')
-rw-r--r--src/ast.c135
-rw-r--r--src/compile.c243
-rw-r--r--src/cordhelpers.c17
-rw-r--r--src/cordhelpers.h3
-rw-r--r--src/enums.c7
-rw-r--r--src/stdlib/fpconv.h2
-rw-r--r--src/stdlib/integers.c7
-rw-r--r--src/stdlib/print.c102
-rw-r--r--src/stdlib/print.h7
-rw-r--r--src/structs.c17
-rw-r--r--src/tomo.c11
-rw-r--r--src/typecheck.c4
-rw-r--r--src/types.c9
13 files changed, 315 insertions, 249 deletions
diff --git a/src/ast.c b/src/ast.c
index 65aa572a..5d8b2021 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -112,16 +112,15 @@ CORD type_ast_to_sexp(type_ast_t *t)
if (!t) return "nil";
switch (t->tag) {
-#define T(type, ...) case type: { __typeof(t->__data.type) data = t->__data.type; (void)data; return CORD_asprintf(__VA_ARGS__); }
+#define T(type, ...) case type: { __typeof(t->__data.type) data = t->__data.type; (void)data; return CORD_all(__VA_ARGS__); }
T(UnknownTypeAST, "(UnknownType)")
- T(VarTypeAST, "(VarType \"%s\")", data.name)
- T(PointerTypeAST, "(PointerType \"%s\" %r)",
- data.is_stack ? "stack" : "heap", type_ast_to_sexp(data.pointed))
- T(ListTypeAST, "(ListType %r)", type_ast_to_sexp(data.item))
- T(SetTypeAST, "(SetType %r)", type_ast_to_sexp(data.item))
- T(TableTypeAST, "(TableType %r %r)", type_ast_to_sexp(data.key), type_ast_to_sexp(data.value))
- T(FunctionTypeAST, "(FunctionType %r %r)", arg_defs_to_sexp(data.args), type_ast_to_sexp(data.ret))
- T(OptionalTypeAST, "(OptionalType %r)", type_ast_to_sexp(data.type))
+ T(VarTypeAST, "(VarType \"", data.name, "\")")
+ T(PointerTypeAST, "(PointerType \"", data.is_stack ? "stack" : "heap", "\" ", type_ast_to_sexp(data.pointed), ")")
+ T(ListTypeAST, "(ListType ", type_ast_to_sexp(data.item), ")")
+ T(SetTypeAST, "(SetType ", type_ast_to_sexp(data.item), ")")
+ T(TableTypeAST, "(TableType ", type_ast_to_sexp(data.key), " ", type_ast_to_sexp(data.value), ")")
+ T(FunctionTypeAST, "(FunctionType ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret), ")")
+ T(OptionalTypeAST, "(OptionalType ", type_ast_to_sexp(data.type), ")")
#undef T
default: return CORD_EMPTY;
}
@@ -142,19 +141,19 @@ CORD ast_to_sexp(ast_t *ast)
if (!ast) return "nil";
switch (ast->tag) {
-#define T(type, ...) case type: { __typeof(ast->__data.type) data = ast->__data.type; (void)data; return CORD_asprintf(__VA_ARGS__); }
+#define T(type, ...) case type: { __typeof(ast->__data.type) data = ast->__data.type; (void)data; return CORD_all(__VA_ARGS__); }
T(Unknown, "(Unknown)")
T(None, "(None)")
- T(Bool, "(Bool %s)", data.b ? "yes" : "no")
- T(Var, "(Var %r)", CORD_quoted(data.name))
- T(Int, "(Int %r)", CORD_quoted(ast_source(ast)))
- T(Num, "(Num %r)", CORD_quoted(ast_source(ast)))
- T(TextLiteral, "%r", CORD_quoted(data.cord))
- T(TextJoin, "(Text%r%r)", data.lang ? CORD_all(" :lang ", CORD_quoted(data.lang)) : CORD_EMPTY, ast_list_to_sexp(data.children))
- T(Path, "(Path %r)", CORD_quoted(data.path))
- T(Declare, "(Declare %r %r %r)", ast_to_sexp(data.var), type_ast_to_sexp(data.type), ast_to_sexp(data.value))
- T(Assign, "(Assign (targets %r) (values %r))", ast_list_to_sexp(data.targets), ast_list_to_sexp(data.values))
-#define BINOP(name) T(name, "(" #name " %r %r)", ast_to_sexp(data.lhs), ast_to_sexp(data.rhs))
+ T(Bool, "(Bool ", data.b ? "yes" : "no", ")")
+ T(Var, "(Var ", CORD_quoted(data.name), ")")
+ T(Int, "(Int ", CORD_quoted(ast_source(ast)), ")")
+ T(Num, "(Num ", CORD_quoted(ast_source(ast)), ")")
+ T(TextLiteral, CORD_quoted(data.cord))
+ T(TextJoin, "(Text", data.lang ? CORD_all(" :lang ", CORD_quoted(data.lang)) : CORD_EMPTY, ast_list_to_sexp(data.children), ")")
+ T(Path, "(Path ", CORD_quoted(data.path), ")")
+ T(Declare, "(Declare ", ast_to_sexp(data.var), " ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value), ")")
+ T(Assign, "(Assign (targets ", ast_list_to_sexp(data.targets), ") (values ", ast_list_to_sexp(data.values), "))")
+#define BINOP(name) T(name, "(" #name " ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), ")")
BINOP(Power) BINOP(PowerUpdate) BINOP(Multiply) BINOP(MultiplyUpdate) BINOP(Divide) BINOP(DivideUpdate) BINOP(Mod) BINOP(ModUpdate)
BINOP(Mod1) BINOP(Mod1Update) BINOP(Plus) BINOP(PlusUpdate) BINOP(Minus) BINOP(MinusUpdate) BINOP(Concat) BINOP(ConcatUpdate)
BINOP(LeftShift) BINOP(LeftShiftUpdate) BINOP(RightShift) BINOP(RightShiftUpdate) BINOP(UnsignedLeftShift) BINOP(UnsignedLeftShiftUpdate)
@@ -162,58 +161,52 @@ CORD ast_to_sexp(ast_t *ast)
BINOP(Xor) BINOP(XorUpdate) BINOP(Compare)
BINOP(Equals) BINOP(NotEquals) BINOP(LessThan) BINOP(LessThanOrEquals) BINOP(GreaterThan) BINOP(GreaterThanOrEquals)
#undef BINOP
- T(Negative, "(Negative %r)", ast_to_sexp(data.value))
- T(Not, "(Not %r)", ast_to_sexp(data.value))
- T(HeapAllocate, "(HeapAllocate %r)", ast_to_sexp(data.value))
- T(StackReference, "(StackReference %r)", ast_to_sexp(data.value))
- T(Min, "(Min %r %r%r)", ast_to_sexp(data.lhs), ast_to_sexp(data.rhs), optional_sexp("key", data.key))
- T(Max, "(Max %r %r%r)", ast_to_sexp(data.lhs), ast_to_sexp(data.rhs), optional_sexp("key", data.key))
- T(List, "(List%r)", ast_list_to_sexp(data.items))
- T(Set, "(Set%r)", ast_list_to_sexp(data.items))
- T(Table, "(Table%r%r%r)",
- optional_sexp("default", data.default_value),
- optional_sexp("fallback", data.fallback),
- ast_list_to_sexp(data.entries))
- T(TableEntry, "(TableEntry %r %r)", ast_to_sexp(data.key), ast_to_sexp(data.value))
- T(Comprehension, "(Comprehension %r (vars%r) %r %r)", ast_to_sexp(data.expr),
- ast_list_to_sexp(data.vars), ast_to_sexp(data.iter),
- optional_sexp("filter", data.filter))
- T(FunctionDef, "(FunctionDef %r %r%r %r)", ast_to_sexp(data.name),
- arg_defs_to_sexp(data.args), optional_type_sexp("return", data.ret_type), ast_to_sexp(data.body))
- T(ConvertDef, "(ConvertDef %r %r %r)",
- arg_defs_to_sexp(data.args), type_ast_to_sexp(data.ret_type), ast_to_sexp(data.body))
- T(Lambda, "(Lambda %r%r %r)", arg_defs_to_sexp(data.args),
- optional_type_sexp("return", data.ret_type), ast_to_sexp(data.body))
- T(FunctionCall, "(FunctionCall %r%r)", ast_to_sexp(data.fn), arg_list_to_sexp(data.args))
- T(MethodCall, "(MethodCall %r %r%r)", ast_to_sexp(data.self), CORD_quoted(data.name), arg_list_to_sexp(data.args))
- T(Block, "(Block%r)", ast_list_to_sexp(data.statements))
- T(For, "(For (vars%r) %r %r %r)", ast_list_to_sexp(data.vars), ast_to_sexp(data.iter),
- ast_to_sexp(data.body), ast_to_sexp(data.empty))
- T(While, "(While %r %r)", ast_to_sexp(data.condition), ast_to_sexp(data.body))
- T(Repeat, "(Repeat %r)", ast_to_sexp(data.body))
- T(If, "(If %r %r%r)", ast_to_sexp(data.condition), ast_to_sexp(data.body), optional_sexp("else", data.else_body))
- T(When, "(When %r%r%r)", ast_to_sexp(data.subject), when_clauses_to_sexp(data.clauses), optional_sexp("else", data.else_body))
- T(Reduction, "(Reduction %r %r %r)", CORD_quoted(binop_method_name(data.op)), ast_to_sexp(data.key),
- ast_to_sexp(data.iter))
- T(Skip, "(Skip %r)", CORD_quoted(data.target))
- T(Stop, "(Stop %r)", CORD_quoted(data.target))
+ T(Negative, "(Negative ", ast_to_sexp(data.value), ")")
+ T(Not, "(Not ", ast_to_sexp(data.value), ")")
+ T(HeapAllocate, "(HeapAllocate ", ast_to_sexp(data.value), ")")
+ T(StackReference, "(StackReference ", ast_to_sexp(data.value), ")")
+ T(Min, "(Min ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")")
+ T(Max, "(Max ", ast_to_sexp(data.lhs), " ", ast_to_sexp(data.rhs), optional_sexp("key", data.key), ")")
+ T(List, "(List", ast_list_to_sexp(data.items), ")")
+ T(Set, "(Set", ast_list_to_sexp(data.items), ")")
+ T(Table, "(Table", optional_sexp("default", data.default_value), optional_sexp("fallback", data.fallback),
+ ast_list_to_sexp(data.entries), ")")
+ T(TableEntry, "(TableEntry ", ast_to_sexp(data.key), " ", ast_to_sexp(data.value), ")")
+ T(Comprehension, "(Comprehension ", ast_to_sexp(data.expr), " (vars", ast_list_to_sexp(data.vars), ") ",
+ ast_to_sexp(data.iter), " ", optional_sexp("filter", data.filter), ")")
+ T(FunctionDef, "(FunctionDef ", ast_to_sexp(data.name), " ", arg_defs_to_sexp(data.args),
+ optional_type_sexp("return", data.ret_type), " ", ast_to_sexp(data.body), ")")
+ T(ConvertDef, "(ConvertDef ", arg_defs_to_sexp(data.args), " ", type_ast_to_sexp(data.ret_type), " ", ast_to_sexp(data.body), ")")
+ T(Lambda, "(Lambda ", arg_defs_to_sexp(data.args), optional_type_sexp("return", data.ret_type), " ", ast_to_sexp(data.body), ")")
+ T(FunctionCall, "(FunctionCall ", ast_to_sexp(data.fn), arg_list_to_sexp(data.args), ")")
+ T(MethodCall, "(MethodCall ", ast_to_sexp(data.self), " ", CORD_quoted(data.name), arg_list_to_sexp(data.args), ")")
+ T(Block, "(Block", ast_list_to_sexp(data.statements), ")")
+ T(For, "(For (vars", ast_list_to_sexp(data.vars), ") ", ast_to_sexp(data.iter), " ", ast_to_sexp(data.body),
+ " ", ast_to_sexp(data.empty), ")")
+ T(While, "(While ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), ")")
+ T(Repeat, "(Repeat ", ast_to_sexp(data.body), ")")
+ T(If, "(If ", ast_to_sexp(data.condition), " ", ast_to_sexp(data.body), optional_sexp("else", data.else_body), ")")
+ T(When, "(When ", ast_to_sexp(data.subject), when_clauses_to_sexp(data.clauses), optional_sexp("else", data.else_body), ")")
+ T(Reduction, "(Reduction ", CORD_quoted(binop_method_name(data.op)), " ", ast_to_sexp(data.key), " ", ast_to_sexp(data.iter), ")")
+ T(Skip, "(Skip ", CORD_quoted(data.target), ")")
+ T(Stop, "(Stop ", CORD_quoted(data.target), ")")
T(Pass, "(Pass)")
- T(Defer, "(Defer %r)", ast_to_sexp(data.body))
- T(Return, "(Return %r)", ast_to_sexp(data.value))
- T(Extern, "(Extern \"%s\" %r)", data.name, type_ast_to_sexp(data.type))
- T(StructDef, "(StructDef \"%s\" %r %r)", data.name, arg_defs_to_sexp(data.fields), ast_to_sexp(data.namespace))
- T(EnumDef, "(EnumDef \"%s\" (tags %r) %r)", data.name, tags_to_sexp(data.tags), ast_to_sexp(data.namespace))
- T(LangDef, "(LangDef \"%s\" %r)", data.name, ast_to_sexp(data.namespace))
- T(Index, "(Index %r %r)", ast_to_sexp(data.indexed), ast_to_sexp(data.index))
- T(FieldAccess, "(FieldAccess %r \"%s\")", ast_to_sexp(data.fielded), data.field)
- T(Optional, "(Optional %r)", ast_to_sexp(data.value))
- T(NonOptional, "(NonOptional %r)", ast_to_sexp(data.value))
- T(DocTest, "(DocTest %r%r)", ast_to_sexp(data.expr), optional_sexp("expected", data.expected))
- T(Assert, "(Assert %r %r)", ast_to_sexp(data.expr), optional_sexp("message", data.message))
- T(Use, "(Use %r %r)", optional_sexp("var", data.var), CORD_quoted(data.path))
- T(InlineCCode, "(InlineCCode %r%r)", ast_list_to_sexp(data.chunks), optional_type_sexp("type", data.type_ast))
- T(Deserialize, "(Deserialize %r %r)", type_ast_to_sexp(data.type), ast_to_sexp(data.value))
- T(Extend, "(Extend \"%s\" %r)", data.name, ast_to_sexp(data.body))
+ T(Defer, "(Defer ", ast_to_sexp(data.body), ")")
+ T(Return, "(Return ", ast_to_sexp(data.value), ")")
+ T(Extern, "(Extern \"", data.name, "\" ", type_ast_to_sexp(data.type), ")")
+ T(StructDef, "(StructDef \"", data.name, "\" ", arg_defs_to_sexp(data.fields), " ", ast_to_sexp(data.namespace), ")")
+ T(EnumDef, "(EnumDef \"", data.name, "\" (tags ", tags_to_sexp(data.tags), ") ", ast_to_sexp(data.namespace), ")")
+ T(LangDef, "(LangDef \"", data.name, "\" ", ast_to_sexp(data.namespace), ")")
+ T(Index, "(Index ", ast_to_sexp(data.indexed), " ", ast_to_sexp(data.index), ")")
+ T(FieldAccess, "(FieldAccess ", ast_to_sexp(data.fielded), " \"", data.field, "\")")
+ T(Optional, "(Optional ", ast_to_sexp(data.value), ")")
+ T(NonOptional, "(NonOptional ", ast_to_sexp(data.value), ")")
+ T(DocTest, "(DocTest ", ast_to_sexp(data.expr), optional_sexp("expected", data.expected), ")")
+ T(Assert, "(Assert ", ast_to_sexp(data.expr), " ", optional_sexp("message", data.message), ")")
+ T(Use, "(Use ", optional_sexp("var", data.var), " ", CORD_quoted(data.path), ")")
+ T(InlineCCode, "(InlineCCode ", ast_list_to_sexp(data.chunks), optional_type_sexp("type", data.type_ast), ")")
+ T(Deserialize, "(Deserialize ", type_ast_to_sexp(data.type), " ", ast_to_sexp(data.value), ")")
+ T(Extend, "(Extend \"", data.name, "\" ", ast_to_sexp(data.body), ")")
default: errx(1, "S-expressions are not implemented for this AST");
#undef T
}
diff --git a/src/compile.c b/src/compile.c
index 37b3934f..1c49c09b 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -73,7 +73,7 @@ static CORD with_source_info(env_t *env, ast_t *ast, CORD code)
if (code == CORD_EMPTY || !ast || !ast->file || !env->do_source_mapping)
return code;
int64_t line = get_line_number(ast->file, ast->start);
- return CORD_asprintf("\n#line %ld\n%r", line, code);
+ return CORD_all("\n#line ", String(line), "\n", code);
}
static bool promote(env_t *env, ast_t *ast, CORD *code, type_t *actual, type_t *needed)
@@ -114,10 +114,10 @@ static bool promote(env_t *env, ast_t *ast, CORD *code, type_t *actual, type_t *
if (needed->tag == NumType && actual->tag == OptionalType && Match(actual, OptionalType)->type->tag == NumType) {
*code = CORD_all("({ ", compile_declaration(actual, "opt"), " = ", *code, "; ",
"if unlikely (", check_none(actual, "opt"), ")\n",
- CORD_asprintf("fail_source(%r, %ld, %ld, \"This was expected to be a value, but it's none\");\n",
- CORD_quoted(ast->file->filename),
- (long)(ast->start - ast->file->text),
- (long)(ast->end - ast->file->text)),
+ "fail_source(", CORD_quoted(ast->file->filename), ", ",
+ String((int64_t)(ast->start - ast->file->text)), ", ",
+ String((int64_t)(ast->end - ast->file->text)), ", ",
+ "\"This was expected to be a value, but it's none\");\n",
optional_into_nonnone(actual, "opt"), "; })");
return true;
}
@@ -792,8 +792,8 @@ CORD compile_type(type_t *t)
case ByteType: return "Byte_t";
case CStringType: return "const char*";
case BigIntType: return "Int_t";
- case IntType: return CORD_asprintf("Int%ld_t", Match(t, IntType)->bits);
- case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits);
+ case IntType: return CORD_all("Int", String(Match(t, IntType)->bits), "_t");
+ case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? "Num_t" : CORD_all("Num", String(Match(t, NumType)->bits), "_t");
case TextType: {
DeclareMatch(text, t, TextType);
if (!text->lang || streq(text->lang, "Text"))
@@ -1188,11 +1188,14 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
expr_t = lhs_t;
env_t *val_scope = with_enum_scope(env, lhs_t);
CORD val_code = compile_to_type(val_scope, value->ast, lhs_t);
- CORD_appendf(&test_code, "%r $%ld = %r;\n", compile_type(lhs_t), i++, val_code);
+ test_code = CORD_all(test_code, compile_type(lhs_t), " $", String(i), " = ", val_code, ";\n");
+ i += 1;
}
i = 1;
- for (ast_list_t *target = assign->targets; target; target = target->next)
- test_code = CORD_all(test_code, compile_assignment(env, target->ast, CORD_asprintf("$%ld", i++)), ";\n");
+ for (ast_list_t *target = assign->targets; target; target = target->next) {
+ test_code = CORD_all(test_code, compile_assignment(env, target->ast, CORD_all("$", String(i))), ";\n");
+ i += 1;
+ }
test_code = CORD_all(test_code, "$1; })");
}
@@ -1218,27 +1221,27 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
test_code = compile(env, test->expr);
}
if (test->expected) {
- return CORD_asprintf(
- "%rtest(%r, %r, %r, %r, %ld, %ld);",
- setup, compile_type(expr_t), test_code,
- compile_to_type(env, test->expected, expr_t),
- compile_type_info(expr_t),
- (int64_t)(test->expr->start - test->expr->file->text),
- (int64_t)(test->expr->end - test->expr->file->text));
+ return CORD_all(
+ setup,
+ "test(", compile_type(expr_t), ", ", test_code, ", ",
+ compile_to_type(env, test->expected, expr_t), ", ",
+ compile_type_info(expr_t), ", ",
+ String((int64_t)(test->expr->start - test->expr->file->text)), ", ",
+ String((int64_t)(test->expr->end - test->expr->file->text)), ");");
} else {
if (expr_t->tag == VoidType || expr_t->tag == AbortType) {
- return CORD_asprintf("%rinspect_void(%r, %r, %ld, %ld);",
- setup, test_code,
- compile_type_info(expr_t),
- (int64_t)(test->expr->start - test->expr->file->text),
- (int64_t)(test->expr->end - test->expr->file->text));
+ return CORD_all(
+ setup,
+ "inspect_void(", test_code, ", ", compile_type_info(expr_t), ", ",
+ String((int64_t)(test->expr->start - test->expr->file->text)), ", ",
+ String((int64_t)(test->expr->end - test->expr->file->text)), ");");
}
- return CORD_asprintf(
- "%rinspect(%r, %r, %r, %ld, %ld);",
- setup, compile_type(expr_t), test_code,
- compile_type_info(expr_t),
- (int64_t)(test->expr->start - test->expr->file->text),
- (int64_t)(test->expr->end - test->expr->file->text));
+ return CORD_all(
+ setup,
+ "inspect(", compile_type(expr_t), ", ", test_code, ", ",
+ compile_type_info(expr_t), ", ",
+ String((int64_t)(test->expr->start - test->expr->file->text)), ", ",
+ String((int64_t)(test->expr->end - test->expr->file->text)), ");");
}
}
case Assert: {
@@ -1283,26 +1286,26 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
compile_declaration(operand_t, "_lhs"), " = ", compile_to_type(env, cmp.lhs, operand_t), ";\n",
compile_declaration(operand_t, "_rhs"), " = ", compile_to_type(env, cmp.rhs, operand_t), ";\n",
"if (!(", compile_condition(env, var_comparison), "))\n",
- CORD_asprintf("fail_source(%r, %ld, %ld, %r, \" (\", %r, \" %s \", %r, \")\");\n",
- CORD_quoted(ast->file->filename),
- (long)(expr->start - expr->file->text),
- (long)(expr->end - expr->file->text),
- message ? CORD_all("Text$as_c_string(", compile_to_type(env, message, Type(TextType)), ")")
- : "\"This assertion failed!\"",
- expr_as_text("_lhs", operand_t, "no"),
- failure,
- expr_as_text("_rhs", operand_t, "no")),
+ CORD_all(
+ "fail_source(", CORD_quoted(ast->file->filename), ", ",
+ String((int64_t)(expr->start - expr->file->text)), ", ",
+ String((int64_t)(expr->end - expr->file->text)), ", ",
+ message ? CORD_all("Text$as_c_string(", compile_to_type(env, message, Type(TextType)), ")")
+ : "\"This assertion failed!\"", ", ",
+ "\" (\", ", expr_as_text("_lhs", operand_t, "no"), ", "
+ "\" ", failure, " \", ", expr_as_text("_rhs", operand_t, "no"), ", \")\");\n"),
"}\n");
}
default: {
- return CORD_all("if (!(", compile_condition(env, expr), "))\n",
- CORD_asprintf("fail_source(%r, %ld, %ld, %r);\n",
- CORD_quoted(ast->file->filename),
- (long)(expr->start - expr->file->text),
- (long)(expr->end - expr->file->text),
- message ? CORD_all("Text$as_c_string(", compile_to_type(env, message, Type(TextType)), ")")
- : "\"This assertion failed!\""));
+ return CORD_all(
+ "if (!(", compile_condition(env, expr), "))\n",
+ "fail_source(", CORD_quoted(ast->file->filename), ", ",
+ String((long)(expr->start - expr->file->text)), ", ",
+ String((long)(expr->end - expr->file->text)), ", ",
+ message ? CORD_all("Text$as_c_string(", compile_to_type(env, message, Type(TextType)), ")")
+ : "\"This assertion failed!\"",
+ ");\n");
}
}
}
@@ -1350,11 +1353,13 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
code_err(ast, "Stack references cannot be assigned to variables because the variable's scope may outlive the scope of the stack memory.");
env_t *val_env = with_enum_scope(env, lhs_t);
CORD val = compile_to_type(val_env, value->ast, lhs_t);
- CORD_appendf(&code, "%r $%ld = %r;\n", compile_type(lhs_t), i++, val);
+ code = CORD_all(code, compile_type(lhs_t), " $", String(i), " = ", val, ";\n");
+ i += 1;
}
i = 1;
for (ast_list_t *target = assign->targets; target; target = target->next) {
- code = CORD_all(code, compile_assignment(env, target->ast, CORD_asprintf("$%ld", i++)), ";\n");
+ code = CORD_all(code, compile_assignment(env, target->ast, CORD_all("$", String(i))), ";\n");
+ i += 1;
}
return CORD_cat(code, "\n}");
}
@@ -1410,7 +1415,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (matched) {
if (!ctx->skip_label) {
static int64_t skip_label_count = 1;
- CORD_sprintf(&ctx->skip_label, "skip_%ld", skip_label_count);
+ ctx->skip_label = CORD_all("skip_", String(skip_label_count));
++skip_label_count;
}
CORD code = CORD_EMPTY;
@@ -1439,7 +1444,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (matched) {
if (!ctx->stop_label) {
static int64_t stop_label_count = 1;
- CORD_sprintf(&ctx->stop_label, "stop_%ld", stop_label_count);
+ ctx->stop_label = CORD_all("stop_", String(stop_label_count));
++stop_label_count;
}
CORD code = CORD_EMPTY;
@@ -1473,7 +1478,8 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (CORD_ncmp(entry->b->code, 0, "userdata->", 0, strlen("userdata->")) == 0) {
Table$str_set(defer_env->locals, entry->name, entry->b);
} else {
- CORD defer_name = CORD_asprintf("defer$%d$%s", ++defer_id, entry->name);
+ CORD defer_name = CORD_all("defer$", String(++defer_id), "$", entry->name);
+ defer_id += 1;
code = CORD_all(
code, compile_declaration(entry->b->type, defer_name), " = ", entry->b->code, ";\n");
set_binding(defer_env, entry->name, entry->b->type, defer_name);
@@ -1992,7 +1998,7 @@ static CORD _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");
- return CORD_asprintf("(void)%r;", compile(env, ast));
+ return CORD_all("(void)", compile(env, ast), ";");
}
}
@@ -2004,24 +2010,24 @@ CORD compile_statement(env_t *env, ast_t *ast) {
CORD expr_as_text(CORD expr, type_t *t, CORD color)
{
switch (t->tag) {
- case MemoryType: return CORD_asprintf("Memory$as_text(stack(%r), %r, &Memory$info)", expr, color);
+ case MemoryType: return CORD_all("Memory$as_text(stack(", expr, "), ", color, ", &Memory$info)");
case BoolType:
// NOTE: this cannot use stack(), since bools may actually be bit fields:
- return CORD_asprintf("Bool$as_text((Bool_t[1]){%r}, %r, &Bool$info)", expr, color);
- case CStringType: return CORD_asprintf("CString$as_text(stack(%r), %r, &CString$info)", expr, color);
+ return CORD_all("Bool$as_text((Bool_t[1]){", expr, "}, ", color, ", &Bool$info)");
+ case CStringType: return CORD_all("CString$as_text(stack(", expr, "), ", color, ", &CString$info)");
case BigIntType: case IntType: case ByteType: case NumType: {
CORD name = type_to_cord(t);
- return CORD_asprintf("%r$as_text(stack(%r), %r, &%r$info)", name, expr, color, name);
- }
- case TextType: return CORD_asprintf("Text$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case ListType: return CORD_asprintf("List$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case SetType: return CORD_asprintf("Table$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case TableType: return CORD_asprintf("Table$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case FunctionType: case ClosureType: return CORD_asprintf("Func$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case PointerType: return CORD_asprintf("Pointer$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
- case OptionalType: return CORD_asprintf("Optional$as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
+ return CORD_all(name, "$as_text(stack(", expr, "), ", color, ", &", name, "$info)");
+ }
+ case TextType: return CORD_all("Text$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case ListType: return CORD_all("List$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case SetType: return CORD_all("Table$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case TableType: return CORD_all("Table$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case FunctionType: case ClosureType: return CORD_all("Func$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case PointerType: return CORD_all("Pointer$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
+ case OptionalType: return CORD_all("Optional$as_text(stack(", expr, "), ", color, ", ", compile_type_info(t), ")");
case StructType: case EnumType:
- return CORD_asprintf("generic_as_text(stack(%r), %r, %r)", expr, color, compile_type_info(t));
+ return CORD_all("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));
}
return CORD_EMPTY;
@@ -2083,8 +2089,8 @@ CORD compile_to_type(env_t *env, ast_t *ast, type_t *t)
} else if (ast->tag == Num && t->tag == NumType) {
double n = Match(ast, Num)->n;
switch (Match(t, NumType)->bits) {
- case TYPE_NBITS64: return CORD_asprintf("N64(%.20g)", n);
- case TYPE_NBITS32: return CORD_asprintf("N32(%.10g)", n);
+ case TYPE_NBITS64: return String(hex_double(n));
+ case TYPE_NBITS32: return String(hex_double(n), "f");
default: code_err(ast, "This is not a valid number bit width");
}
} else if (ast->tag == None) {
@@ -2160,7 +2166,7 @@ CORD compile_typed_list(env_t *env, ast_t *ast, type_t *list_type)
env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : env;
if (is_incomplete_type(item_type))
code_err(ast, "This list's type can't be inferred!");
- CORD code = CORD_all("TypedListN(", compile_type(item_type), CORD_asprintf(", %ld", n));
+ CORD code = CORD_all("TypedListN(", compile_type(item_type), ", ", String(n));
for (ast_list_t *item = list->items; item; item = item->next) {
code = CORD_all(code, ", ", compile_to_type(scope, item->ast, item_type));
}
@@ -2207,8 +2213,8 @@ CORD compile_typed_set(env_t *env, ast_t *ast, type_t *set_type)
{ // No comprehension:
CORD code = CORD_all("Set(",
compile_type(item_type), ", ",
- compile_type_info(item_type));
- CORD_appendf(&code, ", %zu", n);
+ compile_type_info(item_type), ", ",
+ String(n));
env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : env;
for (ast_list_t *item = set->items; item; item = item->next) {
code = CORD_all(code, ", ", compile_to_type(scope, item->ast, item_type));
@@ -2274,7 +2280,7 @@ CORD compile_typed_table(env_t *env, ast_t *ast, type_t *table_type)
size_t n = 0;
for (ast_list_t *entry = table->entries; entry; entry = entry->next)
++n;
- CORD_appendf(&code, ", %zu", n);
+ code = CORD_all(code, ", ", String(n));
for (ast_list_t *entry = table->entries; entry; entry = entry->next) {
DeclareMatch(e, entry->ast, TableEntry);
@@ -2317,7 +2323,7 @@ CORD compile_typed_allocation(env_t *env, ast_t *ast, type_t *pointer_type)
type_t *pointed = Match(pointer_type, PointerType)->pointed;
switch (ast->tag) {
case HeapAllocate: {
- return CORD_asprintf("heap(%r)", compile_to_type(env, Match(ast, HeapAllocate)->value, pointed));
+ return CORD_all("heap(", compile_to_type(env, Match(ast, HeapAllocate)->value, pointed), ")");
}
case StackReference: {
ast_t *subject = Match(ast, StackReference)->value;
@@ -2366,13 +2372,13 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
if (target->tag == ByteType) {
if (mpz_cmp_si(i, UINT8_MAX) <= 0 && mpz_cmp_si(i, 0) >= 0)
- return CORD_asprintf("(Byte_t)(%s)", c_literal);
+ return CORD_all("(Byte_t)(", c_literal, ")");
code_err(ast, "This integer cannot fit in a byte");
} else if (target->tag == NumType) {
if (Match(target, NumType)->bits == TYPE_NBITS64) {
- return CORD_asprintf("N64(%s)", c_literal);
+ return CORD_all("N64(", c_literal, ")");
} else {
- return CORD_asprintf("N32(%s)", c_literal);
+ return CORD_all("N32(", c_literal, ")");
}
} else if (target->tag == IntType) {
int64_t target_bits = (int64_t)Match(target, IntType)->bits;
@@ -2381,19 +2387,19 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
if (mpz_cmp_si(i, INT64_MIN) == 0)
return "I64(INT64_MIN)";
if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0)
- return CORD_asprintf("I64(%sL)", c_literal);
+ return CORD_all("I64(", c_literal, "L)");
break;
case TYPE_IBITS32:
if (mpz_cmp_si(i, INT32_MAX) <= 0 && mpz_cmp_si(i, INT32_MIN) >= 0)
- return CORD_asprintf("I32(%s)", c_literal);
+ return CORD_all("I32(", c_literal, ")");
break;
case TYPE_IBITS16:
if (mpz_cmp_si(i, INT16_MAX) <= 0 && mpz_cmp_si(i, INT16_MIN) >= 0)
- return CORD_asprintf("I16(%s)", c_literal);
+ return CORD_all("I16(", c_literal, ")");
break;
case TYPE_IBITS8:
if (mpz_cmp_si(i, INT8_MAX) <= 0 && mpz_cmp_si(i, INT8_MIN) >= 0)
- return CORD_asprintf("I8(%s)", c_literal);
+ return CORD_all("I8(", c_literal, ")");
break;
default: break;
}
@@ -2423,9 +2429,9 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t
if (int_val.small == 0)
code_err(call_arg->value, "Failed to parse this integer");
if (Match(spec_arg->type, NumType)->bits == TYPE_NBITS64)
- value = CORD_asprintf("N64(%.20g)", Num$from_int(int_val, false));
+ value = String(hex_double(Num$from_int(int_val, false)));
else
- value = CORD_asprintf("N32(%.10g)", (double)Num32$from_int(int_val, false));
+ value = String(hex_double((double)Num32$from_int(int_val, false)), "f");
} else {
env_t *arg_env = with_enum_scope(env, spec_arg->type);
value = compile_maybe_incref(arg_env, call_arg->value, spec_arg->type);
@@ -2450,9 +2456,9 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t
if (int_val.small == 0)
code_err(call_arg->value, "Failed to parse this integer");
if (Match(spec_arg->type, NumType)->bits == TYPE_NBITS64)
- value = CORD_asprintf("N64(%.20g)", Num$from_int(int_val, false));
+ value = String(hex_double(Num$from_int(int_val, false)));
else
- value = CORD_asprintf("N32(%.10g)", (double)Num32$from_int(int_val, false));
+ value = String(hex_double((double)Num32$from_int(int_val, false)), "f");
} else {
env_t *arg_env = with_enum_scope(env, spec_arg->type);
value = compile_maybe_incref(arg_env, call_arg->value, spec_arg->type);
@@ -2502,7 +2508,7 @@ CORD compile_string_literal(CORD literal)
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
- char c = CORD_pos_fetch(i);
+ uint8_t c = (uint8_t)CORD_pos_fetch(i);
switch (c) {
case '\\': code = CORD_cat(code, "\\\\"); break;
case '"': code = CORD_cat(code, "\\\""); break;
@@ -2514,9 +2520,9 @@ CORD compile_string_literal(CORD literal)
case '\v': code = CORD_cat(code, "\\v"); break;
default: {
if (isprint(c))
- code = CORD_cat_char(code, c);
+ code = CORD_cat_char(code, (char)c);
else
- CORD_sprintf(&code, "%r\\x%02X\"\"", code, (uint8_t)c);
+ code = CORD_all(code, "\\x", String(hex((uint64_t)c, .no_prefix=true, .uppercase=true, .digits=2)), "\"\"");
break;
}
}
@@ -2717,15 +2723,15 @@ CORD compile(env_t *env, ast_t *ast)
mpz_t i;
mpz_init_set_int(i, int_val);
if (mpz_cmpabs_ui(i, BIGGEST_SMALL_INT) <= 0) {
- return CORD_asprintf("I_small(%s)", str);
+ return CORD_all("I_small(", str, ")");
} else if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0) {
- return CORD_asprintf("Int$from_int64(%s)", str);
+ return CORD_all("Int$from_int64(", str, ")");
} else {
- return CORD_asprintf("Int$from_str(\"%s\")", str);
+ return CORD_all("Int$from_str(\"", str, "\")");
}
}
case Num: {
- return CORD_asprintf("N64(%.20g)", Match(ast, Num)->n);
+ return String(hex_double(Match(ast, Num)->n));
}
case Not: {
ast_t *value = Match(ast, Not)->value;
@@ -2783,10 +2789,10 @@ CORD compile(env_t *env, ast_t *ast)
CORD value_code = compile(env, value);
return CORD_all("({ ", compile_declaration(t, "opt"), " = ", value_code, "; ",
"if unlikely (", check_none(t, "opt"), ")\n",
- CORD_asprintf("fail_source(%r, %ld, %ld, \"This was expected to be a value, but it's none\");\n",
- CORD_quoted(ast->file->filename),
- (long)(value->start - value->file->text),
- (long)(value->end - value->file->text)),
+ "fail_source(", CORD_quoted(ast->file->filename), ", ",
+ String((long)(value->start - value->file->text)), ", ",
+ String((long)(value->end - value->file->text)), ", ",
+ "\"This was expected to be a value, but it's none\");\n",
optional_into_nonnone(t, "opt"), "; })");
}
case Power: case Multiply: case Divide: case Mod: case Mod1: case Plus: case Minus: case Concat:
@@ -3032,13 +3038,13 @@ CORD compile(env_t *env, ast_t *ast)
}
case Lambda: {
DeclareMatch(lambda, ast, Lambda);
- CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env, env->namespace), lambda->id);
+ CORD name = CORD_all(namespace_prefix(env, env->namespace), "lambda$", String(lambda->id));
env->code->function_naming = CORD_all(
env->code->function_naming,
- CORD_asprintf("register_function(%r, Text(\"%s.tm\"), %ld, Text(%r));\n",
- name, file_base_name(ast->file->filename), get_line_number(ast->file, ast->start),
- CORD_quoted(type_to_cord(get_type(env, ast)))));
+ "register_function(", name, ", Text(\"", file_base_name(ast->file->filename), ".tm\"), ",
+ String(get_line_number(ast->file, ast->start)),
+ ", Text(", CORD_quoted(type_to_cord(get_type(env, ast))), "));\n");
env_t *body_scope = fresh_scope(env);
body_scope->deferred = NULL;
@@ -3798,10 +3804,10 @@ CORD compile(env_t *env, ast_t *ast)
if (streq(field->name, f->field)) {
if (fielded_t->tag == PointerType) {
CORD fielded = compile_to_pointer_depth(env, f->fielded, 1, false);
- return CORD_asprintf("(%r)->%s", fielded, f->field);
+ return CORD_all("(", fielded, ")->", f->field);
} else {
CORD fielded = compile(env, f->fielded);
- return CORD_asprintf("(%r).%s", fielded, f->field);
+ return CORD_all("(", fielded, ").", f->field);
}
}
}
@@ -3894,8 +3900,8 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("List_get_unchecked(", compile_type(item_type), ", ", list, ", ", index_code, ")");
else
return CORD_all("List_get(", compile_type(item_type), ", ", list, ", ", index_code, ", ",
- CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ",
- CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)),
+ String((int64_t)(indexing->index->start - f->text)), ", ",
+ String((int64_t)(indexing->index->end - f->text)),
")");
} else if (container_t->tag == TableType) {
DeclareMatch(table_type, container_t, TableType);
@@ -3984,19 +3990,18 @@ CORD compile_type_info(type_t *t)
case PointerType: {
DeclareMatch(ptr, t, PointerType);
CORD sigil = ptr->is_stack ? "&" : "@";
- return CORD_asprintf("Pointer$info(%r, %r)",
- CORD_quoted(sigil),
- compile_type_info(ptr->pointed));
+ return CORD_all("Pointer$info(", CORD_quoted(sigil), ", ", compile_type_info(ptr->pointed), ")");
}
case FunctionType: {
- return CORD_asprintf("Function$info(%r)", CORD_quoted(type_to_cord(t)));
+ return CORD_all("Function$info(", CORD_quoted(type_to_cord(t)), ")");
}
case ClosureType: {
- return CORD_asprintf("Closure$info(%r)", CORD_quoted(type_to_cord(t)));
+ return CORD_all("Closure$info(", CORD_quoted(type_to_cord(t)), ")");
}
case OptionalType: {
type_t *non_optional = Match(t, OptionalType)->type;
- return CORD_asprintf("Optional$info(sizeof(%r), __alignof__(%r), %r)", compile_type(non_optional), compile_type(non_optional), compile_type_info(non_optional));
+ return CORD_all("Optional$info(sizeof(", compile_type(non_optional),
+ "), __alignof__(", compile_type(non_optional), "), ", compile_type_info(non_optional), ")");
}
case TypeInfoType: return CORD_all("Type$info(", CORD_quoted(type_to_cord(Match(t, TypeInfoType)->type)), ")");
case MemoryType: return "&Memory$info";
@@ -4226,7 +4231,7 @@ CORD compile_function(env_t *env, CORD name_code, ast_t *ast, CORD *staticdefs)
if (cache->tag == Int && !cache_size.is_none && cache_size.value > 0) {
// FIXME: this currently just deletes the first entry, but this should be more like a
// least-recently-used cache eviction policy or least-frequently-used
- pop_code = CORD_all("if (cache.entries.length > ", CORD_asprintf("%ld", cache_size.value),
+ pop_code = CORD_all("if (cache.entries.length > ", String(cache_size.value),
") Table$remove(&cache, cache.entries.data + cache.entries.stride*0, table_type);\n");
}
@@ -4255,10 +4260,10 @@ CORD compile_function(env_t *env, CORD name_code, ast_t *ast, CORD *staticdefs)
int64_t num_fields = used_names.entries.length;
const char *metamethods = is_packed_data(t) ? "PackedData$metamethods" : "Struct$metamethods";
- CORD args_typeinfo = CORD_asprintf("((TypeInfo_t[1]){{.size=sizeof(args), .align=__alignof__(args), .metamethods=%s, "
- ".tag=StructInfo, .StructInfo.name=\"FunctionArguments\", "
- ".StructInfo.num_fields=%ld, .StructInfo.fields=(NamedType_t[%ld]){",
- metamethods, num_fields, num_fields);
+ CORD args_typeinfo = CORD_all("((TypeInfo_t[1]){{.size=sizeof(args), .align=__alignof__(args), .metamethods=", metamethods,
+ ", .tag=StructInfo, .StructInfo.name=\"FunctionArguments\", "
+ ".StructInfo.num_fields=", String(num_fields),
+ ", .StructInfo.fields=(NamedType_t[", String(num_fields), "]){");
CORD args_type = "struct { ";
for (arg_t *f = fields; f; f = f->next) {
args_typeinfo = CORD_all(args_typeinfo, "{\"", f->name, "\", ", compile_type_info(f->type), "}");
@@ -4303,8 +4308,8 @@ CORD compile_function(env_t *env, CORD name_code, ast_t *ast, CORD *staticdefs)
if (!is_inline) {
env->code->function_naming = CORD_all(
env->code->function_naming,
- CORD_asprintf("register_function(%r, Text(\"%s.tm\"), %ld, Text(%r));\n",
- name_code, file_base_name(ast->file->filename), get_line_number(ast->file, ast->start), CORD_quoted(text)));
+ "register_function(", name_code, ", Text(\"", file_base_name(ast->file->filename), ".tm\"), ",
+ String(get_line_number(ast->file, ast->start)), ", Text(", CORD_quoted(text), "));\n");
}
return definition;
}
@@ -4354,7 +4359,7 @@ CORD compile_top_level_code(env_t *env, ast_t *ast)
const char *name = get_type_name(Match(type, FunctionType)->ret);
if (!name)
code_err(ast, "Conversions are only supported for text, struct, and enum types, not ", type_to_str(Match(type, FunctionType)->ret));
- CORD name_code = CORD_asprintf("%r%s$%ld", namespace_prefix(env, env->namespace), name, get_line_number(ast->file, ast->start));
+ CORD name_code = CORD_all(namespace_prefix(env, env->namespace), name, "$", String(get_line_number(ast->file, ast->start)));
return compile_function(env, name_code, ast, &env->code->staticdefs);
}
case StructDef: {
@@ -4374,9 +4379,9 @@ CORD compile_top_level_code(env_t *env, ast_t *ast)
}
case LangDef: {
DeclareMatch(def, ast, LangDef);
- CORD code = CORD_asprintf("public const TypeInfo_t %r%s$$info = {%zu, %zu, .metamethods=Text$metamethods, .tag=TextInfo, .TextInfo={%r}};\n",
- namespace_prefix(env, env->namespace), def->name, sizeof(Text_t), __alignof__(Text_t),
- CORD_quoted(def->name));
+ CORD code = CORD_all("public const TypeInfo_t ", namespace_prefix(env, env->namespace),
+ def->name, "$$info = {", String(sizeof(Text_t)), ", ", String(__alignof__(Text_t)),
+ ", .metamethods=Text$metamethods, .tag=TextInfo, .TextInfo={", CORD_quoted(def->name), "}};\n");
env_t *ns_env = namespace_env(env, def->name);
return CORD_all(code, def->namespace ? compile_top_level_code(ns_env, def->namespace) : CORD_EMPTY);
}
@@ -4637,7 +4642,7 @@ CORD compile_statement_namespace_header(env_t *env, Path_t header_path, ast_t *a
ret_type_code = CORD_all("__attribute__((noreturn)) _Noreturn ", ret_type_code);
CORD name = CORD_all(namespace_prefix(env, env->namespace), decl_name);
if (env->namespace && env->namespace->parent && env->namespace->name && streq(decl_name, env->namespace->name))
- name = CORD_asprintf("%r%ld", namespace_prefix(env, env->namespace), get_line_number(ast->file, ast->start));
+ name = CORD_all(namespace_prefix(env, env->namespace), String(get_line_number(ast->file, ast->start)));
return CORD_all(ret_type_code, " ", name, arg_signature, ";\n");
}
case ConvertDef: {
@@ -4657,7 +4662,7 @@ CORD compile_statement_namespace_header(env_t *env, Path_t header_path, ast_t *a
if (!name)
code_err(ast, "Conversions are only supported for text, struct, and enum types, not ", type_to_str(ret_t));
name = CORD_all(namespace_prefix(env, env->namespace), name);
- CORD name_code = CORD_asprintf("%r$%ld", name, get_line_number(ast->file, ast->start));
+ CORD name_code = CORD_all(name, "$", String(get_line_number(ast->file, ast->start)));
return CORD_all(ret_type_code, " ", name_code, arg_signature, ";\n");
}
default: return CORD_EMPTY;
diff --git a/src/cordhelpers.c b/src/cordhelpers.c
index 1bff9e9c..353a52d9 100644
--- a/src/cordhelpers.c
+++ b/src/cordhelpers.c
@@ -1,21 +1,12 @@
// Some helper functions for the GC Cord library
#include <gc/cord.h>
-#include <stdarg.h>
+#include <stdint.h>
+#include "cordhelpers.h"
+#include "stdlib/print.h"
#include "stdlib/util.h"
-__attribute__((format(printf, 1, 2)))
-public CORD CORD_asprintf(CORD fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- CORD c = NULL;
- CORD_vsprintf(&c, fmt, args);
- va_end(args);
- return c;
-}
-
public CORD CORD_quoted(CORD str)
{
CORD quoted = "\"";
@@ -42,7 +33,7 @@ public CORD CORD_quoted(CORD str)
case '\\': quoted = CORD_cat(quoted, "\\\\"); break;
case '\x00' ... '\x06': case '\x0E' ... '\x1A':
case '\x1C' ... '\x1F': case '\x7F' ... '\x7F':
- CORD_sprintf(&quoted, "%r\\x%02X", quoted, c);
+ quoted = CORD_all(quoted, "\\x", String(hex((uint64_t)c, .no_prefix=true, .uppercase=true, .digits=2)));
break;
default: quoted = CORD_cat_char(quoted, c); break;
}
diff --git a/src/cordhelpers.h b/src/cordhelpers.h
index a1638869..b519a443 100644
--- a/src/cordhelpers.h
+++ b/src/cordhelpers.h
@@ -3,11 +3,8 @@
#include <gc/cord.h>
-#define CORD_appendf(cord, fmt, ...) CORD_sprintf(cord, "%r" fmt, *(cord), __VA_ARGS__)
#define CORD_all(...) CORD_catn(sizeof((CORD[]){__VA_ARGS__})/sizeof(CORD), __VA_ARGS__)
-__attribute__((format(printf, 1, 2)))
-CORD CORD_asprintf(CORD fmt, ...);
CORD CORD_quoted(CORD str);
CORD CORD_replace(CORD c, CORD to_replace, CORD replacement);
diff --git a/src/enums.c b/src/enums.c
index ac21bdda..36b5f97f 100644
--- a/src/enums.c
+++ b/src/enums.c
@@ -36,9 +36,10 @@ CORD compile_enum_typeinfo(env_t *env, ast_t *ast)
type_t *t = Table$str_get(*env->types, def->name);
const char *metamethods = is_packed_data(t) ? "PackedDataEnum$metamethods" : "Enum$metamethods";
- CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r$$info = {%zu, %zu, .metamethods=%s, {.tag=EnumInfo, .EnumInfo={.name=\"%s\", "
- ".num_tags=%d, .tags=(NamedType_t[]){",
- full_name, type_size(t), type_align(t), metamethods, def->name, num_tags);
+ CORD typeinfo = CORD_all("public const TypeInfo_t ", full_name, "$$info = {",
+ String(type_size(t)), "u, ", String(type_align(t)), "u, .metamethods=", metamethods,
+ ", {.tag=EnumInfo, .EnumInfo={.name=\"", def->name, "\", "
+ ".num_tags=", String(num_tags), ", .tags=(NamedType_t[]){");
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
const char *tag_type_name = String(def->name, "$", tag->name);
diff --git a/src/stdlib/fpconv.h b/src/stdlib/fpconv.h
index 360c1f96..1d3dd813 100644
--- a/src/stdlib/fpconv.h
+++ b/src/stdlib/fpconv.h
@@ -24,7 +24,7 @@
* int str_len = fpconv_dtoa(d, buf);
*
* buf[str_len] = '\0';
- * printf("%s", buf);
+ * puts(buf);
* }
*
*/
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index 86cdeb56..7250e2a2 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -32,11 +32,10 @@ static inline Text_t _int64_to_text(int64_t n)
char *p = &buf[19];
bool negative = n < 0;
- if (n == 0)
- *(p--) = '0';
-
- for (; n > 0; n /= 10)
+ do {
*(p--) = '0' + (n % 10);
+ n /= 10;
+ } while (n > 0);
if (negative)
*(p--) = '-';
diff --git a/src/stdlib/print.c b/src/stdlib/print.c
index df10a54f..3270c765 100644
--- a/src/stdlib/print.c
+++ b/src/stdlib/print.c
@@ -14,11 +14,10 @@ public int _print_int(FILE *f, int64_t n)
char *p = &buf[19];
bool negative = n < 0;
- if (n == 0)
- *(p--) = '0';
-
- for (; n > 0; n /= 10)
+ do {
*(p--) = '0' + (n % 10);
+ n /= 10;
+ } while (n > 0);
if (negative)
*(p--) = '-';
@@ -31,11 +30,10 @@ public int _print_uint(FILE *f, uint64_t n)
char buf[21] = {[20]=0}; // Big enough for UINT64_MAX + '\0'
char *p = &buf[19];
- if (n == 0)
- *(p--) = '0';
-
- for (; n > 0; n /= 10)
+ do {
*(p--) = '0' + (n % 10);
+ n /= 10;
+ } while (n > 0);
return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
}
@@ -54,15 +52,16 @@ public int _print_hex(FILE *f, hex_format_t hex)
}
char buf[9] = {[8]='\0'}; // Enough space for FFFFFFFF + '\0'
char *p = &buf[7];
- for (uint64_t n = hex.n; n > 0; n /= 16) {
- uint8_t digit = n % 16;
+ do {
+ uint8_t digit = hex.n % 16;
if (digit <= 9)
*(p--) = '0' + digit;
else if (hex.uppercase)
*(p--) = 'A' + digit - 10;
else
*(p--) = 'a' + digit - 10;
- }
+ hex.n /= 16;
+ } while (hex.n > 0);
printed += (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[7] - p), f);
return printed;
}
@@ -72,18 +71,17 @@ public int _print_oct(FILE *f, oct_format_t oct)
int printed = 0;
if (!oct.no_prefix) printed += fputs("0o", f);
if (oct.digits > 0) {
- for (uint64_t n = oct.n; n > 0 && oct.digits > 0; n /= 8) {
+ for (uint64_t n = oct.n; n > 0 && oct.digits > 0; n /= 8)
oct.digits -= 1;
- }
- for (; oct.digits > 0; oct.digits -= 1) {
+ for (; oct.digits > 0; oct.digits -= 1)
printed += fputc('0', f);
- }
}
char buf[12] = {[11]='\0'}; // Enough space for octal UINT64_MAX + '\0'
char *p = &buf[10];
- for (uint64_t n = oct.n; n > 0; n /= 8) {
- *(p--) = '0' + (n % 8);
- }
+ do {
+ *(p--) = '0' + (oct.n % 8);
+ oct.n /= 8;
+ } while (oct.n > 0);
printed += (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[10] - p), f);
return printed;
}
@@ -95,6 +93,74 @@ public int _print_double(FILE *f, double n)
return (int)fwrite(buf, sizeof(char), (size_t)len, f);
}
+public int _print_hex_double(FILE *f, hex_double_t hex)
+{
+ if (hex.d != hex.d)
+ return fputs("NAN", f);
+ else if (hex.d == 1.0/0.0)
+ return fputs("INF", f);
+ else if (hex.d == -1.0/0.0)
+ return fputs("-INF", f);
+ else if (hex.d == 0.0)
+ return fputs("0.0", f);
+
+ union { double d; uint64_t u; } bits = { .d = hex.d };
+
+ int sign = (bits.u >> 63) & 1ull;
+ int exp = (int)((bits.u >> 52) & 0x7FF) - 1023ull;
+ uint64_t frac = bits.u & 0xFFFFFFFFFFFFFull;
+
+ char buf[25];
+ char *p = buf;
+
+ if (sign) *p++ = '-';
+ *p++ = '0';
+ *p++ = 'x';
+
+ uint64_t mantissa = (1ull << 52) | frac; // implicit 1
+ int mantissa_shift = 52;
+
+ while ((mantissa & 0xF) == 0 && mantissa_shift > 0) {
+ mantissa >>= 4;
+ mantissa_shift -= 4;
+ }
+
+ uint64_t int_part = mantissa >> mantissa_shift;
+ *p++ = "0123456789abcdef"[int_part];
+
+ *p++ = '.';
+
+ while (mantissa_shift > 0) {
+ mantissa_shift -= 4;
+ uint64_t digit = (mantissa >> mantissa_shift) & 0xF;
+ *p++ = "0123456789abcdef"[digit];
+ }
+
+ *p++ = 'p';
+
+ if (exp >= 0) {
+ *p++ = '+';
+ } else {
+ *p++ = '-';
+ exp = -exp;
+ }
+
+ char expbuf[6];
+ int ei = 5;
+ expbuf[ei--] = '\0';
+ do {
+ expbuf[ei--] = '0' + (exp % 10);
+ exp /= 10;
+ } while (exp && ei >= 0);
+
+ ei++;
+ while (expbuf[ei])
+ *p++ = expbuf[ei++];
+
+ *p = '\0';
+ return fwrite(buf, sizeof(char), (size_t)(p - buf), f);
+}
+
public int _print_char(FILE *f, char c)
{
#define ESC(e) "'\\" e "'"
diff --git a/src/stdlib/print.h b/src/stdlib/print.h
index 454ef6b8..9bd89aea 100644
--- a/src/stdlib/print.h
+++ b/src/stdlib/print.h
@@ -43,6 +43,11 @@ typedef struct {
#define hex(x, ...) ((hex_format_t){.n=x, __VA_ARGS__})
typedef struct {
+ double d;
+} hex_double_t;
+#define hex_double(x, ...) ((hex_double_t){.d=x, __VA_ARGS__})
+
+typedef struct {
uint64_t n;
bool no_prefix;
int digits;
@@ -76,6 +81,7 @@ int _print_int(FILE *f, int64_t x);
int _print_uint(FILE *f, uint64_t x);
int _print_double(FILE *f, double x);
int _print_hex(FILE *f, hex_format_t hex);
+int _print_hex_double(FILE *f, hex_double_t hex);
int _print_oct(FILE *f, oct_format_t oct);
PRINT_FN _print_float(FILE *f, float x) { return _print_double(f, (double)x); }
PRINT_FN _print_pointer(FILE *f, void *p) { return _print_hex(f, hex((uint64_t)p)); }
@@ -111,6 +117,7 @@ extern int Int$print(FILE *f, Int_t i);
float: _print_float, \
double: _print_double, \
hex_format_t: _print_hex, \
+ hex_double_t: _print_hex_double, \
oct_format_t: _print_oct, \
quoted_t: _print_quoted, \
string_slice_t: _print_string_slice, \
diff --git a/src/structs.c b/src/structs.c
index 401fcb7a..0735d474 100644
--- a/src/structs.c
+++ b/src/structs.c
@@ -25,14 +25,15 @@ CORD compile_struct_typeinfo(env_t *env, type_t *t, const char *name, arg_ast_t
short_name = strrchr(short_name, '$') + 1;
const char *metamethods = is_packed_data(t) ? "PackedData$metamethods" : "Struct$metamethods";
- CORD typeinfo = CORD_asprintf("public const TypeInfo_t %r = {.size=sizeof(%r), .align=__alignof__(%r), .metamethods=%s, "
- ".tag=StructInfo, .StructInfo.name=\"%s\"%s%s, "
- ".StructInfo.num_fields=%ld",
- typeinfo_name, type_code, type_code, metamethods, short_name, is_secret ? ", .StructInfo.is_secret=true" : "",
- is_opaque ? ", .StructInfo.is_opaque=true" : "",
- num_fields);
+ CORD typeinfo = CORD_all("public const TypeInfo_t ", typeinfo_name,
+ " = {.size=sizeof(", type_code, "), .align=__alignof__(", type_code, "), "
+ ".metamethods=", metamethods, ", "
+ ".tag=StructInfo, .StructInfo.name=\"", short_name, "\"",
+ is_secret ? ", .StructInfo.is_secret=true" : CORD_EMPTY,
+ is_opaque ? ", .StructInfo.is_opaque=true" : CORD_EMPTY,
+ ", .StructInfo.num_fields=", String(num_fields));
if (fields) {
- typeinfo = CORD_asprintf("%r, .StructInfo.fields=(NamedType_t[%d]){", typeinfo, num_fields);
+ typeinfo = CORD_all(typeinfo, ", .StructInfo.fields=(NamedType_t[", String(num_fields), "]){");
for (arg_ast_t *f = fields; f; f = f->next) {
type_t *field_type = get_arg_ast_type(env, f);
typeinfo = CORD_all(typeinfo, "{\"", f->name, "\", ", compile_type_info(field_type), "}");
@@ -64,7 +65,7 @@ CORD compile_struct_header(env_t *env, ast_t *ast)
CORD struct_code = def->external ? CORD_EMPTY : CORD_all(type_code, " {\n", fields, "};\n");
type_t *t = Table$str_get(*env->types, def->name);
- CORD unpadded_size = def->opaque ? CORD_all("sizeof(", type_code, ")") : CORD_asprintf("%zu", unpadded_struct_size(t));
+ CORD unpadded_size = def->opaque ? CORD_all("sizeof(", type_code, ")") : String(unpadded_struct_size(t));
CORD typeinfo_code = CORD_all("extern const TypeInfo_t ", typeinfo_name, ";\n");
CORD optional_code = CORD_EMPTY;
if (!def->opaque) {
diff --git a/src/tomo.c b/src/tomo.c
index 8562ebaa..ec486101 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -68,7 +68,7 @@ static OptionalBool_t verbose = false,
static OptionalText_t
show_codegen = NONE_TEXT,
- cflags = Text("-Werror -fdollars-in-identifiers -std=c2x -Wno-trigraphs -Wno-parentheses-equality "
+ cflags = Text("-Werror -fdollars-in-identifiers -std=c2x -Wno-trigraphs "
" -ffunction-sections -fdata-sections"
" -fno-signed-zeros -fno-finite-math-only "
" -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -fPIC -ggdb"
@@ -211,6 +211,11 @@ int main(int argc, char *argv[])
" -fno-signaling-nans -fno-trapping-math"));
}
+ bool is_clang = (system(String(cc, " -v 2>&1 | grep -q 'clang version'")) == 0);
+ if (is_clang) {
+ cflags = Texts(cflags, Text(" -Wno-parentheses-equality"));
+ }
+
#ifdef __APPLE__
cflags = Texts(cflags, Text(" -I/opt/homebrew/include"));
ldflags = Texts(ldflags, Text(" -L/opt/homebrew/lib -Wl,-rpath,/opt/homebrew/lib"));
@@ -432,7 +437,7 @@ static void _compile_file_header_for_library(env_t *env, Path_t header_path, Pat
visit_topologically(
Match(file_ast, Block)->statements, (Closure_t){.fn=(void*)_compile_statement_header_for_library, &info});
- CORD_fprintf(output, "void %r$initialize(void);\n", namespace_prefix(module_env, module_env->namespace));
+ CORD_put(CORD_all("void ", namespace_prefix(module_env, module_env->namespace), "$initialize(void);\n"), output);
}
void build_library(Path_t lib_dir)
@@ -445,7 +450,7 @@ void build_library(Path_t lib_dir)
List_t tm_files = Path$glob(Path$with_component(lib_dir, Text("[!._0-9]*.tm")));
env_t *env = fresh_scope(global_env(source_mapping));
List_t object_files = {},
- extra_ldlibs = {};
+ extra_ldlibs = {};
compile_files(env, tm_files, &object_files, &extra_ldlibs);
diff --git a/src/typecheck.c b/src/typecheck.c
index f255f348..6c483511 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -340,8 +340,8 @@ void bind_statement(env_t *env, ast_t *statement)
if (!name)
code_err(statement, "Conversions are only supported for text, struct, and enum types, not ", type_to_str(ret_t));
- CORD code = CORD_asprintf("%r%r$%ld", namespace_prefix(env, env->namespace), name,
- get_line_number(statement->file, statement->start));
+ CORD code = CORD_all(namespace_prefix(env, env->namespace), name, "$",
+ String(get_line_number(statement->file, statement->start)));
binding_t binding = {.type=type, .code=code};
env_t *type_ns = get_namespace_by_type(env, ret_t);
List$insert(&type_ns->namespace->constructors, &binding, I(0), sizeof(binding));
diff --git a/src/types.c b/src/types.c
index dd76258d..e1ada1f8 100644
--- a/src/types.c
+++ b/src/types.c
@@ -9,6 +9,7 @@
#include "cordhelpers.h"
#include "environment.h"
#include "stdlib/integers.h"
+#include "stdlib/print.h"
#include "stdlib/tables.h"
#include "stdlib/util.h"
#include "types.h"
@@ -31,11 +32,11 @@ CORD type_to_cord(type_t *t) {
case CStringType: return "CString";
case TextType: return Match(t, TextType)->lang ? Match(t, TextType)->lang : "Text";
case BigIntType: return "Int";
- case IntType: return CORD_asprintf("Int%d", Match(t, IntType)->bits);
+ case IntType: return String("Int", Match(t, IntType)->bits);
case NumType: return Match(t, NumType)->bits == TYPE_NBITS32 ? "Num32" : "Num";
case ListType: {
DeclareMatch(list, t, ListType);
- return CORD_asprintf("[%r]", type_to_cord(list->item_type));
+ return CORD_all("[", type_to_cord(list->item_type), "]");
}
case TableType: {
DeclareMatch(table, t, TableType);
@@ -43,7 +44,7 @@ CORD type_to_cord(type_t *t) {
}
case SetType: {
DeclareMatch(set, t, SetType);
- return CORD_asprintf("{%r}", type_to_cord(set->item_type));
+ return CORD_all("{", type_to_cord(set->item_type), "}");
}
case ClosureType: {
return type_to_cord(Match(t, ClosureType)->fn);
@@ -88,7 +89,7 @@ CORD type_to_cord(type_t *t) {
}
default: {
raise(SIGABRT);
- return CORD_asprintf("Unknown type: %d", t->tag);
+ return String("Unknown type: ", t->tag);
}
}
}