fix: bug hunt
This commit is contained in:
@@ -1499,15 +1499,37 @@ ct_eval_expr :: proc(
|
||||
case .Catch:
|
||||
return ct_eval_catch_expr(state, expr, expected, depth+1)
|
||||
case .Range:
|
||||
left, flow, ok := ct_eval_expr(state, expr.left, types.INVALID, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
child_hint := types.INVALID
|
||||
if types.is_range(expected, store) {
|
||||
child_hint = types.child_type(expected, store)
|
||||
}
|
||||
right, right_flow, right_ok := ct_eval_expr(state, expr.right, state.values[left].type, depth+1)
|
||||
if !right_ok || right_flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, right_flow, right_ok
|
||||
left_const := is_numeric_constant_expr(checker, expr.left)
|
||||
right_const := is_numeric_constant_expr(checker, expr.right)
|
||||
left, right: Ct_Value_Id
|
||||
flow: Ct_Flow
|
||||
ok: bool
|
||||
if left_const && !right_const && !types.is_valid(child_hint) {
|
||||
right, flow, ok = ct_eval_expr(state, expr.right, types.INVALID, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
}
|
||||
left, flow, ok = ct_eval_expr(state, expr.left, state.values[right].type, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
}
|
||||
} else {
|
||||
left, flow, ok = ct_eval_expr(state, expr.left, child_hint, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
}
|
||||
right_hint := child_hint if types.is_valid(child_hint) else state.values[left].type
|
||||
right, flow, ok = ct_eval_expr(state, expr.right, right_hint, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
}
|
||||
}
|
||||
child_type := types.widest(state.values[left].type, state.values[right].type)
|
||||
child_type := child_hint if types.is_valid(child_hint) else
|
||||
types.widest(state.values[left].type, state.values[right].type)
|
||||
if !types.is_concrete_integer(child_type) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, expr.span, "range bounds must be compatible concrete integers")
|
||||
}
|
||||
@@ -1905,10 +1927,15 @@ ct_eval_slice_expr :: proc(state: ^Ct_State, expr: ast.Expr, depth: int) -> (Ct_
|
||||
ct_eval_enum_literal :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Type, depth: int) -> (Ct_Value_Id, Ct_Flow, bool) {
|
||||
checker := state.checker
|
||||
store := &checker.module.types
|
||||
if types.is_tagged_union(expected, store) {
|
||||
index, field, found := find_struct_field(checker, expected, expr.name)
|
||||
literal_expected := expected
|
||||
optional_expected := types.is_optional(expected, store)
|
||||
if optional_expected {
|
||||
literal_expected = types.child_type(expected, store)
|
||||
}
|
||||
if types.is_tagged_union(literal_expected, store) {
|
||||
index, field, found := find_struct_field(checker, literal_expected, expr.name)
|
||||
if !found {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "unknown variant '.%s' on '%s'", symbol_text(checker, expr.name), type_label(checker, expected))
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "unknown variant '.%s' on '%s'", symbol_text(checker, expr.name), type_label(checker, literal_expected))
|
||||
}
|
||||
payload := INVALID_CT_VALUE
|
||||
if expr.left != ast.INVALID_EXPR {
|
||||
@@ -1921,23 +1948,31 @@ ct_eval_enum_literal :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.T
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), false
|
||||
}
|
||||
} else if !types.is_void(field.type) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "variant '.%s' on '%s' needs a payload", symbol_text(checker, expr.name), type_label(checker, expected))
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "variant '.%s' on '%s' needs a payload", symbol_text(checker, expr.name), type_label(checker, literal_expected))
|
||||
}
|
||||
start := u32(len(state.children))
|
||||
append(&state.children, payload)
|
||||
return ct_add_value(state, Ct_Value{kind=.Struct, type=expected, start=start, count=1, active=i64(index)}), ct_flow(.Normal), true
|
||||
result := ct_add_value(state, Ct_Value{kind=.Struct, type=literal_expected, start=start, count=1, active=i64(index)})
|
||||
if optional_expected {
|
||||
return ct_coerce_expr_value(state, result, expected, expr.span)
|
||||
}
|
||||
return result, ct_flow(.Normal), true
|
||||
}
|
||||
if expr.left != ast.INVALID_EXPR {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "'.%s{...}' requires a tagged-union context", symbol_text(checker, expr.name))
|
||||
}
|
||||
if !types.is_enum(expected, store) {
|
||||
if !types.is_enum(literal_expected, store) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "'.%s' requires an enum context", symbol_text(checker, expr.name))
|
||||
}
|
||||
member, ok := find_enum_member(checker, expected, expr.name)
|
||||
member, ok := find_enum_member(checker, literal_expected, expr.name)
|
||||
if !ok {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "unknown enum member '%s'", symbol_text(checker, expr.name))
|
||||
}
|
||||
return ct_add_value(state, Ct_Value{kind=.Integer, type=expected, integer=member.value}), ct_flow(.Normal), true
|
||||
result := ct_add_value(state, Ct_Value{kind=.Integer, type=literal_expected, integer=member.value})
|
||||
if optional_expected {
|
||||
return ct_coerce_expr_value(state, result, expected, expr.span)
|
||||
}
|
||||
return result, ct_flow(.Normal), true
|
||||
}
|
||||
|
||||
ct_eval_field_value :: proc(state: ^Ct_State, base_id: Ct_Value_Id, name: symbol.Id, span: source.Span) -> (Ct_Value_Id, Ct_Flow, bool) {
|
||||
@@ -3550,6 +3585,32 @@ ct_eval_call_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Type
|
||||
}
|
||||
}
|
||||
}
|
||||
named_type := types.find_named(
|
||||
&checker.module.types,
|
||||
u32(target_pkg),
|
||||
u32(expr.name),
|
||||
file=u32(expr_lookup_file(expr, state.file)),
|
||||
)
|
||||
named_item, named_ok := types.node(&checker.module.types, named_type)
|
||||
target := types.resolve_alias(named_type, &checker.module.types)
|
||||
if named_ok && named_item.kind == .Alias &&
|
||||
types.is_concrete_scalar(target) && !types.is_bool(target) {
|
||||
if len(expr.args) != 1 {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(
|
||||
state,
|
||||
.Not_Comptime,
|
||||
expr.span,
|
||||
"type alias '%s' expects 1 argument, got %d",
|
||||
symbol_text(checker, expr.name),
|
||||
len(expr.args),
|
||||
)
|
||||
}
|
||||
value, flow, ok := ct_eval_expr(state, expr.args[0], types.INVALID, depth+1)
|
||||
if !ok || flow.kind != .Normal {
|
||||
return INVALID_CT_VALUE, flow, ok
|
||||
}
|
||||
return ct_scalar_cast(state, value, target, expr.span)
|
||||
}
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "unresolved function '%s'", symbol_text(checker, expr.name))
|
||||
}
|
||||
if runtime_param_count(checker.ast_module.functions[template]) != 0 {
|
||||
|
||||
Reference in New Issue
Block a user