add range constraint type

This commit is contained in:
2026-06-25 23:02:37 +02:00
parent c3208fdb61
commit 70a6d69d29
9 changed files with 222 additions and 40 deletions
+21 -10
View File
@@ -42,6 +42,7 @@ C_LONGDOUBLE :: Type(28)
BOOL :: Type(29)
FLOAT :: Type(30)
RANGE :: Type(31)
DYNAMIC_START :: Type(64)
@@ -57,6 +58,7 @@ Kind :: enum u8 {
Void,
Int_Constraint,
Float_Constraint,
Range_Constraint,
Scalar,
Array,
Pointer,
@@ -299,6 +301,8 @@ kind :: proc(value: Type, store: ^Store = nil) -> Kind {
return .Int_Constraint
case FLOAT:
return .Float_Constraint
case RANGE:
return .Range_Constraint
case BOOL:
return .Scalar
}
@@ -338,15 +342,17 @@ is_bool :: proc(value: Type) -> bool {
}
is_constraint :: proc(value: Type) -> bool {
return value == INT || value == FLOAT
return value == INT || value == FLOAT || value == RANGE
}
// constraint_target reports the concrete type a constraint binding takes for an
// inferred value, or INVALID if the value's numeric family is incompatible.
// FLOAT accepts integers by defaulting them to f64: a constant integer becomes a
// float literal in build_constant_expr, while a runtime integer then fails the
// cross-family f64 coercion in coerce_expr (the intended mismatch error).
constraint_target :: proc(constraint, inferred: Type) -> Type {
// constraint_target reports the concrete type a constraint binding (local, or a
// param/result monomorphized per call site) takes for an inferred value, or
// INVALID if the value's family is incompatible. FLOAT accepts integers by
// defaulting them to f64: a constant integer becomes a float literal in
// build_constant_expr, while a runtime integer then fails the cross-family f64
// coercion in coerce_expr (the intended mismatch error). RANGE accepts any range
// type, keeping its inferred element type.
constraint_target :: proc(constraint, inferred: Type, store: ^Store = nil) -> Type {
switch constraint {
case INT:
return inferred if is_concrete_integer(inferred) else INVALID
@@ -355,18 +361,22 @@ constraint_target :: proc(constraint, inferred: Type) -> Type {
return inferred
}
return F64 if is_concrete_integer(inferred) else INVALID
case RANGE:
return inferred if is_range(inferred, store) else INVALID
}
return INVALID
}
// constraint_accepts reports strict numeric-family membership, used when widening
// a constraint binding across assignments (no integer-to-float defaulting here).
constraint_accepts :: proc(constraint, concrete: Type) -> bool {
// constraint_accepts reports strict family membership, used when widening a
// constraint binding across assignments (no integer-to-float defaulting here).
constraint_accepts :: proc(constraint, concrete: Type, store: ^Store = nil) -> bool {
switch constraint {
case INT:
return is_concrete_integer(concrete)
case FLOAT:
return is_float(concrete)
case RANGE:
return is_range(concrete, store)
}
return false
}
@@ -1175,6 +1185,7 @@ name :: proc(value: Type) -> string {
case BOOL: return "bool"
case INT: return "int"
case FLOAT: return "float"
case RANGE: return "range"
case I8: return "i8"
case I16: return "i16"
case I32: return "i32"