Skip to main content

mago_codex/ttype/
shared.rs

1//! A collection of shared, static, and lazily-initialized `TAtomic` types.
2//!
3//! This module provides canonical, reusable instances for common PHP types.
4//! Using these constants avoids repeated allocations for frequently used types.
5
6use std::sync::Arc;
7use std::sync::LazyLock;
8
9use mago_word::empty_word;
10use mago_word::word;
11
12use crate::ttype::atomic::TAtomic;
13use crate::ttype::atomic::array::TArray;
14use crate::ttype::atomic::array::keyed::TKeyedArray;
15use crate::ttype::atomic::callable::TCallable;
16use crate::ttype::atomic::callable::TCallableSignature;
17use crate::ttype::atomic::iterable::TIterable;
18use crate::ttype::atomic::mixed::TMixed;
19use crate::ttype::atomic::object::TObject;
20use crate::ttype::atomic::resource::TResource;
21use crate::ttype::atomic::scalar::TScalar;
22use crate::ttype::atomic::scalar::int::TInteger;
23use crate::ttype::atomic::scalar::string::TString;
24use crate::ttype::atomic::scalar::string::TStringLiteral;
25use crate::ttype::get_arraykey;
26use crate::ttype::get_mixed;
27
28use super::atomic::scalar::string::TStringCasing;
29
30/// A static `TAtomic` representing the integer literal `1`.
31pub const ONE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::literal_int(1));
32/// A static `TAtomic` representing the integer literal `0`.
33pub const ZERO_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::literal_int(0));
34/// A static `TAtomic` representing the integer literal `-1`.
35pub const MINUS_ONE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::literal_int(-1));
36/// A static `TAtomic` representing the general `int` type.
37pub const INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::int());
38/// A static `TAtomic` representing a positive integer (`positive-int` or `int<1, max>`).
39pub const POSITIVE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Integer(TInteger::positive()));
40/// A static `TAtomic` representing a non-positive integer (`non-positive-int` or `int<min, 0>`).
41pub const NON_POSITIVE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Integer(TInteger::non_positive()));
42/// A static `TAtomic` representing a negative integer (`negative-int` or `int<min, -1>`).
43pub const NEGATIVE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Integer(TInteger::negative()));
44/// A static `TAtomic` representing a non-negative integer (`non-negative-int` or `int<0, max>`).
45pub const NON_NEGATIVE_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Integer(TInteger::non_negative()));
46/// A static `TAtomic` representing a `literal-int` where the value is unknown.
47pub const UNSPECIFIED_LITERAL_INT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Integer(TInteger::UnspecifiedLiteral));
48/// A static `TAtomic` for the general `string` type.
49pub const STRING_ATOMIC: &TAtomic =
50    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, false, false, TStringCasing::Unspecified)));
51/// A static `TAtomic` for a `lowercase-string`.
52pub const LOWERCASE_STRING_ATOMIC: &TAtomic =
53    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, false, false, TStringCasing::Lowercase)));
54/// A static `TAtomic` for a `uppercase-string`.
55pub const UPPERCASE_STRING_ATOMIC: &TAtomic =
56    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, false, false, TStringCasing::Uppercase)));
57/// A static `TAtomic` for a `non-empty-string`.
58pub const NON_EMPTY_STRING_ATOMIC: &TAtomic =
59    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, true, false, TStringCasing::Unspecified)));
60/// A static `TAtomic` for a `non-empty-lowercase-string`.
61pub const NON_EMPTY_LOWERCASE_STRING_ATOMIC: &TAtomic =
62    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, true, false, TStringCasing::Lowercase)));
63/// A static `TAtomic` for a `non-empty-uppercase-string`.
64pub const NON_EMPTY_UPPERCASE_STRING_ATOMIC: &TAtomic =
65    &TAtomic::Scalar(TScalar::String(TString::new(None, false, false, true, false, TStringCasing::Uppercase)));
66/// A static `TAtomic` for a `truthy-string`.
67pub const TRUTHY_STRING_ATOMIC: &TAtomic =
68    &TAtomic::Scalar(TScalar::String(TString::new(None, false, true, false, false, TStringCasing::Unspecified)));
69/// A static `TAtomic` for a `truthy-lowercase-string`.
70pub const TRUTHY_LOWERCASE_STRING_ATOMIC: &TAtomic =
71    &TAtomic::Scalar(TScalar::String(TString::new(None, false, true, false, false, TStringCasing::Lowercase)));
72/// A static `TAtomic` for a `truthy-uppercase-string`.
73pub const TRUTHY_UPPERCASE_STRING_ATOMIC: &TAtomic =
74    &TAtomic::Scalar(TScalar::String(TString::new(None, false, true, false, false, TStringCasing::Uppercase)));
75/// A static `TAtomic` for a `numeric-string`.
76pub const CALLABLE_STRING_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::String(TString::callable()));
77pub const LOWERCASE_CALLABLE_STRING_ATOMIC: &TAtomic =
78    &TAtomic::Scalar(TScalar::String(TString::callable_with_casing(TStringCasing::Lowercase)));
79pub const UPPERCASE_CALLABLE_STRING_ATOMIC: &TAtomic =
80    &TAtomic::Scalar(TScalar::String(TString::callable_with_casing(TStringCasing::Uppercase)));
81pub const NUMERIC_STRING_ATOMIC: &TAtomic =
82    &TAtomic::Scalar(TScalar::String(TString::new(None, true, false, false, false, TStringCasing::Unspecified)));
83/// A static `TAtomic` for a `numeric-string` that is also `truthy`.
84pub const NUMERIC_TRUTHY_STRING_ATOMIC: &TAtomic =
85    &TAtomic::Scalar(TScalar::String(TString::new(None, true, true, false, false, TStringCasing::Unspecified)));
86/// A static `TAtomic` representing the `class-string` type.
87pub const CLASS_STRING_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::class_string());
88/// A static `TAtomic` representing the `float` type.
89pub const FLOAT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::float());
90/// A static `TAtomic` representing the `literal-float` type (unspecified literal).
91pub const UNSPECIFIED_LITERAL_FLOAT_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::unspecified_literal_float());
92/// A static `TAtomic` representing the `mixed` type.
93pub const MIXED_ATOMIC: &TAtomic = &TAtomic::Mixed(TMixed::new());
94/// A static `TAtomic` representing a `mixed` type that originates from an `isset()` check inside a loop.
95pub const ISSET_FROM_LOOP_MIXED_ATOMIC: &TAtomic = &TAtomic::Mixed(TMixed::isset_from_loop());
96/// A static `TAtomic` representing the `never` type, which indicates an impossible state.
97pub const NEVER_ATOMIC: &TAtomic = &TAtomic::Never;
98/// A static `TAtomic` representing any "truthy" value.
99pub const TRUTHY_MIXED_ATOMIC: &TAtomic = &TAtomic::Mixed(TMixed::truthy());
100/// A static `TAtomic` representing the `resource` type.
101pub const RESOURCE_ATOMIC: &TAtomic = &TAtomic::Resource(TResource::new(None));
102/// A static `TAtomic` representing an open `resource`.
103pub const OPEN_RESOURCE_ATOMIC: &TAtomic = &TAtomic::Resource(TResource::open());
104/// A static `TAtomic` representing a closed `resource`.
105pub const CLOSED_RESOURCE_ATOMIC: &TAtomic = &TAtomic::Resource(TResource::closed());
106/// A static `TAtomic` used as a temporary placeholder during type reconciliation.
107pub const PLACEHOLDER_ATOMIC: &TAtomic = &TAtomic::Placeholder;
108/// A static `TAtomic` representing the `void` type.
109pub const VOID_ATOMIC: &TAtomic = &TAtomic::Void;
110/// A static `TAtomic` representing the `null` type.
111pub const NULL_ATOMIC: &TAtomic = &TAtomic::Null;
112/// A static `TAtomic` representing the `array-key` type (`int|string`).
113pub const ARRAYKEY_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::ArrayKey);
114/// A static `TAtomic` representing the `bool` type.
115pub const BOOL_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::bool());
116/// A static `TAtomic` representing the literal `false` type.
117pub const FALSE_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::r#false());
118/// A static `TAtomic` representing the literal `true` type.
119pub const TRUE_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::r#true());
120/// A static `TAtomic` representing the general `object` type.
121pub const OBJECT_ATOMIC: &TAtomic = &TAtomic::Object(TObject::Any);
122/// A static `TAtomic` representing the `numeric` type (`int|float|numeric-string`).
123pub const NUMERIC_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Numeric);
124/// A static `TAtomic` representing an empty string literal (`""`).
125pub static EMPTY_STRING_ATOMIC: LazyLock<TAtomic> = LazyLock::new(|| {
126    TAtomic::Scalar(TScalar::String(TString {
127        literal: Some(TStringLiteral::Value(empty_word())),
128        is_numeric: false,
129        is_truthy: false,
130        is_non_empty: false,
131        is_callable: false,
132        casing: TStringCasing::Unspecified,
133    }))
134});
135/// A static `TAtomic` representing a `literal-string` where the value is unknown.
136pub const UNSPECIFIED_LITERAL_STRING_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::unspecified_literal_string(false));
137/// A static `TAtomic` representing a non-empty `literal-string` where the value is unknown.
138pub const NON_EMPTY_UNSPECIFIED_LITERAL_STRING_ATOMIC: &TAtomic =
139    &TAtomic::Scalar(TScalar::unspecified_literal_string(true));
140/// A static `TAtomic` representing the `scalar` type (`int|float|string|bool`).
141pub const SCALAR_ATOMIC: &TAtomic = &TAtomic::Scalar(TScalar::Generic);
142
143/// A lazily-initialized static `TAtomic` for a mixed iterable (`iterable<mixed, mixed>`).
144pub static MIXED_ITERABLE_ATOMIC: LazyLock<TAtomic> = LazyLock::new(|| {
145    TAtomic::Iterable(TIterable {
146        key_type: Arc::new(get_mixed()),
147        value_type: Arc::new(get_mixed()),
148        intersection_types: None,
149    })
150});
151
152/// A lazily-initialized static `TAtomic` for an empty array (`array<never, never>`).
153pub static EMPTY_KEYED_ARRAY_ATOMIC: LazyLock<TAtomic> =
154    LazyLock::new(|| TAtomic::Array(TArray::Keyed(TKeyedArray::new())));
155/// A lazily-initialized static `TAtomic` for a mixed array (`array<array-key, mixed>`).
156pub static MIXED_KEYED_ARRAY_ATOMIC: LazyLock<TAtomic> = LazyLock::new(|| {
157    TAtomic::Array(TArray::Keyed(TKeyedArray::new_with_parameters(Arc::new(get_arraykey()), Arc::new(get_mixed()))))
158});
159/// A lazily-initialized static `TAtomic` for a mixed callable (`callable`).
160pub static MIXED_CALLABLE_ATOMIC: LazyLock<TAtomic> =
161    LazyLock::new(|| TAtomic::Callable(TCallable::Signature(TCallableSignature::mixed(false))));
162/// A lazily-initialized static `TAtomic` for a mixed closure (`Closure`).
163pub static MIXED_CLOSURE_ATOMIC: LazyLock<TAtomic> =
164    LazyLock::new(|| TAtomic::Callable(TCallable::Signature(TCallableSignature::mixed(true))));
165
166/// A static slice of atomics representing the union type `int|float`.
167pub const INT_FLOAT_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Scalar(TScalar::int()), TAtomic::Scalar(TScalar::float())];
168/// A static slice of atomics representing the union type `int|string`.
169pub const INT_STRING_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Scalar(TScalar::int()), TAtomic::Scalar(TScalar::string())];
170/// A static slice of atomics representing the union type `null|scalar`.
171pub const NULL_SCALAR_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Null, TAtomic::Scalar(TScalar::Generic)];
172/// A static slice of atomics representing the union type `null|string`.
173pub const NULL_STRING_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Null, TAtomic::Scalar(TScalar::string())];
174/// A static slice of atomics representing the union type `null|int`.
175pub const NULL_INT_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Null, TAtomic::Scalar(TScalar::int())];
176/// A static slice of atomics representing the union type `null|float`.
177pub const NULL_FLOAT_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Null, TAtomic::Scalar(TScalar::float())];
178/// A static slice of atomics representing the union type `null|object`.
179pub const NULL_OBJECT_ATOMIC_SLICE: &[TAtomic] = &[TAtomic::Null, TAtomic::Object(TObject::Any)];
180
181/// A static slice of atomics representing the union type `-1|0|1`, commonly
182/// returned by comparison operations like the spaceship operator (`<=>`).
183pub const SIGNUM_RESULT_SLICE: &[TAtomic] = &[
184    TAtomic::Scalar(TScalar::literal_int(-1)),
185    TAtomic::Scalar(TScalar::literal_int(0)),
186    TAtomic::Scalar(TScalar::literal_int(1)),
187];
188
189pub static EMPTY_SCALAR_ATOMIC_SLICE: LazyLock<[TAtomic; 5]> = LazyLock::new(|| {
190    [
191        TAtomic::Scalar(TScalar::literal_int(0)),
192        TAtomic::Scalar(TScalar::literal_float(0.0)),
193        TAtomic::Scalar(TScalar::literal_string(word("0"))),
194        EMPTY_STRING_ATOMIC.clone(),
195        TAtomic::Scalar(TScalar::r#false()),
196    ]
197});
198
199pub static EMPTY_ATOMIC_SLICE: LazyLock<[TAtomic; 7]> = LazyLock::new(|| {
200    [
201        TAtomic::Null,
202        TAtomic::Scalar(TScalar::literal_int(0)),
203        TAtomic::Scalar(TScalar::literal_float(0.0)),
204        TAtomic::Scalar(TScalar::literal_string(word("0"))),
205        EMPTY_STRING_ATOMIC.clone(),
206        TAtomic::Scalar(TScalar::r#false()),
207        EMPTY_KEYED_ARRAY_ATOMIC.clone(),
208    ]
209});