2024-11-05 19:38:26 -05:00
|
|
|
//! Value types and conflict handling.
|
2024-06-24 04:02:44 -04:00
|
|
|
use std::{
|
2024-08-17 04:06:13 -04:00
|
|
|
cmp::Ordering,
|
|
|
|
collections::HashMap,
|
2024-06-24 04:02:44 -04:00
|
|
|
fmt::{self, Display, Formatter},
|
|
|
|
};
|
2024-03-06 22:15:35 -05:00
|
|
|
|
2024-06-04 14:47:15 -04:00
|
|
|
use serde::{Deserialize, Serialize};
|
2024-03-20 08:36:18 -04:00
|
|
|
|
2025-02-05 19:12:26 -05:00
|
|
|
use crate::instruction::TypeCode;
|
|
|
|
|
2024-07-15 15:49:34 -04:00
|
|
|
/// Description of a kind of value.
|
2025-02-08 05:56:49 -05:00
|
|
|
#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "Type", content = "Value")]
|
2024-02-28 21:04:38 -05:00
|
|
|
pub enum Type {
|
|
|
|
Boolean,
|
2024-08-16 17:07:49 -04:00
|
|
|
Byte,
|
|
|
|
Character,
|
|
|
|
Enum(EnumType),
|
2024-02-28 21:04:38 -05:00
|
|
|
Float,
|
2025-02-08 05:56:49 -05:00
|
|
|
Function(FunctionType),
|
|
|
|
Generic(GenericType),
|
2024-02-28 21:04:38 -05:00
|
|
|
Integer,
|
2025-02-07 15:37:48 -05:00
|
|
|
List(TypeCode),
|
2025-02-08 05:56:49 -05:00
|
|
|
Map(Vec<Type>),
|
|
|
|
#[default]
|
2024-11-09 21:40:33 -05:00
|
|
|
None,
|
2025-02-08 05:56:49 -05:00
|
|
|
Range(Box<Type>),
|
2024-12-17 03:22:44 -05:00
|
|
|
SelfFunction,
|
2024-11-27 19:43:50 -05:00
|
|
|
String,
|
2024-08-13 13:28:22 -04:00
|
|
|
Struct(StructType),
|
2025-02-08 05:56:49 -05:00
|
|
|
Tuple(Vec<Type>),
|
2024-02-28 21:04:38 -05:00
|
|
|
}
|
|
|
|
|
2024-03-06 12:15:03 -05:00
|
|
|
impl Type {
|
2025-02-08 05:56:49 -05:00
|
|
|
pub fn function<T: Into<Vec<u16>>, U: Into<Vec<Type>>>(
|
|
|
|
type_parameters: T,
|
|
|
|
value_parameters: U,
|
|
|
|
return_type: Type,
|
|
|
|
) -> Self {
|
|
|
|
Type::Function(FunctionType {
|
|
|
|
type_parameters: type_parameters.into(),
|
|
|
|
value_parameters: value_parameters.into(),
|
|
|
|
return_type: Box::new(return_type),
|
|
|
|
})
|
2024-12-04 13:31:02 -05:00
|
|
|
}
|
|
|
|
|
2025-02-05 19:12:26 -05:00
|
|
|
pub fn type_code(&self) -> TypeCode {
|
|
|
|
match self {
|
|
|
|
Type::Boolean => TypeCode::BOOLEAN,
|
|
|
|
Type::Byte => TypeCode::BYTE,
|
|
|
|
Type::Character => TypeCode::CHARACTER,
|
|
|
|
Type::Float => TypeCode::FLOAT,
|
|
|
|
Type::Integer => TypeCode::INTEGER,
|
|
|
|
Type::None => TypeCode::NONE,
|
|
|
|
Type::String => TypeCode::STRING,
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::List { .. } => TypeCode::LIST,
|
|
|
|
Type::Function { .. } => TypeCode::FUNCTION,
|
2025-02-05 19:12:26 -05:00
|
|
|
_ => todo!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-13 10:47:24 -04:00
|
|
|
/// Returns a concrete type, either the type itself or the concrete type of a generic type.
|
|
|
|
pub fn concrete_type(&self) -> &Type {
|
2025-02-08 05:56:49 -05:00
|
|
|
if let Type::Generic(GenericType {
|
2024-08-20 02:25:22 -04:00
|
|
|
concrete_type: Some(concrete_type),
|
|
|
|
..
|
2025-02-08 05:56:49 -05:00
|
|
|
}) = self
|
2024-08-20 02:25:22 -04:00
|
|
|
{
|
|
|
|
concrete_type.concrete_type()
|
|
|
|
} else {
|
|
|
|
self
|
2024-07-13 10:47:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that the type is compatible with another type.
|
2024-03-17 00:49:01 -04:00
|
|
|
pub fn check(&self, other: &Type) -> Result<(), TypeConflict> {
|
2024-07-13 10:47:24 -04:00
|
|
|
match (self.concrete_type(), other.concrete_type()) {
|
2025-02-08 17:36:30 -05:00
|
|
|
(Type::Boolean, Type::Boolean)
|
2024-08-20 11:40:37 -04:00
|
|
|
| (Type::Byte, Type::Byte)
|
|
|
|
| (Type::Character, Type::Character)
|
2024-03-06 12:15:03 -05:00
|
|
|
| (Type::Float, Type::Float)
|
|
|
|
| (Type::Integer, Type::Integer)
|
2024-11-10 19:28:21 -05:00
|
|
|
| (Type::None, Type::None)
|
2024-08-20 18:48:25 -04:00
|
|
|
| (Type::String { .. }, Type::String { .. }) => return Ok(()),
|
2024-06-19 00:05:58 -04:00
|
|
|
(
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::Generic(GenericType {
|
2024-06-19 00:05:58 -04:00
|
|
|
concrete_type: left,
|
|
|
|
..
|
2025-02-08 05:56:49 -05:00
|
|
|
}),
|
|
|
|
Type::Generic(GenericType {
|
2024-06-19 00:05:58 -04:00
|
|
|
concrete_type: right,
|
|
|
|
..
|
2025-02-08 05:56:49 -05:00
|
|
|
}),
|
2024-06-19 00:05:58 -04:00
|
|
|
) => match (left, right) {
|
2024-06-17 17:38:24 -04:00
|
|
|
(Some(left), Some(right)) => {
|
2024-07-12 10:20:52 -04:00
|
|
|
if left.check(right).is_ok() {
|
2024-06-17 17:38:24 -04:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(None, None) => {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
},
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Generic(GenericType { concrete_type, .. }), other)
|
|
|
|
| (other, Type::Generic(GenericType { concrete_type, .. })) => {
|
2024-06-19 00:05:58 -04:00
|
|
|
if let Some(concrete_type) = concrete_type {
|
|
|
|
if other == concrete_type.as_ref() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-13 13:28:22 -04:00
|
|
|
(Type::Struct(left_struct_type), Type::Struct(right_struct_type)) => {
|
|
|
|
if left_struct_type == right_struct_type {
|
2024-03-20 01:29:07 -04:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
2024-11-27 19:43:50 -05:00
|
|
|
(Type::List(left_type), Type::List(right_type)) => {
|
2025-02-07 15:37:48 -05:00
|
|
|
if left_type != right_type {
|
2024-06-17 11:02:13 -04:00
|
|
|
return Err(TypeConflict {
|
|
|
|
actual: other.clone(),
|
|
|
|
expected: self.clone(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(());
|
|
|
|
}
|
2024-12-04 13:31:02 -05:00
|
|
|
(Type::Function(left_function_type), Type::Function(right_function_type)) => {
|
|
|
|
let FunctionType {
|
2024-06-17 10:10:06 -04:00
|
|
|
type_parameters: left_type_parameters,
|
|
|
|
value_parameters: left_value_parameters,
|
2024-03-20 08:36:18 -04:00
|
|
|
return_type: left_return,
|
2025-02-08 05:56:49 -05:00
|
|
|
} = left_function_type;
|
2024-12-04 13:31:02 -05:00
|
|
|
let FunctionType {
|
2024-06-17 10:10:06 -04:00
|
|
|
type_parameters: right_type_parameters,
|
|
|
|
value_parameters: right_value_parameters,
|
2024-03-20 08:36:18 -04:00
|
|
|
return_type: right_return,
|
2025-02-08 05:56:49 -05:00
|
|
|
} = right_function_type;
|
2024-12-04 13:31:02 -05:00
|
|
|
|
2024-10-12 20:19:21 -04:00
|
|
|
if left_return != right_return
|
2024-08-17 10:07:38 -04:00
|
|
|
|| left_type_parameters != right_type_parameters
|
|
|
|
|| left_value_parameters != right_value_parameters
|
|
|
|
{
|
2024-08-16 17:07:49 -04:00
|
|
|
return Err(TypeConflict {
|
|
|
|
actual: other.clone(),
|
|
|
|
expected: self.clone(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-08-17 10:07:38 -04:00
|
|
|
return Ok(());
|
|
|
|
}
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Range(left_type), Type::Range(right_type)) => {
|
2024-08-17 10:07:38 -04:00
|
|
|
if left_type == right_type {
|
2024-03-20 01:29:07 -04:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
2024-03-06 12:15:03 -05:00
|
|
|
}
|
2024-03-20 01:29:07 -04:00
|
|
|
|
|
|
|
Err(TypeConflict {
|
|
|
|
actual: other.clone(),
|
|
|
|
expected: self.clone(),
|
|
|
|
})
|
2024-03-06 12:15:03 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 22:15:35 -05:00
|
|
|
impl Display for Type {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
match self {
|
2024-03-23 17:07:41 -04:00
|
|
|
Type::Boolean => write!(f, "bool"),
|
2024-08-16 17:07:49 -04:00
|
|
|
Type::Byte => write!(f, "byte"),
|
|
|
|
Type::Character => write!(f, "char"),
|
2024-08-17 10:07:38 -04:00
|
|
|
Type::Enum(EnumType { name, .. }) => write!(f, "{name}"),
|
2024-03-06 22:15:35 -05:00
|
|
|
Type::Float => write!(f, "float"),
|
2024-08-16 17:07:49 -04:00
|
|
|
Type::Function(function_type) => write!(f, "{function_type}"),
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::Generic(GenericType { concrete_type, .. }) => {
|
2024-06-26 11:35:39 -04:00
|
|
|
match concrete_type.clone().map(|r#box| *r#box) {
|
2025-02-08 05:56:49 -05:00
|
|
|
Some(Type::Generic(GenericType {
|
|
|
|
identifier_index, ..
|
|
|
|
})) => write!(f, "C_{identifier_index}"),
|
2024-06-26 11:35:39 -04:00
|
|
|
Some(concrete_type) => write!(f, "implied to be {concrete_type}"),
|
|
|
|
None => write!(f, "unknown"),
|
2024-06-17 17:38:24 -04:00
|
|
|
}
|
|
|
|
}
|
2024-03-23 17:07:41 -04:00
|
|
|
Type::Integer => write!(f, "int"),
|
2024-11-27 19:43:50 -05:00
|
|
|
Type::List(item_type) => write!(f, "[{item_type}]"),
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::Map(pairs) => {
|
2024-08-17 10:07:38 -04:00
|
|
|
write!(f, "map ")?;
|
|
|
|
|
|
|
|
write!(f, "{{")?;
|
|
|
|
|
2025-02-08 05:56:49 -05:00
|
|
|
for (index, r#type) in pairs.iter().enumerate() {
|
|
|
|
write!(f, "???: {type}")?;
|
2024-08-17 10:07:38 -04:00
|
|
|
|
|
|
|
if index != pairs.len() - 1 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "}}")
|
|
|
|
}
|
2024-11-09 21:40:33 -05:00
|
|
|
Type::None => write!(f, "none"),
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::Range(r#type) => write!(f, "{type} range"),
|
2024-12-17 03:22:44 -05:00
|
|
|
Type::SelfFunction => write!(f, "self"),
|
2024-11-27 19:43:50 -05:00
|
|
|
Type::String => write!(f, "str"),
|
2024-08-20 00:15:19 -04:00
|
|
|
Type::Struct(struct_type) => write!(f, "{struct_type}"),
|
2025-02-08 05:56:49 -05:00
|
|
|
Type::Tuple(fields) => {
|
2024-12-10 08:04:47 -05:00
|
|
|
write!(f, "(")?;
|
2024-06-24 04:02:44 -04:00
|
|
|
|
2024-12-10 08:04:47 -05:00
|
|
|
for (index, r#type) in fields.iter().enumerate() {
|
|
|
|
if index > 0 {
|
|
|
|
write!(f, ", ")?;
|
2024-06-24 04:16:05 -04:00
|
|
|
}
|
2024-06-24 04:02:44 -04:00
|
|
|
|
2024-12-10 08:04:47 -05:00
|
|
|
write!(f, "{type}")?;
|
2024-08-23 12:16:56 -04:00
|
|
|
}
|
2024-12-10 08:04:47 -05:00
|
|
|
|
|
|
|
write!(f, ")")
|
2024-06-24 04:02:44 -04:00
|
|
|
}
|
2024-08-16 17:07:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-08 21:26:49 -05:00
|
|
|
|
2024-08-17 10:07:38 -04:00
|
|
|
impl PartialOrd for Type {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for Type {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
match (self, other) {
|
|
|
|
(Type::Boolean, Type::Boolean) => Ordering::Equal,
|
|
|
|
(Type::Boolean, _) => Ordering::Greater,
|
|
|
|
(Type::Byte, Type::Byte) => Ordering::Equal,
|
|
|
|
(Type::Byte, _) => Ordering::Greater,
|
|
|
|
(Type::Character, Type::Character) => Ordering::Equal,
|
|
|
|
(Type::Character, _) => Ordering::Greater,
|
|
|
|
(Type::Enum(left_enum), Type::Enum(right_enum)) => left_enum.cmp(right_enum),
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Enum { .. }, _) => Ordering::Greater,
|
2024-08-17 10:07:38 -04:00
|
|
|
(Type::Float, Type::Float) => Ordering::Equal,
|
|
|
|
(Type::Float, _) => Ordering::Greater,
|
|
|
|
(Type::Function(left_function), Type::Function(right_function)) => {
|
|
|
|
left_function.cmp(right_function)
|
|
|
|
}
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Function { .. }, _) => Ordering::Greater,
|
2024-08-17 10:07:38 -04:00
|
|
|
(Type::Generic { .. }, Type::Generic { .. }) => Ordering::Equal,
|
|
|
|
(Type::Generic { .. }, _) => Ordering::Greater,
|
|
|
|
(Type::Integer, Type::Integer) => Ordering::Equal,
|
|
|
|
(Type::Integer, _) => Ordering::Greater,
|
2024-11-27 19:43:50 -05:00
|
|
|
(Type::List(left_item_type), Type::List(right_item_type)) => {
|
|
|
|
left_item_type.cmp(right_item_type)
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
|
|
|
(Type::List { .. }, _) => Ordering::Greater,
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Map(left_pairs), Type::Map(right_pairs)) => {
|
2024-08-17 10:07:38 -04:00
|
|
|
left_pairs.iter().cmp(right_pairs.iter())
|
|
|
|
}
|
|
|
|
(Type::Map { .. }, _) => Ordering::Greater,
|
2024-11-09 21:40:33 -05:00
|
|
|
(Type::None, Type::None) => Ordering::Equal,
|
|
|
|
(Type::None, _) => Ordering::Greater,
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Range(left_type), Type::Range(right_type)) => left_type.cmp(right_type),
|
2024-08-17 10:07:38 -04:00
|
|
|
(Type::Range { .. }, _) => Ordering::Greater,
|
2024-12-17 03:22:44 -05:00
|
|
|
(Type::SelfFunction, Type::SelfFunction) => Ordering::Equal,
|
|
|
|
(Type::SelfFunction, _) => Ordering::Greater,
|
2024-11-27 19:43:50 -05:00
|
|
|
(Type::String, Type::String) => Ordering::Equal,
|
2024-08-20 18:48:25 -04:00
|
|
|
(Type::String { .. }, _) => Ordering::Greater,
|
2024-08-17 10:07:38 -04:00
|
|
|
(Type::Struct(left_struct), Type::Struct(right_struct)) => {
|
|
|
|
left_struct.cmp(right_struct)
|
|
|
|
}
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Struct { .. }, _) => Ordering::Greater,
|
2024-08-23 12:16:56 -04:00
|
|
|
|
2025-02-08 05:56:49 -05:00
|
|
|
(Type::Tuple(left), Type::Tuple(right)) => left.cmp(right),
|
2024-08-23 12:16:56 -04:00
|
|
|
(Type::Tuple { .. }, _) => Ordering::Greater,
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub struct FunctionType {
|
2025-01-13 06:01:38 -05:00
|
|
|
pub type_parameters: Vec<u16>,
|
2025-02-08 05:56:49 -05:00
|
|
|
pub value_parameters: Vec<Type>,
|
|
|
|
pub return_type: Box<Type>,
|
2024-12-04 13:31:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FunctionType {
|
2025-02-08 05:56:49 -05:00
|
|
|
pub fn new<T: Into<Vec<u16>>, U: Into<Vec<Type>>>(
|
2025-01-09 01:44:07 -05:00
|
|
|
type_parameters: T,
|
|
|
|
value_parameters: U,
|
2024-12-04 13:31:02 -05:00
|
|
|
return_type: Type,
|
|
|
|
) -> Self {
|
|
|
|
FunctionType {
|
2025-01-09 01:44:07 -05:00
|
|
|
type_parameters: type_parameters.into(),
|
|
|
|
value_parameters: value_parameters.into(),
|
2025-02-08 05:56:49 -05:00
|
|
|
return_type: Box::new(return_type),
|
2024-12-04 13:31:02 -05:00
|
|
|
}
|
|
|
|
}
|
2024-08-16 17:07:49 -04:00
|
|
|
}
|
2024-06-26 14:44:23 -04:00
|
|
|
|
2025-02-07 15:37:48 -05:00
|
|
|
impl Default for FunctionType {
|
|
|
|
fn default() -> Self {
|
|
|
|
FunctionType {
|
|
|
|
type_parameters: Vec::new(),
|
|
|
|
value_parameters: Vec::new(),
|
2025-02-08 05:56:49 -05:00
|
|
|
return_type: Box::new(Type::None),
|
2025-02-07 15:37:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
impl Display for FunctionType {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(f, "fn ")?;
|
2024-06-17 10:10:06 -04:00
|
|
|
|
2025-01-09 01:44:07 -05:00
|
|
|
if !self.type_parameters.is_empty() {
|
2024-08-16 17:07:49 -04:00
|
|
|
write!(f, "<")?;
|
2024-06-17 10:10:06 -04:00
|
|
|
|
2025-01-09 01:44:07 -05:00
|
|
|
for (index, type_parameter) in self.type_parameters.iter().enumerate() {
|
2024-10-12 20:19:21 -04:00
|
|
|
if index > 0 {
|
2024-08-16 17:07:49 -04:00
|
|
|
write!(f, ", ")?;
|
2024-03-08 21:26:49 -05:00
|
|
|
}
|
2024-10-12 20:19:21 -04:00
|
|
|
|
|
|
|
write!(f, "{type_parameter}")?;
|
2024-08-16 17:07:49 -04:00
|
|
|
}
|
2024-03-08 21:26:49 -05:00
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
write!(f, ">")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "(")?;
|
|
|
|
|
2025-01-09 01:44:07 -05:00
|
|
|
if !self.value_parameters.is_empty() {
|
2025-02-08 05:56:49 -05:00
|
|
|
for (index, r#type) in self.value_parameters.iter().enumerate() {
|
2024-10-12 20:19:21 -04:00
|
|
|
if index > 0 {
|
2024-08-16 17:07:49 -04:00
|
|
|
write!(f, ", ")?;
|
2024-06-22 00:58:30 -04:00
|
|
|
}
|
2024-10-12 20:19:21 -04:00
|
|
|
|
2024-12-17 16:31:32 -05:00
|
|
|
write!(f, "{type}")?;
|
2024-03-08 21:26:49 -05:00
|
|
|
}
|
2024-08-13 13:28:22 -04:00
|
|
|
}
|
2024-08-16 17:07:49 -04:00
|
|
|
|
|
|
|
write!(f, ")")?;
|
|
|
|
|
2025-02-08 05:56:49 -05:00
|
|
|
if self.return_type.as_ref() != &Type::None {
|
2024-11-09 21:40:33 -05:00
|
|
|
write!(f, " -> {}", self.return_type)?;
|
2024-08-16 17:07:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2024-08-13 13:28:22 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
2024-08-13 13:28:22 -04:00
|
|
|
pub enum StructType {
|
2024-11-04 15:38:58 -05:00
|
|
|
Unit { name: u8 },
|
|
|
|
Tuple { name: u8, fields: Vec<Type> },
|
|
|
|
Fields { name: u8, fields: HashMap<u8, Type> },
|
2024-08-13 13:28:22 -04:00
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
impl StructType {
|
2024-11-04 15:38:58 -05:00
|
|
|
pub fn name(&self) -> u8 {
|
2024-08-13 13:28:22 -04:00
|
|
|
match self {
|
2024-11-04 15:38:58 -05:00
|
|
|
StructType::Unit { name } => *name,
|
|
|
|
StructType::Tuple { name, .. } => *name,
|
|
|
|
StructType::Fields { name, .. } => *name,
|
2024-03-06 22:15:35 -05:00
|
|
|
}
|
|
|
|
}
|
2024-08-17 04:06:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
impl Display for StructType {
|
2024-08-17 10:07:38 -04:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
2024-08-20 00:15:19 -04:00
|
|
|
match self {
|
|
|
|
StructType::Unit { name } => write!(f, "{name}"),
|
|
|
|
StructType::Tuple { name, fields } => {
|
|
|
|
write!(f, "{name}(")?;
|
2024-08-17 10:07:38 -04:00
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
for (index, field) in fields.iter().enumerate() {
|
|
|
|
write!(f, "{field}")?;
|
2024-08-17 10:07:38 -04:00
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
if index != fields.len() - 1 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ")")
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
2024-08-20 00:15:19 -04:00
|
|
|
StructType::Fields { name, fields } => {
|
|
|
|
write!(f, "{name} {{")?;
|
|
|
|
|
|
|
|
for (index, (identifier, r#type)) in fields.iter().enumerate() {
|
|
|
|
write!(f, "{identifier}: {type}")?;
|
|
|
|
|
|
|
|
if index != fields.len() - 1 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
}
|
2024-08-17 10:07:38 -04:00
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
write!(f, "}}")
|
|
|
|
}
|
|
|
|
}
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
impl PartialOrd for StructType {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
2024-08-17 04:06:13 -04:00
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
impl Ord for StructType {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
match (self, other) {
|
|
|
|
(StructType::Unit { name: left_name }, StructType::Unit { name: right_name }) => {
|
|
|
|
left_name.cmp(right_name)
|
|
|
|
}
|
|
|
|
(StructType::Unit { .. }, _) => Ordering::Greater,
|
|
|
|
(
|
|
|
|
StructType::Tuple {
|
|
|
|
name: left_name,
|
|
|
|
fields: left_fields,
|
|
|
|
},
|
|
|
|
StructType::Tuple {
|
|
|
|
name: right_name,
|
|
|
|
fields: right_fields,
|
|
|
|
},
|
|
|
|
) => {
|
|
|
|
let name_cmp = left_name.cmp(right_name);
|
|
|
|
|
|
|
|
if name_cmp == Ordering::Equal {
|
|
|
|
left_fields.cmp(right_fields)
|
|
|
|
} else {
|
|
|
|
name_cmp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(StructType::Tuple { .. }, _) => Ordering::Greater,
|
|
|
|
(
|
|
|
|
StructType::Fields {
|
|
|
|
name: left_name,
|
|
|
|
fields: left_fields,
|
|
|
|
},
|
|
|
|
StructType::Fields {
|
|
|
|
name: right_name,
|
|
|
|
fields: right_fields,
|
|
|
|
},
|
|
|
|
) => {
|
|
|
|
let name_cmp = left_name.cmp(right_name);
|
2024-08-17 10:07:38 -04:00
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
if name_cmp == Ordering::Equal {
|
|
|
|
let len_cmp = left_fields.len().cmp(&right_fields.len());
|
2024-08-17 10:07:38 -04:00
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
if len_cmp == Ordering::Equal {
|
|
|
|
left_fields.iter().cmp(right_fields.iter())
|
|
|
|
} else {
|
|
|
|
len_cmp
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
name_cmp
|
|
|
|
}
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
2024-08-20 00:15:19 -04:00
|
|
|
(StructType::Fields { .. }, _) => Ordering::Greater,
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub struct EnumType {
|
2024-11-04 15:38:58 -05:00
|
|
|
pub name: u8,
|
2024-08-20 00:15:19 -04:00
|
|
|
pub variants: Vec<StructType>,
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
impl Display for EnumType {
|
2024-08-17 10:07:38 -04:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
let EnumType { name, variants } = self;
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
write!(f, "enum {name} {{ ")?;
|
2024-08-17 10:07:38 -04:00
|
|
|
|
|
|
|
for (index, variant) in variants.iter().enumerate() {
|
|
|
|
write!(f, "{variant}")?;
|
|
|
|
|
|
|
|
if index != self.variants.len() - 1 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 00:15:19 -04:00
|
|
|
write!(f, " }}")
|
2024-08-17 10:07:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-08 05:56:49 -05:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub struct GenericType {
|
|
|
|
pub identifier_index: u8,
|
|
|
|
pub concrete_type: Option<Box<Type>>,
|
|
|
|
}
|
|
|
|
|
2024-08-16 17:07:49 -04:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct TypeConflict {
|
|
|
|
pub expected: Type,
|
|
|
|
pub actual: Type,
|
|
|
|
}
|