Add some missing functionality for Bytes

This commit is contained in:
Bruce Hill 2024-11-04 01:12:37 -05:00
parent 81a180eda0
commit b69d14b894
4 changed files with 26 additions and 10 deletions

View File

@ -679,7 +679,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
type_t *lhs_t = get_type(env, update->lhs);
type_t *rhs_t = get_type(env, update->rhs);
if (!promote(env, &rhs, rhs_t, lhs_t)) {
if (update->rhs->tag == Int && lhs_t->tag == IntType)
if (update->rhs->tag == Int && (lhs_t->tag == IntType || lhs_t->tag == ByteType))
rhs = compile_int_to_type(env, update->rhs, lhs_t);
else if (!(lhs_t->tag == ArrayType && promote(env, &rhs, rhs_t, Match(lhs_t, ArrayType)->item_type)))
code_err(ast, "I can't do operations between %T and %T", lhs_t, rhs_t);
@ -1623,7 +1623,6 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
return code;
}
int64_t target_bits = (int64_t)Match(target, IntType)->bits;
OptionalInt_t int_val = Int$from_str(Match(ast, Int)->str);
if (int_val.small == 0)
code_err(ast, "Failed to parse this integer");
@ -1631,6 +1630,13 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
mpz_t i;
mpz_init_set_int(i, int_val);
if (target->tag == ByteType) {
if (mpz_cmp_si(i, UINT8_MAX) <= 0 && mpz_cmp_si(i, 0) >= 0)
return CORD_asprintf("(Byte_t)(%s)", Match(ast, Int)->str);
code_err(ast, "This integer cannot fit in a byte");
}
int64_t target_bits = (int64_t)Match(target, IntType)->bits;
switch (target_bits) {
case TYPE_IBITS64:
if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0)
@ -2075,7 +2081,7 @@ CORD compile(env_t *env, ast_t *ast)
// Special case for bit shifting by an integer literal:
if (binop->op == BINOP_LSHIFT || binop->op == BINOP_RSHIFT || binop->op == BINOP_ULSHIFT || binop->op == BINOP_URSHIFT) {
if (lhs_t->tag == IntType && rhs_t->tag == BigIntType && binop->rhs->tag == Int) {
if ((lhs_t->tag == IntType || lhs_t->tag == ByteType) && rhs_t->tag == BigIntType && binop->rhs->tag == Int) {
CORD shift_amount = compile_int_to_type(env, binop->rhs, lhs_t);
if (binop->op == BINOP_LSHIFT)
return CORD_all("(", lhs, " << ", shift_amount, ")");
@ -3024,7 +3030,7 @@ CORD compile(env_t *env, ast_t *ast)
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);
if (is_numeric_type(actual)) {
if (is_numeric_type(actual) || actual->tag == ByteType) {
return CORD_all(type_to_cord(actual), "_to_", type_to_cord(t), "(", arg_code, ")");
} else if (actual->tag == BoolType) {
if (t->tag == NumType) {
@ -3035,9 +3041,9 @@ CORD compile(env_t *env, ast_t *ast)
} else {
code_err(ast, "You cannot convert a %T to a %T this way.", actual, t);
}
} else if (t->tag == IntType) {
} else if (t->tag == IntType || t->tag == ByteType) {
type_t *actual = get_type(env, call->args->value);
if (is_numeric_type(actual)) {
if (is_numeric_type(actual) || actual->tag == ByteType) {
arg_t *args = new(arg_t, .name="i", .type=actual, .next=new(arg_t, .name="truncate", .type=Type(BoolType),
.default_val=FakeAST(Bool, false)));
CORD arg_code = compile_arguments(env, ast, args, call->args);
@ -3427,7 +3433,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 && index_t->tag != BigIntType)
if (index_t->tag != IntType && index_t->tag != BigIntType && index_t->tag != ByteType)
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);

View File

@ -1764,7 +1764,7 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn
else pos = key->end;
}
spaces(&pos);
whitespace(&pos);
ast_t *rhs = parse_infix_expr(ctx, pos, op_tightness[op] + 1);
if (!rhs) break;
pos = rhs->end;

View File

@ -13,6 +13,16 @@
PUREFUNC Text_t Byte$as_text(const Byte_t *b, bool colorize, const TypeInfo_t *type);
#define Byte_to_Int64(b, _) ((Int64_t)(b))
#define Byte_to_Int32(b, _) ((Int32_t)(b))
#define Byte_to_Int16(b, _) ((Int16_t)(b))
#define Byte_to_Int8(b, _) ((Int8_t)(b))
#define Int64_to_Byte(b, _) ((Byte_t)(b))
#define Int32_to_Byte(b, _) ((Byte_t)(b))
#define Int16_to_Byte(b, _) ((Byte_t)(b))
#define Int8_to_Byte(b, _) ((Byte_t)(b))
extern const Byte_t Byte$min;
extern const Byte_t Byte$max;

View File

@ -702,7 +702,7 @@ 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 || index_t->tag == BigIntType)
if (index_t->tag == IntType || index_t->tag == BigIntType || index_t->tag == ByteType)
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) {
@ -720,7 +720,7 @@ 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 == BigIntType || t->tag == NumType
|| t->tag == TextType || t->tag == CStringType || t->tag == DateTimeType)
|| t->tag == ByteType || t->tag == TextType || t->tag == CStringType || t->tag == DateTimeType)
return t; // Constructor
code_err(call->fn, "This is not a type that has a constructor");
}