aboutsummaryrefslogtreecommitdiff
path: root/src/compile
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2026-01-11 23:03:00 -0500
committerBruce Hill <bruce@bruce-hill.com>2026-01-11 23:03:00 -0500
commit6894dc69374efcc23619e93b040a4224588054cd (patch)
tree045adf796e3291349b02d695b24e390929c8446e /src/compile
parentb97ea6b6ac3498b21321e1f93ccc1a2dd145e9d7 (diff)
Refactor some AST logic to keep Ints/Reals as "Integer" and "Number" AST
nodes and use improved parsing logic from Int/Real
Diffstat (limited to 'src/compile')
-rw-r--r--src/compile/functions.c13
-rw-r--r--src/compile/integers.c38
-rw-r--r--src/compile/lists.c12
-rw-r--r--src/compile/loops.c6
-rw-r--r--src/compile/promotions.c6
5 files changed, 45 insertions, 30 deletions
diff --git a/src/compile/functions.c b/src/compile/functions.c
index 2784bedd..2f52cf18 100644
--- a/src/compile/functions.c
+++ b/src/compile/functions.c
@@ -7,7 +7,6 @@
#include "../stdlib/datatypes.h"
#include "../stdlib/floats.h"
#include "../stdlib/integers.h"
-#include "../stdlib/optionals.h"
#include "../stdlib/tables.h"
#include "../stdlib/text.h"
#include "../stdlib/util.h"
@@ -82,8 +81,7 @@ Text_t compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_
if (spec_arg->type->tag == IntType && call_arg->value->tag == Integer) {
value = compile_int_to_type(env, call_arg->value, spec_arg->type);
} else if (spec_arg->type->tag == FloatType && call_arg->value->tag == Integer) {
- OptionalInt_t int_val = Int$from_str(Match(call_arg->value, Integer)->str);
- if (int_val.small == 0) code_err(call_arg->value, "Failed to parse this integer");
+ Int_t int_val = Match(call_arg->value, Integer)->i;
if (Match(spec_arg->type, FloatType)->bits == TYPE_NBITS64)
value = Text$from_str(String(hex_double(Float64$from_int(int_val, false))));
else value = Text$from_str(String(hex_double((double)Float32$from_int(int_val, false)), "f"));
@@ -106,8 +104,7 @@ Text_t compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_
if (spec_arg->type->tag == IntType && call_arg->value->tag == Integer) {
value = compile_int_to_type(env, call_arg->value, spec_arg->type);
} else if (spec_arg->type->tag == FloatType && call_arg->value->tag == Integer) {
- OptionalInt_t int_val = Int$from_str(Match(call_arg->value, Integer)->str);
- if (int_val.small == 0) code_err(call_arg->value, "Failed to parse this integer");
+ Int_t int_val = Match(call_arg->value, Integer)->i;
if (Match(spec_arg->type, FloatType)->bits == TYPE_NBITS64)
value = Text$from_str(String(hex_double(Float64$from_int(int_val, false))));
else value = Text$from_str(String(hex_double((double)Float32$from_int(int_val, false)), "f"));
@@ -829,13 +826,13 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
definition = Texts(definition, wrapper);
} else if (cache && cache->tag == Integer) {
assert(args);
- OptionalInt64_t cache_size = Int64$parse(Text$from_str(Match(cache, Integer)->str), NONE_INT, NULL);
+ int64_t cache_size = Int64$from_int(Match(cache, Integer)->i, false);
Text_t pop_code = EMPTY_TEXT;
- if (cache->tag == Integer && cache_size.has_value && cache_size.value > 0) {
+ if (cache->tag == Integer && cache_size > 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 = Texts("if (cache.entries.length > ", cache_size.value,
+ pop_code = Texts("if (cache.entries.length > ", cache_size,
") Table$remove(&cache, cache.entries.data + "
"cache.entries.stride*0, table_type);\n");
}
diff --git a/src/compile/integers.c b/src/compile/integers.c
index ea316218..ace98aa8 100644
--- a/src/compile/integers.c
+++ b/src/compile/integers.c
@@ -30,17 +30,17 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) {
", .has_value=true})");
}
- const char *literal = Match(ast, Integer)->str;
- OptionalInt_t int_val = Int$from_str(literal);
- if (int_val.small == 0) code_err(ast, "Failed to parse this integer");
+ OptionalInt_t int_val = Match(ast, Integer)->i;
+
+ Text_t source = ast_source(ast);
mpz_t i;
mpz_init_set_int(i, int_val);
char *c_literal;
- if (strncmp(literal, "0x", 2) == 0 || strncmp(literal, "0X", 2) == 0 || strncmp(literal, "0b", 2) == 0) {
+ if (Text$has(source, Text("0x")) || Text$has(source, Text("0X")) || Text$has(source, Text("0b"))) {
gmp_asprintf(&c_literal, "0x%ZX", i);
- } else if (strncmp(literal, "0o", 2) == 0) {
+ } else if (Text$has(source, Text("0o"))) {
gmp_asprintf(&c_literal, "%#Zo", i);
} else {
gmp_asprintf(&c_literal, "%#Zd", i);
@@ -82,16 +82,32 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) {
public
Text_t compile_int(ast_t *ast) {
- const char *str = Match(ast, Integer)->str;
- OptionalInt_t int_val = Int$from_str(str);
- if (int_val.small == 0) code_err(ast, "Failed to parse this integer");
+ Int_t int_val = Match(ast, Integer)->i;
mpz_t i;
mpz_init_set_int(i, int_val);
+
+ OptionalText_t source = ast_source(ast);
+ char *c_literal;
+ if (Text$has(source, Text("0x")) || Text$has(source, Text("0X")) || Text$has(source, Text("0b"))) {
+ gmp_asprintf(&c_literal, "0x%ZX", i);
+ } else if (Text$has(source, Text("0o"))) {
+ gmp_asprintf(&c_literal, "%#Zo", i);
+ } else {
+ gmp_asprintf(&c_literal, "%#Zd", i);
+ }
+
+ // TODO: preserve base
if (mpz_cmpabs_ui(i, BIGGEST_SMALL_INT) <= 0) {
- return Texts("I_small(", str, ")");
+ return Texts("I_small(", c_literal, ")");
} else if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0) {
- return Texts("Int$from_int64(", str, ")");
+ return Texts("Int$from_int64(", c_literal, ")");
+ } else if (source.tag == TEXT_NONE) {
+ return Texts("Int$from_str(\"", int_val, "\")");
} else {
- return Texts("Int$from_str(\"", str, "\")");
+ source = Text$replace(source, Text("("), Text(""));
+ source = Text$replace(source, Text(")"), Text(""));
+ source = Text$replace(source, Text(" "), Text(""));
+ source = Text$replace(source, Text("_"), Text(""));
+ return Texts("Int$from_str(\"", source, "\")");
}
}
diff --git a/src/compile/lists.c b/src/compile/lists.c
index 9c969d2c..da125549 100644
--- a/src/compile/lists.c
+++ b/src/compile/lists.c
@@ -83,28 +83,28 @@ Text_t compile_list_method_call(env_t *env, ast_t *ast) {
EXPECT_POINTER();
arg_t *arg_spec =
new (arg_t, .name = "item", .type = item_t,
- .next = new (arg_t, .name = "at", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "0")));
+ .next = new (arg_t, .name = "at", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(0))));
return Texts("List$insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
padded_item_size, ")");
} else if (streq(call->name, "insert_all")) {
EXPECT_POINTER();
arg_t *arg_spec =
new (arg_t, .name = "items", .type = self_value_t,
- .next = new (arg_t, .name = "at", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "0")));
+ .next = new (arg_t, .name = "at", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(0))));
return Texts("List$insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
padded_item_size, ")");
} else if (streq(call->name, "remove_at")) {
EXPECT_POINTER();
arg_t *arg_spec =
- new (arg_t, .name = "index", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "-1"),
- .next = new (arg_t, .name = "count", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "1")));
+ new (arg_t, .name = "index", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(-1)),
+ .next = new (arg_t, .name = "count", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(1))));
return Texts("List$remove_at(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
padded_item_size, ")");
} else if (streq(call->name, "remove_item")) {
EXPECT_POINTER();
arg_t *arg_spec = new (
arg_t, .name = "item", .type = item_t,
- .next = new (arg_t, .name = "max_count", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "-1")));
+ .next = new (arg_t, .name = "max_count", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(-1))));
return Texts("List$remove_item_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
compile_type_info(self_value_t), ")");
} else if (streq(call->name, "has")) {
@@ -257,7 +257,7 @@ Text_t compile_list_method_call(env_t *env, ast_t *ast) {
return Texts("Table$from_entries(", self, ", Table$info(", compile_type_info(item_t), ", &Present$$info))");
} else if (streq(call->name, "pop")) {
EXPECT_POINTER();
- arg_t *arg_spec = new (arg_t, .name = "index", .type = INT_TYPE, .default_val = FakeAST(Integer, "-1"));
+ arg_t *arg_spec = new (arg_t, .name = "index", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(-1)));
Text_t index = compile_arguments(env, ast, arg_spec, call->args);
return Texts("List$pop(", self, ", ", index, ", ", compile_type(item_t), ", _, ",
promote_to_optional(item_t, Text("_")), ", ", compile_none(item_t), ")");
diff --git a/src/compile/loops.c b/src/compile/loops.c
index f3ae9b59..8dd8eca3 100644
--- a/src/compile/loops.c
+++ b/src/compile/loops.c
@@ -125,7 +125,7 @@ Text_t compile_for_loop(env_t *env, ast_t *ast) {
// Special case for Int.onward()
arg_ast_t *args = Match(for_->iter, MethodCall)->args;
arg_t *arg_spec =
- new (arg_t, .name = "step", .type = INT_TYPE, .default_val = FakeAST(Integer, .str = "1"), .next = NULL);
+ new (arg_t, .name = "step", .type = INT_TYPE, .default_val = FakeAST(Integer, .i = I(1)), .next = NULL);
Text_t step = compile_arguments(env, for_->iter, arg_spec, args);
Text_t value = for_->vars ? compile(body_scope, for_->vars->ast) : Text("i");
return Texts("for (Int_t ", value, " = ", compile(env, Match(for_->iter, MethodCall)->self), ", ",
@@ -232,9 +232,7 @@ Text_t compile_for_loop(env_t *env, ast_t *ast) {
case BigIntType: {
Text_t n;
if (for_->iter->tag == Integer) {
- const char *str = Match(for_->iter, Integer)->str;
- Int_t int_val = Int$from_str(str);
- if (int_val.small == 0) code_err(for_->iter, "Failed to parse this integer");
+ Int_t int_val = Match(for_->iter, Integer)->i;
mpz_t i;
mpz_init_set_int(i, int_val);
if (mpz_cmpabs_ui(i, BIGGEST_SMALL_INT) <= 0) n = Text$from_str(mpz_get_str(NULL, 10, i));
diff --git a/src/compile/promotions.c b/src/compile/promotions.c
index a13108e5..a4d6b9b3 100644
--- a/src/compile/promotions.c
+++ b/src/compile/promotions.c
@@ -3,6 +3,7 @@
#include "../ast.h"
#include "../environment.h"
#include "../stdlib/datatypes.h"
+#include "../stdlib/reals.h"
#include "../stdlib/text.h"
#include "../typecheck.h"
#include "../types.h"
@@ -139,8 +140,11 @@ Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t) {
if (ast->tag == Integer && is_numeric_type(non_optional(t))) {
return compile_int_to_type(env, ast, t);
+ } else if (ast->tag == Number && t->tag == RealType) {
+ return compile(env, ast);
} else if (ast->tag == Number && t->tag == FloatType) {
- double n = Match(ast, Number)->n;
+ Real_t real = Match(ast, Number)->n;
+ double n = Real$as_float64(real, true);
switch (Match(t, FloatType)->bits) {
case TYPE_NBITS64: return Text$from_str(String(hex_double(n)));
case TYPE_NBITS32: return Text$from_str(String(hex_double(n), "f"));