use crate::checker::EnvResolve;
use syntax::types::{CompoundKind, SimpleKind, Symbol, Type};
use crate::checker::TaskState;
use crate::store::Store;
impl TaskState<'_> {
fn builtin_qualified_name(&mut self, store: &Store, type_name: &str) -> Symbol {
self.lookup_qualified_name(store, type_name)
.map(Symbol::from)
.unwrap_or_else(|| panic!("Builtin type {type_name} not found in store"))
}
fn builtin_type(&mut self, store: &Store, type_name: &str) -> Type {
if let Some(ty) = self.builtins.get(type_name) {
return ty.clone();
}
let qualified_name = self.builtin_qualified_name(store, type_name);
let ty = store
.get_type(&qualified_name)
.unwrap_or_else(|| panic!("Builtin type {type_name} not found in store"));
let body = match &ty {
Type::Forall { body, .. } => body.as_ref().clone(),
_ => ty.clone(),
};
self.builtins.insert(type_name.to_string(), body.clone());
body
}
pub fn type_unit(&self) -> Type {
Type::unit()
}
pub fn type_never(&self) -> Type {
Type::Never
}
pub fn type_int(&mut self) -> Type {
Type::Simple(SimpleKind::Int)
}
pub fn type_float(&mut self) -> Type {
Type::Simple(SimpleKind::Float64)
}
pub fn type_string(&mut self) -> Type {
Type::Simple(SimpleKind::String)
}
pub fn type_char(&mut self) -> Type {
Type::Simple(SimpleKind::Rune)
}
pub fn type_bool(&mut self) -> Type {
Type::Simple(SimpleKind::Bool)
}
pub fn type_complex128(&mut self) -> Type {
Type::Simple(SimpleKind::Complex128)
}
pub fn type_unknown(&mut self, store: &Store) -> Type {
self.builtin_type(store, "Unknown")
}
pub fn type_slice(&mut self, element_type: Type) -> Type {
Type::Compound {
kind: CompoundKind::Slice,
args: vec![element_type],
}
}
pub fn type_reference(&mut self, inner_type: Type) -> Type {
Type::Compound {
kind: CompoundKind::Ref,
args: vec![inner_type],
}
}
pub fn type_map(&mut self, key_type: Type, value_type: Type) -> Type {
Type::Compound {
kind: CompoundKind::Map,
args: vec![key_type, value_type],
}
}
pub fn type_result(&mut self, store: &Store, ok_type: Type, error_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "Result"),
params: vec![ok_type, error_type],
underlying_ty: None,
}
}
pub fn type_option(&mut self, store: &Store, some_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "Option"),
params: vec![some_type],
underlying_ty: None,
}
}
pub fn type_panic_value(&mut self, store: &Store) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "PanicValue"),
params: vec![],
underlying_ty: None,
}
}
pub fn type_range(&mut self, store: &Store, element_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "Range"),
params: vec![element_type],
underlying_ty: None,
}
}
pub fn type_range_inclusive(&mut self, store: &Store, element_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "RangeInclusive"),
params: vec![element_type],
underlying_ty: None,
}
}
pub fn type_range_from(&mut self, store: &Store, element_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "RangeFrom"),
params: vec![element_type],
underlying_ty: None,
}
}
pub fn type_range_to(&mut self, store: &Store, element_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "RangeTo"),
params: vec![element_type],
underlying_ty: None,
}
}
pub fn type_range_to_inclusive(&mut self, store: &Store, element_type: Type) -> Type {
Type::Nominal {
id: self.builtin_qualified_name(store, "RangeToInclusive"),
params: vec![element_type],
underlying_ty: None,
}
}
pub fn is_generic_container_with_interface(&self, store: &Store, ty: &Type) -> bool {
let resolved = ty.resolve_in(&self.env);
let Type::Nominal { id, params, .. } = &resolved else {
return false;
};
if id != "prelude.Option" && id != "prelude.Result" {
return false;
}
params.iter().any(|p| {
if let Type::Nominal { id, .. } = p.resolve_in(&self.env) {
store.get_interface(&id).is_some() || id.starts_with("go:")
} else {
false
}
})
}
}