usize indexing only
This commit is contained in:
@@ -291,6 +291,7 @@ Ct_Binding :: struct {
|
||||
value: Ct_Value_Id,
|
||||
cell: Ct_Cell_Id,
|
||||
mutable: bool,
|
||||
open_integer: bool,
|
||||
}
|
||||
|
||||
Ct_Error_Refinement :: struct {
|
||||
@@ -473,9 +474,23 @@ ct_extend_place :: proc(
|
||||
return ct_add_place(state, base.cell, value_type, writable, extended[:])
|
||||
}
|
||||
|
||||
ct_bind_value :: proc(state: ^Ct_State, name: symbol.Id, value_type: types.Type, value: Ct_Value_Id, mutable: bool) {
|
||||
ct_bind_value :: proc(
|
||||
state: ^Ct_State,
|
||||
name: symbol.Id,
|
||||
value_type: types.Type,
|
||||
value: Ct_Value_Id,
|
||||
mutable: bool,
|
||||
open_integer := false,
|
||||
) {
|
||||
cell := ct_add_cell(state, value, mutable)
|
||||
append(&state.bindings, Ct_Binding{name=name, type=value_type, value=value, cell=cell, mutable=mutable})
|
||||
append(&state.bindings, Ct_Binding{
|
||||
name=name,
|
||||
type=value_type,
|
||||
value=value,
|
||||
cell=cell,
|
||||
mutable=mutable,
|
||||
open_integer=open_integer,
|
||||
})
|
||||
}
|
||||
|
||||
ct_pop_bindings :: proc(state: ^Ct_State, start: int) {
|
||||
@@ -581,6 +596,32 @@ ct_binding_value :: proc(state: ^Ct_State, index: int) -> Ct_Value_Id {
|
||||
return binding.value
|
||||
}
|
||||
|
||||
ct_contextualize_open_integer_binding :: proc(state: ^Ct_State, index: int, expected: types.Type) {
|
||||
if expected != types.USIZE || index < 0 || index >= len(state.bindings) ||
|
||||
!state.bindings[index].open_integer {
|
||||
return
|
||||
}
|
||||
value_id := ct_binding_value(state, index)
|
||||
if value_id == INVALID_CT_VALUE || int(value_id) >= len(state.values) {
|
||||
return
|
||||
}
|
||||
value := state.values[value_id]
|
||||
if value.kind != .Integer ||
|
||||
!fits_integer_type(value.integer, expected, state.checker.target) {
|
||||
return
|
||||
}
|
||||
value.type = expected
|
||||
contextual := ct_add_value(state, value)
|
||||
binding := &state.bindings[index]
|
||||
binding.type = expected
|
||||
binding.value = contextual
|
||||
binding.open_integer = false
|
||||
if binding.cell != INVALID_CT_CELL && int(binding.cell) < len(state.cells) &&
|
||||
state.cells[binding.cell].live {
|
||||
state.cells[binding.cell].value = contextual
|
||||
}
|
||||
}
|
||||
|
||||
ct_binding_place :: proc(state: ^Ct_State, index: int) -> Ct_Place_Id {
|
||||
if index < 0 || index >= len(state.bindings) {
|
||||
return INVALID_CT_PLACE
|
||||
@@ -1315,6 +1356,7 @@ ct_eval_expr :: proc(
|
||||
case .Name:
|
||||
if !symbol.is_valid(expr.qualifier) {
|
||||
if index, ok := ct_find_binding_index(state, expr.name); ok {
|
||||
ct_contextualize_open_integer_binding(state, index, expected)
|
||||
return ct_observe_value(state, ct_binding_value(state, index), expr.span)
|
||||
}
|
||||
if value, ok := current_comptime_value(checker, expr.name); ok {
|
||||
@@ -1452,16 +1494,19 @@ ct_eval_expr :: proc(
|
||||
}
|
||||
return ct_eval_field_value(state, base_id, expr.name, expr.span)
|
||||
case .Index:
|
||||
index_id, index_flow, index_ok := ct_eval_expr(state, expr.right, types.INVALID, depth+1)
|
||||
index_id, index_flow, index_ok := ct_eval_expr(state, expr.right, types.USIZE, depth+1)
|
||||
if !index_ok || index_flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, index_flow, index_ok
|
||||
}
|
||||
index_type := state.values[index_id].type
|
||||
index_representation := types.runtime_representation(index_type, store)
|
||||
index_literal := is_numeric_constant_expr(checker, expr.right)
|
||||
if !types.is_concrete_integer(index_representation) ||
|
||||
!index_literal && !can_implicitly_convert_type(checker, index_representation, types.USIZE) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "comptime index must be coercible to usize")
|
||||
if !types.equal(index_type, types.USIZE) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(
|
||||
state,
|
||||
.Not_Comptime,
|
||||
checker.ast_module.exprs[expr.right].span,
|
||||
"index must have type usize, got %s",
|
||||
type_label(checker, index_type),
|
||||
)
|
||||
}
|
||||
index_value, index_is_int := ct_integer_value(state, index_id)
|
||||
if !index_is_int || index_value < 0 || index_value > i128(0x7fff_ffff) {
|
||||
@@ -1962,16 +2007,19 @@ ct_eval_slice_expr :: proc(state: ^Ct_State, expr: ast.Expr, depth: int) -> (Ct_
|
||||
if bound == ast.INVALID_EXPR {
|
||||
continue
|
||||
}
|
||||
value, bound_flow, bound_ok := ct_eval_expr(state, bound, types.INVALID, depth+1)
|
||||
value, bound_flow, bound_ok := ct_eval_expr(state, bound, types.USIZE, depth+1)
|
||||
if !bound_ok || bound_flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, bound_flow, bound_ok
|
||||
}
|
||||
bound_type := state.values[value].type
|
||||
bound_representation := types.runtime_representation(bound_type, store)
|
||||
bound_literal := is_numeric_constant_expr(checker, bound)
|
||||
if !types.is_concrete_integer(bound_representation) ||
|
||||
!bound_literal && !can_implicitly_convert_type(checker, bound_representation, types.USIZE) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "slice bounds must be coercible to usize")
|
||||
if !types.equal(bound_type, types.USIZE) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(
|
||||
state,
|
||||
.Not_Comptime,
|
||||
checker.ast_module.exprs[bound].span,
|
||||
"slice bound must have type usize, got %s",
|
||||
type_label(checker, bound_type),
|
||||
)
|
||||
}
|
||||
integer, integer_ok := ct_integer_value(state, value)
|
||||
if !integer_ok || integer < 0 || integer > i128(0x7fff_ffff) {
|
||||
@@ -2352,6 +2400,16 @@ ct_eval_place :: proc(
|
||||
if !index_ok || index_flow.kind != .Normal {
|
||||
return INVALID_CT_PLACE, types.INVALID, false, index_flow, index_ok
|
||||
}
|
||||
index_type := state.values[index_value].type
|
||||
if !types.equal(index_type, types.USIZE) {
|
||||
return INVALID_CT_PLACE, types.INVALID, false, ct_flow(.Normal), ct_failf(
|
||||
state,
|
||||
.Not_Comptime,
|
||||
checker.ast_module.exprs[expr.right].span,
|
||||
"index must have type usize, got %s",
|
||||
type_label(checker, index_type),
|
||||
)
|
||||
}
|
||||
index_int, int_ok := ct_integer_value(state, index_value)
|
||||
if !int_ok || index_int < 0 || index_int > i128(0x7fff_ffff) {
|
||||
return INVALID_CT_PLACE, types.INVALID, false, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "comptime index must be a non-negative integer")
|
||||
@@ -4983,6 +5041,11 @@ ct_exec_statements :: proc(
|
||||
} else {
|
||||
declared := type_from_syntax(checker, statement.type, state.pkg, state.file, active_state=state)
|
||||
expected := declared if types.is_valid(declared) && !types.is_void(declared) else types.INVALID
|
||||
open_integer := false
|
||||
if !is_runtime_type(checker, declared) {
|
||||
constant := eval_integer_constant_in_context(checker, statement.expr, state.pkg, state.file)
|
||||
open_integer = constant.kind == .Value
|
||||
}
|
||||
value, expr_flow, expr_ok := ct_eval_expr(state, statement.expr, expected, depth+1)
|
||||
ok = expr_ok
|
||||
flow = expr_flow
|
||||
@@ -4991,7 +5054,14 @@ ct_exec_statements :: proc(
|
||||
value, ok = ct_coerce_value(state, value, expected, statement.span)
|
||||
}
|
||||
if ok && statement.name != checker.sink_symbol {
|
||||
ct_bind_value(state, statement.name, state.values[value].type, value, !statement.immutable)
|
||||
ct_bind_value(
|
||||
state,
|
||||
statement.name,
|
||||
state.values[value].type,
|
||||
value,
|
||||
!statement.immutable,
|
||||
open_integer=open_integer,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user