From da4d07c6658f6b8189f98dfb051a7299fe45fb62 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 18 Aug 2024 12:47:29 -0400 Subject: Fix up some bigint logic issues --- compile.c | 22 +++++++++++----------- environment.c | 5 ++--- typecheck.c | 24 ++++++++++++------------ types.c | 15 ++++++++++++++- types.h | 2 ++ 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/compile.c b/compile.c index 88902cfb..c0f52c4f 100644 --- a/compile.c +++ b/compile.c @@ -37,7 +37,7 @@ static bool promote(env_t *env, CORD *code, type_t *actual, type_t *needed) return true; } - if (actual->tag == IntType && needed->tag == NumType) { + if ((actual->tag == IntType || actual->tag == BigIntType) && needed->tag == NumType) { *code = CORD_all(type_to_cord(actual), "_to_", type_to_cord(needed), "(", *code, ")"); return true; } @@ -1022,7 +1022,7 @@ CORD compile_statement(env_t *env, ast_t *ast) } return loop; } - case IntType: { + case BigIntType: { CORD n = compile(env, for_->iter); if (for_->empty) { return CORD_all( @@ -1164,7 +1164,7 @@ CORD expr_as_text(env_t *env, CORD expr, type_t *t, CORD color) case MemoryType: return CORD_asprintf("Memory$as_text(stack(%r), %r, &$Memory)", expr, color); case BoolType: return CORD_asprintf("Bool$as_text((Bool_t[1]){%r}, %r, &$Bool)", expr, color); case CStringType: return CORD_asprintf("CString$as_text(stack(%r), %r, &$CString)", expr, color); - case IntType: { + case BigIntType: case IntType: { CORD name = type_to_cord(t); return CORD_asprintf("%r$as_text(stack(%r), %r, &$%r)", name, expr, color, name); } @@ -1387,11 +1387,11 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]); if (binding_works(b, lhs_t, rhs_t, lhs_t)) return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")"); - } else if (lhs_t->tag == NumType || lhs_t->tag == IntType) { + } else if (lhs_t->tag == NumType || lhs_t->tag == IntType || lhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, rhs, "scaled_by"); if (binding_works(b, rhs_t, lhs_t, rhs_t)) return CORD_all(b->code, "(", compile(env, rhs), ", ", compile(env, lhs), ")"); - } else if (rhs_t->tag == NumType || rhs_t->tag == IntType) { + } else if (rhs_t->tag == NumType || rhs_t->tag == IntType|| rhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, lhs, "scaled_by"); if (binding_works(b, lhs_t, rhs_t, lhs_t)) return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")"); @@ -1407,7 +1407,7 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t break; } case BINOP_DIVIDE: case BINOP_MOD: case BINOP_MOD1: { - if (rhs_t->tag == NumType || rhs_t->tag == IntType) { + if (rhs_t->tag == NumType || rhs_t->tag == IntType || rhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]); if (binding_works(b, lhs_t, rhs_t, lhs_t)) return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")"); @@ -1415,7 +1415,7 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t break; } case BINOP_LSHIFT: case BINOP_RSHIFT: { - if (rhs_t->tag == IntType) { + if (rhs_t->tag == IntType || rhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]); if (binding_works(b, lhs_t, rhs_t, lhs_t)) return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")"); @@ -1423,7 +1423,7 @@ CORD compile_math_method(env_t *env, binop_e op, ast_t *lhs, ast_t *rhs, type_t break; } case BINOP_POWER: { - if (rhs_t->tag == NumType || rhs_t->tag == IntType) { + if (rhs_t->tag == NumType || rhs_t->tag == IntType || rhs_t->tag == BigIntType) { binding_t *b = get_namespace_binding(env, lhs, binop_method_names[op]); if (binding_works(b, lhs_t, rhs_t, lhs_t)) return CORD_all(b->code, "(", compile(env, lhs), ", ", compile(env, rhs), ")"); @@ -2677,7 +2677,7 @@ CORD compile(env_t *env, ast_t *ast) type_t *container_t = value_type(indexed_type); type_t *index_t = get_type(env, indexing->index); if (container_t->tag == ArrayType) { - if (index_t->tag != IntType) + if (index_t->tag != IntType && index_t->tag != BigIntType) code_err(indexing->index, "Arrays can only be indexed by integers, not %T", index_t); type_t *item_type = Match(container_t, ArrayType)->item_type; CORD arr = compile_to_pointer_depth(env, indexing->indexed, 0, false); @@ -2792,7 +2792,7 @@ CORD compile_namespace_definitions(env_t *env, const char *ns_name, ast_t *block CORD compile_type_info(env_t *env, type_t *t) { switch (t->tag) { - case BoolType: case IntType: case NumType: case CStringType: + case BoolType: case IntType: case BigIntType: case NumType: case CStringType: return CORD_asprintf("&$%r", type_to_cord(t)); case TextType: { auto text = Match(t, TextType); @@ -2930,7 +2930,7 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type) "}\n"); break; } - case IntType: case NumType: { + case IntType: case BigIntType: case NumType: { CORD type_name = type_to_cord(t); code = CORD_all(code, "else if (pop_flag(argv, &i, \"", flag, "\", &flag)) {\n", "if (flag == CORD_EMPTY)\n" diff --git a/environment.c b/environment.c index 411074ef..7f7d7e7f 100644 --- a/environment.c +++ b/environment.c @@ -411,7 +411,7 @@ env_t *for_scope(env_t *env, ast_t *ast) } return scope; } - case IntType: { + case BigIntType: { if (for_->vars) { if (for_->vars->next) code_err(for_->vars->next->ast, "This is too many variables for this loop"); @@ -495,7 +495,7 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name) switch (cls_type->tag) { case ArrayType: return NULL; case TableType: return NULL; - case BoolType: case IntType: case NumType: { + case BoolType: case IntType: case BigIntType: case NumType: { binding_t *b = get_binding(env, CORD_to_const_char_star(type_to_cord(cls_type))); assert(b); return get_binding(Match(b->type, TypeInfoType)->env, name); @@ -519,7 +519,6 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name) } default: break; } - code_err(self, "No such method!"); return NULL; } diff --git a/typecheck.c b/typecheck.c index 129a71da..3e7084c8 100644 --- a/typecheck.c +++ b/typecheck.c @@ -687,9 +687,8 @@ type_t *get_type(env_t *env, ast_t *ast) if (value_t->tag == ArrayType) { if (!indexing->index) return indexed_t; type_t *index_t = get_type(env, indexing->index); - if (index_t->tag == IntType) { + if (index_t->tag == IntType || index_t->tag == BigIntType) return Match(value_t, ArrayType)->item_type; - } code_err(indexing->index, "I only know how to index lists using integers, not %T", index_t); } else if (value_t->tag == TableType) { code_err(ast, "Tables use the table:get(key) method, not square bracket indexing like table[key]"); @@ -705,7 +704,8 @@ type_t *get_type(env_t *env, ast_t *ast) if (fn_type_t->tag == TypeInfoType) { type_t *t = Match(fn_type_t, TypeInfoType)->type; - if (t->tag == StructType || t->tag == IntType || t->tag == NumType || t->tag == TextType || t->tag == CStringType) + if (t->tag == StructType || t->tag == IntType || t->tag == BigIntType || t->tag == NumType + || t->tag == TextType || t->tag == CStringType) return t; // Constructor code_err(call->fn, "This is not a type that has a constructor"); } @@ -898,9 +898,9 @@ type_t *get_type(env_t *env, ast_t *ast) // Check for a binop method like plus() etc: switch (binop->op) { case BINOP_MULT: { - if ((lhs_t->tag == NumType || lhs_t->tag == IntType) && binding_works("scaled_by", binop->rhs, rhs_t, lhs_t, rhs_t)) + if (is_numeric_type(lhs_t) && binding_works("scaled_by", binop->rhs, rhs_t, lhs_t, rhs_t)) return rhs_t; - else if ((rhs_t->tag == NumType || rhs_t->tag == IntType) && binding_works("scaled_by", binop->lhs, lhs_t, rhs_t, lhs_t)) + else if (is_numeric_type(rhs_t) && binding_works("scaled_by", binop->lhs, lhs_t, rhs_t, lhs_t)) return lhs_t; else if (type_eq(lhs_t, rhs_t) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) return lhs_t; @@ -912,17 +912,17 @@ type_t *get_type(env_t *env, ast_t *ast) break; } case BINOP_DIVIDE: case BINOP_MOD: case BINOP_MOD1: { - if ((rhs_t->tag == NumType || rhs_t->tag == IntType) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) + if (is_numeric_type(rhs_t) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) return lhs_t; break; } case BINOP_LSHIFT: case BINOP_RSHIFT: { - if (rhs_t->tag == IntType && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) + if (is_int_type(rhs_t) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) return lhs_t; break; } case BINOP_POWER: { - if ((rhs_t->tag == NumType || rhs_t->tag == IntType) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) + if (is_numeric_type(rhs_t) && binding_works(binop_method_names[binop->op], binop->lhs, lhs_t, rhs_t, lhs_t)) return lhs_t; break; } @@ -944,7 +944,7 @@ type_t *get_type(env_t *env, ast_t *ast) if (type_eq(lhs_ptr->pointed, rhs_ptr->pointed)) return Type(PointerType, .pointed=lhs_ptr->pointed, .is_optional=lhs_ptr->is_optional || rhs_ptr->is_optional, .is_readonly=lhs_ptr->is_readonly || rhs_ptr->is_readonly); - } else if (lhs_t->tag == IntType && rhs_t->tag == IntType) { + } else if (is_int_type(lhs_t) && is_int_type(rhs_t)) { return get_math_type(env, ast, lhs_t, rhs_t); } code_err(ast, "I can't figure out the type of this `and` expression because the left side is a %T, but the right side is a %T", @@ -955,7 +955,7 @@ type_t *get_type(env_t *env, ast_t *ast) return lhs_t; } else if (lhs_t->tag == BoolType && (rhs_t->tag == AbortType || rhs_t->tag == ReturnType)) { return lhs_t; - } else if (lhs_t->tag == IntType && rhs_t->tag == IntType) { + } else if (is_int_type(lhs_t) && is_int_type(rhs_t)) { return get_math_type(env, ast, lhs_t, rhs_t); } else if (lhs_t->tag == PointerType) { auto lhs_ptr = Match(lhs_t, PointerType); @@ -974,7 +974,7 @@ type_t *get_type(env_t *env, ast_t *ast) case BINOP_XOR: { if (lhs_t->tag == BoolType && rhs_t->tag == BoolType) { return lhs_t; - } else if (lhs_t->tag == IntType && rhs_t->tag == IntType) { + } else if (is_int_type(lhs_t) && is_int_type(rhs_t)) { return get_math_type(env, ast, lhs_t, rhs_t); } @@ -1016,7 +1016,7 @@ type_t *get_type(env_t *env, ast_t *ast) type_t *value_t; type_t *iter_value_t = value_type(iter_t); switch (iter_value_t->tag) { - case IntType: value_t = iter_value_t; break; + case BigIntType: case IntType: value_t = iter_value_t; break; case ArrayType: value_t = Match(iter_value_t, ArrayType)->item_type; break; case TableType: value_t = Match(iter_value_t, TableType)->key_type; break; case FunctionType: case ClosureType: { diff --git a/types.c b/types.c index d71da0e3..f666f667 100644 --- a/types.c +++ b/types.c @@ -273,7 +273,10 @@ bool can_promote(type_t *actual, type_t *needed) if (actual->tag == NumType && needed->tag == IntType) return false; - if (actual->tag == IntType && needed->tag == NumType) + if (actual->tag == IntType && (needed->tag == NumType || needed->tag == BigIntType)) + return true; + + if (actual->tag == BigIntType && needed->tag == NumType) return true; if (actual->tag == IntType && needed->tag == IntType) { @@ -402,6 +405,16 @@ bool can_have_cycles(type_t *t) return _can_have_cycles(t, &seen); } +bool is_int_type(type_t *t) +{ + return t->tag == IntType || t->tag == BigIntType; +} + +bool is_numeric_type(type_t *t) +{ + return t->tag == IntType || t->tag == BigIntType || t->tag == NumType; +} + type_t *replace_type(type_t *t, type_t *target, type_t *replacement) { if (type_eq(t, target)) diff --git a/types.h b/types.h index 8c3abb75..94896498 100644 --- a/types.h +++ b/types.h @@ -141,6 +141,8 @@ bool can_send_over_channel(type_t *t); bool can_promote(type_t *actual, type_t *needed); bool can_leave_uninitialized(type_t *t); bool can_have_cycles(type_t *t); +bool is_int_type(type_t *t); +bool is_numeric_type(type_t *t); type_t *replace_type(type_t *t, type_t *target, type_t *replacement); size_t type_size(type_t *t); size_t type_align(type_t *t); -- cgit v1.2.3