diff options
Diffstat (limited to 'src/compile')
| -rw-r--r-- | src/compile/functions.c | 13 | ||||
| -rw-r--r-- | src/compile/integers.c | 38 | ||||
| -rw-r--r-- | src/compile/lists.c | 12 | ||||
| -rw-r--r-- | src/compile/loops.c | 6 | ||||
| -rw-r--r-- | src/compile/promotions.c | 6 |
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")); |
