From b69d14b89492919dc5c1669d2c569ee3baf1bbb0 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 4 Nov 2024 01:12:37 -0500 Subject: [PATCH] Add some missing functionality for Bytes --- compile.c | 20 +++++++++++++------- parse.c | 2 +- stdlib/bytes.h | 10 ++++++++++ typecheck.c | 4 ++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/compile.c b/compile.c index 1cd0c2d..5a481e0 100644 --- a/compile.c +++ b/compile.c @@ -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); diff --git a/parse.c b/parse.c index 0130673..94f0cd0 100644 --- a/parse.c +++ b/parse.c @@ -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; diff --git a/stdlib/bytes.h b/stdlib/bytes.h index 2a92f65..f073979 100644 --- a/stdlib/bytes.h +++ b/stdlib/bytes.h @@ -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; diff --git a/typecheck.c b/typecheck.c index e525595..44068f5 100644 --- a/typecheck.c +++ b/typecheck.c @@ -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"); }