Split BigIntType out of IntType and switch to using enums for the size
of ints/nums
This commit is contained in:
parent
8b94c2c7f1
commit
752ab8212c
4
ast.c
4
ast.c
@ -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))
|
||||
|
4
ast.h
4
ast.h
@ -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;
|
||||
|
125
compile.c
125
compile.c
@ -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);
|
||||
|
@ -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"},
|
||||
|
19
parse.c
19
parse.c
@ -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);
|
||||
}
|
||||
|
49
repl.c
49
repl.c
@ -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; \
|
||||
|
31
structs.c
31
structs.c
@ -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;
|
||||
}
|
||||
|
37
typecheck.c
37
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);
|
||||
|
57
types.c
57
types.c
@ -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);
|
||||
|
10
types.h
10
types.h
@ -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[]);
|
||||
|
Loading…
Reference in New Issue
Block a user