use crate::{
error::CompileError,
parse_tree::Literal,
type_system::{resolve_type, TypeId, TypeInfo},
};
use super::types::{create_enum_aggregate, create_tuple_aggregate};
use sway_ir::{Aggregate, Constant, Context, Type, Value};
use sway_types::span::Span;
pub(super) fn convert_literal_to_value(context: &mut Context, ast_literal: &Literal) -> Value {
match ast_literal {
Literal::U8(n) | Literal::Byte(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U16(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U32(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U64(n) => Constant::get_uint(context, 64, *n),
Literal::Numeric(n) => Constant::get_uint(context, 64, *n),
Literal::String(s) => Constant::get_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::get_bool(context, *b),
Literal::B256(bs) => Constant::get_b256(context, *bs),
}
}
pub(super) fn convert_literal_to_constant(ast_literal: &Literal) -> Constant {
match ast_literal {
Literal::U8(n) | Literal::Byte(n) => Constant::new_uint(64, *n as u64),
Literal::U16(n) => Constant::new_uint(64, *n as u64),
Literal::U32(n) => Constant::new_uint(64, *n as u64),
Literal::U64(n) => Constant::new_uint(64, *n),
Literal::Numeric(n) => Constant::new_uint(64, *n),
Literal::String(s) => Constant::new_string(s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::new_bool(*b),
Literal::B256(bs) => Constant::new_b256(*bs),
}
}
pub(super) fn convert_resolved_typeid(
context: &mut Context,
ast_type: &TypeId,
span: &Span,
) -> Result<Type, CompileError> {
convert_resolved_type(
context,
&resolve_type(*ast_type, span)
.map_err(|ty_err| CompileError::InternalOwned(format!("{ty_err:?}"), span.clone()))?,
span,
)
}
pub(super) fn convert_resolved_typeid_no_span(
context: &mut Context,
ast_type: &TypeId,
) -> Result<Type, CompileError> {
let msg = "unknown source location";
let span = crate::span::Span::from_string(msg.to_string());
convert_resolved_typeid(context, ast_type, &span)
}
fn convert_resolved_type(
context: &mut Context,
ast_type: &TypeInfo,
span: &Span,
) -> Result<Type, CompileError> {
macro_rules! reject_type {
($name_str:literal) => {{
return Err(CompileError::Internal(
concat!($name_str, " type cannot be resolved in IR."),
span.clone(),
));
}};
}
Ok(match ast_type {
TypeInfo::UnsignedInteger(_) => Type::Uint(64),
TypeInfo::Numeric => Type::Uint(64),
TypeInfo::Boolean => Type::Bool,
TypeInfo::Byte => Type::Uint(64),
TypeInfo::B256 => Type::B256,
TypeInfo::Str(n) => Type::String(*n),
TypeInfo::Struct { fields, .. } => super::types::get_aggregate_for_types(
context,
fields
.iter()
.map(|field| field.type_id)
.collect::<Vec<_>>()
.as_slice(),
)
.map(&Type::Struct)?,
TypeInfo::Enum { variant_types, .. } => {
create_enum_aggregate(context, variant_types.clone()).map(&Type::Struct)?
}
TypeInfo::Array(elem_type_id, count, _) => {
let elem_type = convert_resolved_typeid(context, elem_type_id, span)?;
Type::Array(Aggregate::new_array(context, elem_type, *count as u64))
}
TypeInfo::Tuple(fields) => {
if fields.is_empty() {
Type::Unit
} else {
let new_fields = fields.iter().map(|x| x.type_id).collect();
create_tuple_aggregate(context, new_fields).map(Type::Struct)?
}
}
TypeInfo::Custom { .. } => reject_type!("Custom"),
TypeInfo::SelfType { .. } => reject_type!("Self"),
TypeInfo::Contract => reject_type!("Contract"),
TypeInfo::ContractCaller { .. } => reject_type!("ContractCaller"),
TypeInfo::Unknown => reject_type!("Unknown"),
TypeInfo::UnknownGeneric { .. } => reject_type!("Generic"),
TypeInfo::Ref(..) => reject_type!("Ref"),
TypeInfo::ErrorRecovery => reject_type!("Error recovery"),
TypeInfo::Storage { .. } => reject_type!("Storage"),
})
}