diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-18 11:49:51 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-18 11:49:51 -0400 |
| commit | 752ab8212c7556ed714d1272582e57180b50c5a6 (patch) | |
| tree | 50d05d8e7512494fbbe16a27ed89d6a14b401ea5 | |
| parent | 8b94c2c7f198babe64a2636538913cf67165709c (diff) | |
Split BigIntType out of IntType and switch to using enums for the size
of ints/nums
| -rw-r--r-- | ast.c | 4 | ||||
| -rw-r--r-- | ast.h | 4 | ||||
| -rw-r--r-- | compile.c | 125 | ||||
| -rw-r--r-- | environment.c | 14 | ||||
| -rw-r--r-- | parse.c | 19 | ||||
| -rw-r--r-- | repl.c | 49 | ||||
| -rw-r--r-- | structs.c | 31 | ||||
| -rw-r--r-- | typecheck.c | 37 | ||||
| -rw-r--r-- | types.c | 57 | ||||
| -rw-r--r-- | types.h | 10 |
10 files changed, 176 insertions, 174 deletions
@@ -99,8 +99,8 @@ CORD ast_to_xml(ast_t *ast) T(Nil, "<Nil>%r</Nil>", type_ast_to_xml(data.type)) T(Bool, "<Bool value=\"%s\" />", data.b ? "yes" : "no") T(Var, "<Var>%s</Var>", data.name) - T(Int, "<Int bits=\"%ld\">%s</Int>", data.bits, data.str) - T(Num, "<Num bits=\"%ld\">%g</Num>", data.bits, data.n) + T(Int, "<Int bits=\"%d\">%s</Int>", data.bits, data.str) + T(Num, "<Num bits=\"%d\">%g</Num>", data.bits, data.n) T(TextLiteral, "%r", xml_escape(data.cord)) T(TextJoin, "<Text%r>%r</Text>", data.lang ? CORD_all(" lang=\"", data.lang, "\"") : CORD_EMPTY, ast_list_to_xml(data.children)) T(Declare, "<Declare var=\"%r\">%r</Declare>", ast_to_xml(data.var), ast_to_xml(data.value)) @@ -144,11 +144,11 @@ struct ast_s { } Var; struct { const char *str; - int64_t bits; + enum { IBITS_UNSPECIFIED=0, IBITS8=8, IBITS16=16, IBITS32=32, IBITS64=64 } bits; } Int; struct { double n; - int64_t bits; + enum { NBITS_UNSPECIFIED=0, NBITS32=32, NBITS64=64 } bits; } Num; struct { CORD cord; @@ -32,7 +32,7 @@ static bool promote(env_t *env, CORD *code, type_t *actual, type_t *needed) if (!can_promote(actual, needed)) return false; - if (actual->tag == IntType && needed->tag == IntType && Match(needed, IntType)->bits == 0) { + if (actual->tag == IntType && needed->tag == BigIntType) { *code = CORD_all("I(", *code, ")"); return true; } @@ -156,8 +156,9 @@ CORD compile_type(type_t *t) case MemoryType: return "void"; case BoolType: return "Bool_t"; case CStringType: return "char*"; - case IntType: return Match(t, IntType)->bits == 0 ? "Int_t" : CORD_asprintf("Int%ld_t", Match(t, IntType)->bits); - case NumType: return Match(t, NumType)->bits == 64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits); + 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 TextType: { auto text = Match(t, TextType); return text->lang ? CORD_all(namespace_prefix(text->env->libname, text->env->namespace->parent), text->lang, "_t") : "Text_t"; @@ -540,7 +541,7 @@ CORD compile_statement(env_t *env, ast_t *ast) case BINOP_POWER: { if (lhs_t->tag != NumType) code_err(ast, "'^=' is only supported for Num types"); - if (lhs_t->tag == NumType && Match(lhs_t, NumType)->bits == 32) + if (lhs_t->tag == NumType && Match(lhs_t, NumType)->bits == TYPE_NBITS32) return CORD_all(lhs, " = powf(", lhs, ", ", rhs, ");"); else return CORD_all(lhs, " = pow(", lhs, ", ", rhs, ");"); @@ -1248,26 +1249,28 @@ env_t *with_enum_scope(env_t *env, type_t *t) CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target) { - int64_t target_bits = Match(target, IntType)->bits; + if (target->tag == BigIntType) + return compile(env, ast); + + int64_t target_bits = (int64_t)Match(target, IntType)->bits; Int_t int_val = Int$from_text(Match(ast, Int)->str); mpz_t i; mpz_init_set_int(i, int_val); switch (target_bits) { - case 0: return compile(env, ast); - case 64: + case TYPE_IBITS64: if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0) return CORD_asprintf("I64(%s)", Match(ast, Int)->str); break; - case 32: + case TYPE_IBITS32: if (mpz_cmp_si(i, INT32_MAX) <= 0 && mpz_cmp_si(i, INT32_MIN) >= 0) return CORD_asprintf("I32(%s)", Match(ast, Int)->str); break; - case 16: + case TYPE_IBITS16: if (mpz_cmp_si(i, INT16_MAX) <= 0 && mpz_cmp_si(i, INT16_MIN) >= 0) return CORD_asprintf("I16(%s)", Match(ast, Int)->str); break; - case 8: + case TYPE_IBITS8: if (mpz_cmp_si(i, INT8_MAX) <= 0 && mpz_cmp_si(i, INT8_MIN) >= 0) return CORD_asprintf("I8(%s)", Match(ast, Int)->str); break; @@ -1292,7 +1295,7 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t } else if (spec_arg->type->tag == NumType && call_arg->value->tag == Int) { Int_t int_val = Int$from_text(Match(call_arg->value, Int)->str); double n = Int_to_Num(int_val); - value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == 64 + value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == TYPE_NBITS64 ? "N64(%.9g)" : "N32(%.9g)", n); } else { env_t *arg_env = with_enum_scope(env, spec_arg->type); @@ -1320,7 +1323,7 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t } else if (spec_arg->type->tag == NumType && call_arg->value->tag == Int) { Int_t int_val = Int$from_text(Match(call_arg->value, Int)->str); double n = Int_to_Num(int_val); - value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == 64 + value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == TYPE_NBITS64 ? "N64(%.9g)" : "N32(%.9g)", n); } else { env_t *arg_env = with_enum_scope(env, spec_arg->type); @@ -1454,7 +1457,7 @@ CORD compile(env_t *env, ast_t *ast) mpz_init_set_int(i, int_val); switch (Match(ast, Int)->bits) { - case 0: + case IBITS_UNSPECIFIED: if (mpz_cmpabs_ui(i, BIGGEST_SMALL_INT) <= 0) { return CORD_asprintf("I_small(%s)", str); } else if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0) { @@ -1462,19 +1465,19 @@ CORD compile(env_t *env, ast_t *ast) } else { return CORD_asprintf("Int$from_text(\"%s\")", str); } - case 64: + case IBITS64: if ((mpz_cmp_si(i, INT64_MAX) < 0) && (mpz_cmp_si(i, INT64_MIN) > 0)) return CORD_asprintf("I64(%s)", str); code_err(ast, "This value cannot fit in a 64-bit integer"); - case 32: + case IBITS32: if ((mpz_cmp_si(i, INT32_MAX) < 0) && (mpz_cmp_si(i, INT32_MIN) > 0)) return CORD_asprintf("I32(%s)", str); code_err(ast, "This value cannot fit in a 32-bit integer"); - case 16: + case IBITS16: if ((mpz_cmp_si(i, INT16_MAX) < 0) && (mpz_cmp_si(i, INT16_MIN) > 0)) return CORD_asprintf("I16(%s)", str); code_err(ast, "This value cannot fit in a 16-bit integer"); - case 8: + case IBITS8: if ((mpz_cmp_si(i, INT8_MAX) < 0) && (mpz_cmp_si(i, INT8_MIN) > 0)) return CORD_asprintf("I8(%s)", str); code_err(ast, "This value cannot fit in a 8-bit integer"); @@ -1482,7 +1485,13 @@ CORD compile(env_t *env, ast_t *ast) } } case Num: { - return CORD_asprintf(Match(ast, Num)->bits == 64 ? "N64(%.9g)" : "N32(%.9g)", Match(ast, Num)->n); + switch (Match(ast, Num)->bits) { + case NBITS_UNSPECIFIED: case NBITS64: + return CORD_asprintf("N64(%.9g)", Match(ast, Num)->n); + case NBITS32: + return CORD_asprintf("N32(%.9g)", Match(ast, Num)->n); + default: code_err(ast, "This is not a valid number bit width"); + } } case Length: { ast_t *expr = Match(ast, Length)->value; @@ -1588,7 +1597,7 @@ CORD compile(env_t *env, ast_t *ast) case BINOP_POWER: { if (operand_t->tag != NumType) code_err(ast, "Exponentiation is only supported for Num types"); - if (operand_t->tag == NumType && Match(operand_t, NumType)->bits == 32) + if (operand_t->tag == NumType && Match(operand_t, NumType)->bits == TYPE_NBITS32) return CORD_all("powf(", lhs, ", ", rhs, ")"); else return CORD_all("pow(", lhs, ", ", rhs, ")"); @@ -1635,11 +1644,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_EQ: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("Int$equal_value(", lhs, ", ", rhs, ")"); - return CORD_all("(", lhs, " == ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("Int$equal_value(", lhs, ", ", rhs, ")"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " == ", rhs, ")"); default: return CORD_asprintf("generic_equal(stack(%r), stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1647,11 +1654,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_NE: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("!Int$equal_value(", lhs, ", ", rhs, ")"); - return CORD_all("(", lhs, " != ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("!Int$equal_value(", lhs, ", ", rhs, ")"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " != ", rhs, ")"); default: return CORD_asprintf("!generic_equal(stack(%r), stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1659,11 +1664,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_LT: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") < 0)"); - return CORD_all("(", lhs, " != ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") < 0)"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " < ", rhs, ")"); default: return CORD_asprintf("(generic_compare(stack(%r), stack(%r), %r) < 0)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1671,11 +1674,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_LE: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") <= 0)"); - return CORD_all("(", lhs, " != ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") <= 0)"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " <= ", rhs, ")"); default: return CORD_asprintf("(generic_compare(stack(%r), stack(%r), %r) <= 0)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1683,11 +1684,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_GT: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") > 0)"); - return CORD_all("(", lhs, " != ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") > 0)"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " > ", rhs, ")"); default: return CORD_asprintf("(generic_compare(stack(%r), stack(%r), %r) > 0)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1695,11 +1694,9 @@ CORD compile(env_t *env, ast_t *ast) } case BINOP_GE: { switch (operand_t->tag) { - case IntType: - if (Match(operand_t, IntType)->bits == 0) - return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") >= 0)"); - return CORD_all("(", lhs, " != ", rhs, ")"); - case BoolType: case NumType: case PointerType: case FunctionType: + case BigIntType: + return CORD_all("(Int$compare_value(", lhs, ", ", rhs, ") >= 0)"); + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_all("(", lhs, " >= ", rhs, ")"); default: return CORD_asprintf("(generic_compare(stack(%r), stack(%r), %r) >= 0)", lhs, rhs, compile_type_info(env, operand_t)); @@ -1865,7 +1862,7 @@ CORD compile(env_t *env, ast_t *ast) type_t *key_t = get_type(expr_env, key); CORD comparison; - if (key_t->tag == IntType && Match(key_t, IntType)->bits == 0) + if (key_t->tag == BigIntType) comparison = CORD_all("(Int$compare_value(", lhs_key, ", ", rhs_key, ")", (ast->tag == Min ? "<=" : ">="), "0)"); else if (key_t->tag == IntType || key_t->tag == NumType || key_t->tag == BoolType || key_t->tag == PointerType) comparison = CORD_all("((", lhs_key, ")", (ast->tag == Min ? "<=" : ">="), "(", rhs_key, "))"); @@ -2161,25 +2158,25 @@ CORD compile(env_t *env, ast_t *ast) if (streq(call->name, "insert")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, - .next=new(arg_t, .name="at", .type=INT_TYPE, .default_val=FakeAST(Int, .str="0", .bits=0))); + .next=new(arg_t, .name="at", .type=INT_TYPE, .default_val=FakeAST(Int, .str="0"))); return CORD_all("Array$insert_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "insert_all")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); 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(Int, .str="0", .bits=0))); + .next=new(arg_t, .name="at", .type=INT_TYPE, .default_val=FakeAST(Int, .str="0"))); return CORD_all("Array$insert_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "remove_at")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); - arg_t *arg_spec = new(arg_t, .name="index", .type=INT_TYPE, .default_val=FakeAST(Int, .str="-1", .bits=0), - .next=new(arg_t, .name="count", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1", .bits=0))); + arg_t *arg_spec = new(arg_t, .name="index", .type=INT_TYPE, .default_val=FakeAST(Int, .str="-1"), + .next=new(arg_t, .name="count", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"))); return CORD_all("Array$remove_at(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "remove_item")) { CORD self = compile_to_pointer_depth(env, call->self, 1, false); 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(Int, .str="-1", .bits=0))); + .next=new(arg_t, .name="max_count", .type=INT_TYPE, .default_val=FakeAST(Int, .str="-1"))); return CORD_all("Array$remove_item_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type_info(env, self_value_t), ")"); } else if (streq(call->name, "random")) { @@ -2194,7 +2191,7 @@ CORD compile(env_t *env, ast_t *ast) } else if (streq(call->name, "sample")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); arg_t *arg_spec = new(arg_t, .name="count", .type=INT_TYPE, - .next=new(arg_t, .name="weights", .type=Type(ArrayType, .item_type=Type(NumType, .bits=64)), + .next=new(arg_t, .name="weights", .type=Type(ArrayType, .item_type=Type(NumType)), .default_val=FakeAST(Array, .item_type=new(type_ast_t, .tag=VarTypeAST, .__data.VarTypeAST.name="Num")))); return CORD_all("Array$sample(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); @@ -2212,7 +2209,7 @@ CORD compile(env_t *env, ast_t *ast) if (call->args) { type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true, .is_readonly=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), - .ret=Type(IntType, .bits=32)); + .ret=Type(IntType, .bits=TYPE_IBITS32)); arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t)); comparison = compile_arguments(env, ast, arg_spec, call->args); } else { @@ -2225,7 +2222,7 @@ CORD compile(env_t *env, ast_t *ast) if (call->args) { type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), - .ret=Type(IntType, .bits=32)); + .ret=Type(IntType, .bits=TYPE_IBITS32)); arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t)); comparison = compile_arguments(env, ast, arg_spec, call->args); } else { @@ -2236,7 +2233,7 @@ CORD compile(env_t *env, ast_t *ast) CORD self = compile_to_pointer_depth(env, call->self, 1, false); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), - .ret=Type(IntType, .bits=32)); + .ret=Type(IntType, .bits=TYPE_IBITS32)); ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), @@ -2249,7 +2246,7 @@ CORD compile(env_t *env, ast_t *ast) CORD self = compile_to_pointer_depth(env, call->self, 1, false); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), - .ret=Type(IntType, .bits=32)); + .ret=Type(IntType, .bits=TYPE_IBITS32)); ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), @@ -2261,7 +2258,7 @@ CORD compile(env_t *env, ast_t *ast) CORD self = compile_to_pointer_depth(env, call->self, 0, false); type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true); type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)), - .ret=Type(IntType, .bits=32)); + .ret=Type(IntType, .bits=TYPE_IBITS32)); ast_t *default_cmp = FakeAST(InlineCCode, .code=CORD_all("((closure_t){.fn=generic_compare, .userdata=(void*)", compile_type_info(env, item_t), "})"), @@ -2436,8 +2433,8 @@ CORD compile(env_t *env, ast_t *ast) if (!(table->value_type->tag == IntType || table->value_type->tag == NumType)) code_err(ast, "bump() is only supported for tables with numeric value types, not %T", self_value_t); ast_t *one = table->value_type->tag == IntType - ? FakeAST(Int, .str="1", .bits=Match(table->value_type, IntType)->bits) - : FakeAST(Num, .n=1, .bits=Match(table->value_type, NumType)->bits); + ? FakeAST(Int, .str="1") + : FakeAST(Num, .n=1); arg_t *arg_spec = new(arg_t, .name="key", .type=table->key_type, .next=new(arg_t, .name="amount", .type=table->value_type, .default_val=one)); return CORD_all("Table$bump(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", @@ -2479,7 +2476,7 @@ CORD compile(env_t *env, ast_t *ast) // Struct constructor: fn_t = Type(FunctionType, .args=Match(t, StructType)->fields, .ret=t); return CORD_all("((", compile_type(t), "){", compile_arguments(env, ast, Match(fn_t, FunctionType)->args, call->args), "})"); - } else if (t->tag == NumType || (t->tag == IntType && Match(t, IntType)->bits == 0)) { + } else if (t->tag == NumType || t->tag == BigIntType) { type_t *actual = get_type(env, call->args->value); arg_t *args = new(arg_t, .name="i", .type=actual); // No truncation argument CORD arg_code = compile_arguments(env, ast, args, call->args); diff --git a/environment.c b/environment.c index becf1291..411074ef 100644 --- a/environment.c +++ b/environment.c @@ -87,7 +87,7 @@ env_t *new_compilation_unit(CORD *libname) {"from_text", "Bool$from_text", "func(text:Text, success=!&Bool)->Bool"}, {"random", "Bool$random", "func(p=0.5)->Bool"}, )}, - {"Int", Type(IntType, .bits=0), "Int_t", "$Int", TypedArray(ns_entry_t, + {"Int", Type(BigIntType), "Int_t", "$Int", TypedArray(ns_entry_t, {"format", "Int$format", "func(i:Int, digits=0)->Text"}, {"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"}, {"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes)->Text"}, @@ -111,7 +111,7 @@ env_t *new_compilation_unit(CORD *libname) {"sqrt", "Int$sqrt", "func(x:Int)->Int"}, {"power", "Int$power", "func(base:Int,exponent:Int)->Int"}, )}, - {"Int64", Type(IntType, .bits=64), "Int64_t", "$Int64", TypedArray(ns_entry_t, + {"Int64", Type(IntType, .bits=TYPE_IBITS64), "Int64_t", "$Int64", TypedArray(ns_entry_t, {"format", "Int64$format", "func(i:Int64, digits=0)->Text"}, {"hex", "Int64$hex", "func(i:Int64, digits=0, uppercase=yes, prefix=yes)->Text"}, {"octal", "Int64$octal", "func(i:Int64, digits=0, prefix=yes)->Text"}, @@ -126,7 +126,7 @@ env_t *new_compilation_unit(CORD *libname) {"modulo", "Int64$modulo", "func(x:Int64,y:Int64)->Int64"}, {"modulo1", "Int64$modulo1", "func(x:Int64,y:Int64)->Int64"}, )}, - {"Int32", Type(IntType, .bits=32), "Int32_t", "$Int32", TypedArray(ns_entry_t, + {"Int32", Type(IntType, .bits=TYPE_IBITS32), "Int32_t", "$Int32", TypedArray(ns_entry_t, {"format", "Int32$format", "func(i:Int32, digits=0)->Text"}, {"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"}, {"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes)->Text"}, @@ -141,7 +141,7 @@ env_t *new_compilation_unit(CORD *libname) {"modulo", "Int32$modulo", "func(x:Int32,y:Int32)->Int32"}, {"modulo1", "Int32$modulo1", "func(x:Int32,y:Int32)->Int32"}, )}, - {"Int16", Type(IntType, .bits=16), "Int16_t", "$Int16", TypedArray(ns_entry_t, + {"Int16", Type(IntType, .bits=TYPE_IBITS16), "Int16_t", "$Int16", TypedArray(ns_entry_t, {"format", "Int16$format", "func(i:Int16, digits=0)->Text"}, {"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"}, {"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes)->Text"}, @@ -156,7 +156,7 @@ env_t *new_compilation_unit(CORD *libname) {"modulo", "Int16$modulo", "func(x:Int16,y:Int16)->Int16"}, {"modulo1", "Int16$modulo1", "func(x:Int16,y:Int16)->Int16"}, )}, - {"Int8", Type(IntType, .bits=8), "Int8_t", "$Int8", TypedArray(ns_entry_t, + {"Int8", Type(IntType, .bits=TYPE_IBITS8), "Int8_t", "$Int8", TypedArray(ns_entry_t, {"format", "Int8$format", "func(i:Int8, digits=0)->Text"}, {"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"}, {"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes)->Text"}, @@ -174,7 +174,7 @@ env_t *new_compilation_unit(CORD *libname) #define C(name) {#name, "M_"#name, "Num"} #define F(name) {#name, #name, "func(n:Num)->Num"} #define F2(name) {#name, #name, "func(x:Num, y:Num)->Num"} - {"Num", Type(NumType, .bits=64), "Num_t", "$Num", TypedArray(ns_entry_t, + {"Num", Type(NumType, .bits=TYPE_NBITS64), "Num_t", "$Num", TypedArray(ns_entry_t, {"near", "Num$near", "func(x:Num, y:Num, ratio=1e-9, min_epsilon=1e-9)->Bool"}, {"format", "Num$format", "func(n:Num, precision=0)->Text"}, {"scientific", "Num$scientific", "func(n:Num, precision=0)->Text"}, @@ -202,7 +202,7 @@ env_t *new_compilation_unit(CORD *libname) #define C(name) {#name, "(Num32_t)(M_"#name")", "Num32"} #define F(name) {#name, #name"f", "func(n:Num32)->Num32"} #define F2(name) {#name, #name"f", "func(x:Num32, y:Num32)->Num32"} - {"Num32", Type(NumType, .bits=32), "Num32_t", "$Num32", TypedArray(ns_entry_t, + {"Num32", Type(NumType, .bits=TYPE_NBITS32), "Num32_t", "$Num32", TypedArray(ns_entry_t, {"near", "Num32$near", "func(x:Num32, y:Num32, ratio=1e-9f32, min_epsilon=1e-9f32)->Bool"}, {"format", "Num32$format", "func(n:Num32, precision=0)->Text"}, {"scientific", "Num32$scientific", "func(n:Num32, precision=0)->Text"}, @@ -468,11 +468,11 @@ PARSER(parse_int) { } match(&pos, "_"); - int64_t bits = 0; - if (match(&pos, "i64")) bits = 64; - else if (match(&pos, "i32")) bits = 32; - else if (match(&pos, "i16")) bits = 16; - else if (match(&pos, "i8")) bits = 8; + auto bits = IBITS_UNSPECIFIED; + if (match(&pos, "i64")) bits = IBITS64; + else if (match(&pos, "i32")) bits = IBITS32; + else if (match(&pos, "i16")) bits = IBITS16; + else if (match(&pos, "i8")) bits = IBITS8; // else if (match(&pos, ".") || match(&pos, "e")) return NULL; // looks like a float @@ -624,14 +624,13 @@ PARSER(parse_num) { if (negative) d *= -1; - int64_t bits = 64; + auto bits = NBITS_UNSPECIFIED; match(&pos, "_"); - if (match(&pos, "f64")) bits = 64; - else if (match(&pos, "f32")) bits = 32; + if (match(&pos, "f64")) bits = NBITS64; + else if (match(&pos, "f32")) bits = NBITS32; - if (match(&pos, "%")) { + if (match(&pos, "%")) d /= 100.; - } return NewAST(ctx->file, start, pos, Num, .n=d, .bits=bits); } @@ -103,18 +103,19 @@ const TypeInfo *type_to_type_info(type_t *t) case VoidType: return &$Void; case MemoryType: return &$Memory; case BoolType: return &$Bool; + case BigIntType: return &$Int; case IntType: switch (Match(t, IntType)->bits) { - case 0: case 64: return &$Int; - case 32: return &$Int32; - case 16: return &$Int16; - case 8: return &$Int8; + case TYPE_IBITS64: return &$Int64; + case TYPE_IBITS32: return &$Int32; + case TYPE_IBITS16: return &$Int16; + case TYPE_IBITS8: return &$Int8; default: errx(1, "Invalid bits"); } case NumType: switch (Match(t, NumType)->bits) { - case 0: case 64: return &$Num; - case 32: return &$Num32; + case TYPE_NBITS64: return &$Num; + case TYPE_NBITS32: return &$Num32; default: errx(1, "Invalid bits"); } case TextType: return &$Text; @@ -161,15 +162,19 @@ static Int_t ast_to_int(env_t *env, ast_t *ast) { type_t *t = get_type(env, ast); switch (t->tag) { + case BigIntType: { + number_t num; + eval(env, ast, &num); + return num.integer; + } case IntType: { number_t num; eval(env, ast, &num); switch (Match(t, IntType)->bits) { - case 0: return num.integer; - case 64: return Int64_to_Int((int64_t)num.i64); - case 32: return Int32_to_Int(num.i32); - case 16: return Int16_to_Int(num.i16); - case 8: return Int8_to_Int(num.i8); + case TYPE_IBITS64: return Int64_to_Int((int64_t)num.i64); + case TYPE_IBITS32: return Int32_to_Int(num.i32); + case TYPE_IBITS16: return Int16_to_Int(num.i16); + case TYPE_IBITS8: return Int8_to_Int(num.i8); default: errx(1, "Invalid int bits"); } } @@ -181,22 +186,23 @@ static double ast_to_num(env_t *env, ast_t *ast) { type_t *t = get_type(env, ast); switch (t->tag) { - case IntType: { + case BigIntType: case IntType: { number_t num; eval(env, ast, &num); + if (t->tag == BigIntType) + return Int_to_Num(num.integer); switch (Match(t, IntType)->bits) { - case 0: return Int_to_Num(num.integer); - case 64: return (double)num.i64; - case 32: return (double)num.i32; - case 16: return (double)num.i16; - case 8: return (double)num.i8; + case TYPE_IBITS64: return (double)num.i64; + case TYPE_IBITS32: return (double)num.i32; + case TYPE_IBITS16: return (double)num.i16; + case TYPE_IBITS8: return (double)num.i8; default: errx(1, "Invalid int bits"); } } case NumType: { number_t num; eval(env, ast, &num); - return Match(t, NumType)->bits == 32 ? (double)num.n32 : (double)num.n64; + return Match(t, NumType)->bits == TYPE_NBITS32 ? (double)num.n32 : (double)num.n64; } default: repl_err(NULL, "Cannot convert to number"); } @@ -388,13 +394,16 @@ void eval(env_t *env, ast_t *ast, void *dest) } case BinaryOp: { auto binop = Match(ast, BinaryOp); - if (t->tag == IntType) { + if (t->tag == IntType || t->tag == BigIntType) { #define CASE_OP(OP_NAME, method_name) case BINOP_##OP_NAME: {\ Int_t lhs = ast_to_int(env, binop->lhs); \ Int_t rhs = ast_to_int(env, binop->rhs); \ Int_t result = Int$ ## method_name (lhs, rhs); \ + if (t->tag == BigIntType) {\ + *(Int_t*)dest = result; \ + return; \ + } \ switch (Match(t, IntType)->bits) { \ - case 0: *(Int_t*)dest = result; return; \ case 64: *(int64_t*)dest = Int_to_Int64(result, false); return; \ case 32: *(int32_t*)dest = Int_to_Int32(result, false); return; \ case 16: *(int16_t*)dest = Int_to_Int16(result, false); return; \ @@ -47,13 +47,10 @@ static CORD compile_compare_method(env_t *env, ast_t *ast) for (arg_ast_t *field = def->fields; field; field = field->next) { type_t *field_type = get_arg_ast_type(env, field); switch (field_type->tag) { - case IntType: - if (Match(field_type, IntType)->bits == 0) - cmp_func = CORD_all(cmp_func, "diff = Int$compare_value(x->$", field->name, ", y->$", field->name, ");"); - else - cmp_func = CORD_all(cmp_func, "diff = (x->$", field->name, " > y->$", field->name, ") - (x->$", field->name, " < y->$", field->name, ");"); + case BigIntType: + cmp_func = CORD_all(cmp_func, "diff = Int$compare_value(x->$", field->name, ", y->$", field->name, ");"); break; - case BoolType: case NumType: case PointerType: case FunctionType: + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: cmp_func = CORD_all(cmp_func, "diff = (x->$", field->name, " > y->$", field->name, ") - (x->$", field->name, " < y->$", field->name, ");"); break; case TextType: @@ -83,13 +80,10 @@ static CORD compile_equals_method(env_t *env, ast_t *ast) condition = CORD_all(condition, " && "); type_t *field_type = get_arg_ast_type(env, field); switch (field_type->tag) { - case IntType: - if (Match(field_type, IntType)->bits == 0) - condition = CORD_all(condition, "Int$equal_value(x->$", field->name, ", y->$", field->name, ")"); - else - condition = CORD_all(condition, "(x->$", field->name, " == y->$", field->name, ")"); + case BigIntType: + condition = CORD_all(condition, "Int$equal_value(x->$", field->name, ", y->$", field->name, ")"); break; - case BoolType: case NumType: case PointerType: case FunctionType: + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: condition = CORD_all(condition, "(x->$", field->name, " == y->$", field->name, ")"); break; case TextType: @@ -144,24 +138,15 @@ void compile_struct_def(env_t *env, ast_t *ast) if (struct_->fields && !struct_->fields->next) { // Single member, can just use its methods type_t *member_t = struct_->fields->type; switch (member_t->tag) { - case NumType: + case IntType: case NumType: typeinfo = CORD_all(typeinfo, ".compare=(void*)", type_to_cord(member_t), "$compare, " ".equal=(void*)", type_to_cord(member_t), "$equal, "); goto got_methods; - case TextType: + case BigIntType: case TextType: typeinfo = CORD_all(typeinfo, ".hash=(void*)", type_to_cord(member_t), "$hash", ", ", ".compare=(void*)", type_to_cord(member_t), "$compare, " ".equal=(void*)", type_to_cord(member_t), "$equal, "); goto got_methods; - case IntType: - if (Match(member_t, IntType)->bits == 0) - typeinfo = CORD_all(typeinfo, ".hash=(void*)Int$hash", ", ", - ".compare=(void*)Int$compare, " - ".equal=(void*)Int$equal, "); - else - typeinfo = CORD_all(typeinfo, ".compare=(void*)", type_to_cord(member_t), "$compare, " - ".equal=(void*)", type_to_cord(member_t), "$equal, "); - goto got_methods; case BoolType: goto got_methods; default: break; } diff --git a/typecheck.c b/typecheck.c index 332f68e1..129a71da 100644 --- a/typecheck.c +++ b/typecheck.c @@ -116,15 +116,11 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast) type_t *get_math_type(env_t *env, ast_t *ast, type_t *lhs_t, type_t *rhs_t) { (void)env; - if (lhs_t->tag == IntType && rhs_t->tag == IntType) - return Match(lhs_t, IntType)->bits >= Match(rhs_t, IntType)->bits ? lhs_t : rhs_t; - else if (lhs_t->tag == NumType && rhs_t->tag == NumType) - return Match(lhs_t, NumType)->bits >= Match(rhs_t, NumType)->bits ? lhs_t : rhs_t; - else if (lhs_t->tag == NumType && rhs_t->tag == IntType) - return lhs_t; - else if (rhs_t->tag == NumType && lhs_t->tag == IntType) - return rhs_t; - + switch (compare_precision(lhs_t, rhs_t)) { + case NUM_PRECISION_EQUAL: case NUM_PRECISION_MORE: return lhs_t; + case NUM_PRECISION_LESS: return rhs_t; + default: return NULL; + } code_err(ast, "Math operations between %T and %T are not supported", lhs_t, rhs_t); } @@ -456,11 +452,24 @@ type_t *get_type(env_t *env, ast_t *ast) } case Int: { auto i = Match(ast, Int); - return Type(IntType, .bits=i->bits); + switch (i->bits) { + case IBITS_UNSPECIFIED: return Type(BigIntType); + case IBITS8: return Type(IntType, .bits=TYPE_IBITS8); + case IBITS16: return Type(IntType, .bits=TYPE_IBITS16); + case IBITS32: return Type(IntType, .bits=TYPE_IBITS32); + case IBITS64: return Type(IntType, .bits=TYPE_IBITS64); + default: errx(1, "Invalid integer bits"); + } } case Num: { auto n = Match(ast, Num); - return Type(NumType, .bits=n->bits); + switch (n->bits) { + case NBITS_UNSPECIFIED: case NBITS64: + return Type(NumType, .bits=TYPE_NBITS64); + case NBITS32: + return Type(NumType, .bits=TYPE_NBITS32); + default: errx(1, "Invalid num bits"); + } } case HeapAllocate: { type_t *pointed = get_type(env, Match(ast, HeapAllocate)->value); @@ -987,12 +996,12 @@ type_t *get_type(env_t *env, ast_t *ast) return Type(BoolType); } case BINOP_CMP: - return Type(IntType, .bits=32); + return Type(IntType, .bits=TYPE_IBITS32); case BINOP_POWER: { type_t *result = get_math_type(env, ast, lhs_t, rhs_t); if (result->tag == NumType) return result; - return Type(NumType, .bits=64); + return Type(NumType, .bits=TYPE_NBITS64); } default: { return get_math_type(env, ast, lhs_t, rhs_t); @@ -1351,7 +1360,7 @@ bool is_constant(env_t *env, ast_t *ast) case Bool: case Num: case Nil: case TextLiteral: return true; case Int: { auto info = Match(ast, Int); - if (info->bits == 0) { + if (info->bits == IBITS_UNSPECIFIED) { Int_t int_val = Int$from_text(info->str); mpz_t i; mpz_init_set_int(i, int_val); @@ -19,8 +19,9 @@ CORD type_to_cord(type_t *t) { case BoolType: return "Bool"; case CStringType: return "CString"; case TextType: return Match(t, TextType)->lang ? Match(t, TextType)->lang : "Text"; - case IntType: return Match(t, IntType)->bits == 0 ? "Int" : CORD_asprintf("Int%ld", Match(t, IntType)->bits); - case NumType: return Match(t, NumType)->bits == 64 ? "Num" : CORD_asprintf("Num%ld", Match(t, NumType)->bits); + case BigIntType: return "Int"; + case IntType: return CORD_asprintf("Int%d", Match(t, IntType)->bits); + case NumType: return Match(t, NumType)->bits == TYPE_NBITS32 ? "Num32" : "Num"; case ArrayType: { auto array = Match(t, ArrayType); return CORD_asprintf("[%r]", type_to_cord(array->item_type)); @@ -154,14 +155,14 @@ static inline double type_min_magnitude(type_t *t) { switch (t->tag) { case BoolType: return (double)false; + case BigIntType: return -1./0.; case IntType: { switch (Match(t, IntType)->bits) { - case 0: return -1./0.; - case 8: return (double)INT8_MIN; - case 16: return (double)INT16_MIN; - case 32: return (double)INT32_MIN; - case 64: return (double)INT64_MIN; - default: return NAN; + case TYPE_IBITS8: return (double)INT8_MIN; + case TYPE_IBITS16: return (double)INT16_MIN; + case TYPE_IBITS32: return (double)INT32_MIN; + case TYPE_IBITS64: return (double)INT64_MIN; + default: errx(1, "Invalid integer bit size"); } } case NumType: return -1./0.; @@ -173,14 +174,14 @@ static inline double type_max_magnitude(type_t *t) { switch (t->tag) { case BoolType: return (double)true; + case BigIntType: return 1./0.; case IntType: { switch (Match(t, IntType)->bits) { - case 0: return 1./0.; - case 8: return (double)INT8_MAX; - case 16: return (double)INT16_MAX; - case 32: return (double)INT32_MAX; - case 64: return (double)INT64_MAX; - default: return NAN; + case TYPE_IBITS8: return (double)INT8_MAX; + case TYPE_IBITS16: return (double)INT16_MAX; + case TYPE_IBITS32: return (double)INT32_MAX; + case TYPE_IBITS64: return (double)INT64_MAX; + default: errx(1, "Invalid integer bit size"); } } case NumType: return 1./0.; @@ -211,7 +212,7 @@ bool has_heap_memory(type_t *t) case TableType: return true; case SetType: return true; case PointerType: return true; - case IntType: return (Match(t, IntType)->bits == 0); + case BigIntType: return true; case StructType: { for (arg_t *field = Match(t, StructType)->fields; field; field = field->next) { if (has_heap_memory(field->type)) @@ -452,17 +453,17 @@ size_t type_size(type_t *t) case MemoryType: errx(1, "Memory has undefined type size"); case BoolType: return sizeof(bool); case CStringType: return sizeof(char*); + case BigIntType: return sizeof(Int_t); case IntType: { switch (Match(t, IntType)->bits) { - case 0: return sizeof(Int_t); - case 64: return sizeof(int64_t); - case 32: return sizeof(int32_t); - case 16: return sizeof(int16_t); - case 8: return sizeof(int8_t); - default: return 0; + case TYPE_IBITS64: return sizeof(int64_t); + case TYPE_IBITS32: return sizeof(int32_t); + case TYPE_IBITS16: return sizeof(int16_t); + case TYPE_IBITS8: return sizeof(int8_t); + default: errx(1, "Invalid integer bit size"); } } - case NumType: return Match(t, NumType)->bits/8; + case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? sizeof(double) : sizeof(float); case TextType: return sizeof(CORD); case ArrayType: return sizeof(array_t); case SetType: return sizeof(table_t); @@ -515,17 +516,17 @@ size_t type_align(type_t *t) case MemoryType: errx(1, "Memory has undefined type alignment"); case BoolType: return __alignof__(bool); case CStringType: return __alignof__(char*); + case BigIntType: return __alignof__(Int_t); case IntType: { switch (Match(t, IntType)->bits) { - case 0: return __alignof__(Int_t); - case 64: return __alignof__(int64_t); - case 32: return __alignof__(int32_t); - case 16: return __alignof__(int16_t); - case 8: return __alignof__(int8_t); + case TYPE_IBITS64: return __alignof__(int64_t); + case TYPE_IBITS32: return __alignof__(int32_t); + case TYPE_IBITS16: return __alignof__(int16_t); + case TYPE_IBITS8: return __alignof__(int8_t); default: return 0; } } - case NumType: return Match(t, NumType)->bits/8; + case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? __alignof__(double) : __alignof__(float); case TextType: return __alignof__(CORD); case SetType: return __alignof__(table_t); case ArrayType: return __alignof__(array_t); @@ -43,6 +43,7 @@ struct type_s { VoidType, MemoryType, BoolType, + BigIntType, IntType, NumType, CStringType, @@ -66,11 +67,12 @@ struct type_s { struct { type_t *ret; } ReturnType; + struct {} BigIntType; struct { - int64_t bits; + enum { TYPE_IBITS8=8, TYPE_IBITS16=16, TYPE_IBITS32=32, TYPE_IBITS64=64 } bits; } IntType; struct { - int64_t bits; + enum { TYPE_NBITS32=32, TYPE_NBITS64=64 } bits; } NumType; struct {} CStringType; struct { @@ -121,8 +123,8 @@ struct type_s { }; #define Type(typetag, ...) new(type_t, .tag=typetag, .__data.typetag={__VA_ARGS__}) -#define INT_TYPE Type(IntType, .bits=0) -#define NUM_TYPE Type(NumType, .bits=64) +#define INT_TYPE Type(BigIntType) +#define NUM_TYPE Type(NumType, .bits=TYPE_NBITS64) int printf_pointer_size(const struct printf_info *info, size_t n, int argtypes[n], int size[n]); int printf_type(FILE *stream, const struct printf_info *info, const void *const args[]); |
