-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Factor intermediate language type declarations into separate files
The `ast_files` was getting too large. This commit moves all types but the main `DataType` into separate files.
- Loading branch information
1 parent
66796b3
commit 89bbd00
Showing
10 changed files
with
737 additions
and
712 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use std::fmt::Display; | ||
|
||
use super::{DataType, FunctionType}; | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub enum AbstractArgument { | ||
FunctionArgument(AbstractFunctionArg), | ||
ValueArgument(AbstractValueArg), | ||
} | ||
|
||
impl Display for AbstractArgument { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!( | ||
f, | ||
"{}", | ||
match self { | ||
AbstractArgument::ValueArgument(val_arg) => { | ||
format!("{}: {}", val_arg.name, val_arg.data_type) | ||
} | ||
AbstractArgument::FunctionArgument(fun_arg) => { | ||
format!("fn ({}): {}", fun_arg.abstract_name, fun_arg.function_type) | ||
} | ||
} | ||
) | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct AbstractFunctionArg { | ||
pub abstract_name: String, | ||
pub function_type: FunctionType, | ||
} | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct AbstractValueArg { | ||
pub name: String, | ||
pub data_type: DataType, | ||
pub mutable: bool, | ||
} | ||
|
||
impl Display for AbstractValueArg { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}: {}", self.name, self.data_type) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use super::DataType; | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct ArrayType { | ||
pub element_type: Box<DataType>, | ||
pub length: usize, | ||
} | ||
|
||
impl ArrayType { | ||
pub(crate) fn size_in_memory(&self) -> usize { | ||
self.element_type.stack_size() * self.length | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use anyhow::bail; | ||
|
||
use super::{DataType, EnumType, StructType}; | ||
|
||
/// Helper-type used during parsing to handle all | ||
/// custom-types. | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub enum CustomTypeOil { | ||
Struct(StructType), | ||
Enum(EnumType), | ||
} | ||
|
||
impl From<EnumType> for CustomTypeOil { | ||
fn from(value: EnumType) -> Self { | ||
CustomTypeOil::Enum(value) | ||
} | ||
} | ||
|
||
impl From<&EnumType> for CustomTypeOil { | ||
fn from(value: &EnumType) -> Self { | ||
CustomTypeOil::Enum(value.to_owned()) | ||
} | ||
} | ||
|
||
impl TryFrom<&CustomTypeOil> for EnumType { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(value: &CustomTypeOil) -> Result<Self, Self::Error> { | ||
match value { | ||
CustomTypeOil::Struct(s) => bail!("Expected enum but found struct {s}"), | ||
CustomTypeOil::Enum(e) => Ok(e.to_owned()), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<DataType> for CustomTypeOil { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(value: DataType) -> Result<Self, Self::Error> { | ||
match value { | ||
DataType::Enum(enumt) => Ok(CustomTypeOil::Enum(*enumt.to_owned())), | ||
DataType::Struct(structt) => Ok(CustomTypeOil::Struct(structt.to_owned())), | ||
_ => bail!("Cannot convert {value} to specified type"), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<CustomTypeOil> for EnumType { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(value: CustomTypeOil) -> Result<Self, Self::Error> { | ||
match value { | ||
CustomTypeOil::Struct(s) => bail!("Expected enum but found struct {s}"), | ||
CustomTypeOil::Enum(e) => Ok(e), | ||
} | ||
} | ||
} | ||
|
||
impl From<StructType> for CustomTypeOil { | ||
fn from(value: StructType) -> Self { | ||
CustomTypeOil::Struct(value) | ||
} | ||
} | ||
|
||
impl From<CustomTypeOil> for DataType { | ||
fn from(value: CustomTypeOil) -> Self { | ||
match value { | ||
CustomTypeOil::Struct(s) => DataType::Struct(s), | ||
CustomTypeOil::Enum(e) => DataType::Enum(Box::new(e)), | ||
} | ||
} | ||
} | ||
|
||
impl CustomTypeOil { | ||
pub(crate) fn name(&self) -> &str { | ||
match self { | ||
CustomTypeOil::Struct(s) => &s.name, | ||
CustomTypeOil::Enum(e) => &e.name, | ||
} | ||
} | ||
|
||
pub(crate) fn is_prelude(&self) -> bool { | ||
match self { | ||
CustomTypeOil::Struct(_) => false, | ||
CustomTypeOil::Enum(e) => e.is_prelude, | ||
} | ||
} | ||
|
||
pub fn field_or_variant_types_mut<'a>( | ||
&'a mut self, | ||
) -> Box<dyn Iterator<Item = &'a mut DataType> + 'a> { | ||
match self { | ||
CustomTypeOil::Struct(struct_type) => struct_type.field_types_mut(), | ||
CustomTypeOil::Enum(enum_type) => enum_type.variant_types_mut(), | ||
} | ||
} | ||
|
||
pub fn field_or_variant_types<'a>(&'a self) -> Box<dyn Iterator<Item = &'a DataType> + 'a> { | ||
match self { | ||
CustomTypeOil::Struct(struct_type) => struct_type.field_types(), | ||
CustomTypeOil::Enum(enum_type) => enum_type.variant_types(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
use itertools::Itertools; | ||
|
||
use super::DataType; | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct EnumType { | ||
pub name: String, | ||
pub is_copy: bool, | ||
pub variants: Vec<(String, DataType)>, | ||
pub is_prelude: bool, | ||
|
||
// Use `type_parameter` to create differentiate between function labels | ||
// for e.g. `Result<T>` and `Result<S>` types. | ||
pub type_parameter: Option<DataType>, | ||
} | ||
|
||
impl From<&EnumType> for DataType { | ||
fn from(value: &EnumType) -> Self { | ||
Self::Enum(Box::new(value.to_owned())) | ||
} | ||
} | ||
|
||
impl From<EnumType> for DataType { | ||
fn from(value: EnumType) -> Self { | ||
Self::Enum(Box::new(value)) | ||
} | ||
} | ||
|
||
impl EnumType { | ||
/// Return an iterator over mutable references to the type's nested datatypes | ||
pub(crate) fn variant_types_mut<'a>( | ||
&'a mut self, | ||
) -> Box<dyn Iterator<Item = &'a mut DataType> + 'a> { | ||
Box::new(self.variants.iter_mut().map(|x| &mut x.1)) | ||
} | ||
|
||
pub(crate) fn variant_types<'a>(&'a self) -> Box<dyn Iterator<Item = &'a DataType> + 'a> { | ||
Box::new(self.variants.iter().map(|x| &x.1)) | ||
} | ||
|
||
pub(crate) fn has_variant_of_name(&self, variant_name: &str) -> bool { | ||
self.variants.iter().any(|x| x.0 == variant_name) | ||
} | ||
|
||
pub(crate) fn variant_data_type(&self, variant_name: &str) -> DataType { | ||
for type_variant in self.variants.iter() { | ||
if type_variant.0 == variant_name { | ||
return type_variant.1.clone(); | ||
} | ||
} | ||
|
||
panic!( | ||
"variant name \"{variant_name}\" is not defined for enum {}", | ||
self.name | ||
); | ||
} | ||
|
||
/// Return the "discriminant" of an enum variant, an integer showing | ||
/// what variant the enum type takes. | ||
pub(crate) fn variant_discriminant(&self, variant_name: &str) -> usize { | ||
self.variants | ||
.iter() | ||
.find_position(|x| x.0 == variant_name) | ||
.unwrap_or_else(|| { | ||
panic!( | ||
"Could not find variant {variant_name} in enum {}", | ||
self.name, | ||
) | ||
}) | ||
.0 | ||
} | ||
|
||
/// Returns the stack size that this enum type always occupies, assuming | ||
/// it's on the stack, and not boxed. | ||
pub(crate) fn stack_size(&self) -> usize { | ||
self.variants | ||
.iter() | ||
.max_by_key(|x| x.1.stack_size()) | ||
.map(|x| x.1.stack_size() + 1) | ||
.unwrap_or_default() | ||
} | ||
|
||
/// Return the words of padding used for a specific variant in this enum | ||
pub(crate) fn padding_size(&self, variant_name: &str) -> usize { | ||
self.stack_size() - self.variant_data_type(variant_name).stack_size() - 1 | ||
} | ||
|
||
/// Decompose the type of a variant into its three consituent parts: | ||
/// data, padding, discriminant. Must match layout defined by constructor | ||
/// which is: | ||
/// stack: _ [data] [padding] discriminator | ||
pub fn decompose_variant(&self, variant_name: &str) -> Vec<DataType> { | ||
[ | ||
self.variant_data_type(variant_name).as_tuple_type().fields, | ||
vec![DataType::Tuple( | ||
vec![DataType::Bfe; self.padding_size(variant_name)].into(), | ||
)], | ||
vec![DataType::Bfe], | ||
] | ||
.concat() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use std::fmt::Display; | ||
|
||
use anyhow::bail; | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub enum FieldId { | ||
NamedField(String), | ||
UnnamedField(usize), | ||
} | ||
|
||
impl From<&str> for FieldId { | ||
fn from(value: &str) -> Self { | ||
Self::NamedField(value.to_owned()) | ||
} | ||
} | ||
|
||
impl From<&String> for FieldId { | ||
fn from(value: &String) -> Self { | ||
Self::NamedField(value.to_owned()) | ||
} | ||
} | ||
|
||
impl From<String> for FieldId { | ||
fn from(value: String) -> Self { | ||
Self::NamedField(value) | ||
} | ||
} | ||
|
||
impl From<&usize> for FieldId { | ||
fn from(value: &usize) -> Self { | ||
Self::UnnamedField(*value) | ||
} | ||
} | ||
|
||
impl From<usize> for FieldId { | ||
fn from(value: usize) -> Self { | ||
Self::UnnamedField(value) | ||
} | ||
} | ||
|
||
impl From<u32> for FieldId { | ||
fn from(value: u32) -> Self { | ||
Self::UnnamedField(value as usize) | ||
} | ||
} | ||
|
||
impl TryFrom<&FieldId> for usize { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(value: &FieldId) -> Result<Self, Self::Error> { | ||
match value { | ||
FieldId::NamedField(_) => bail!("Cannot convert named field to usize"), | ||
FieldId::UnnamedField(tuple_index) => Ok(*tuple_index), | ||
} | ||
} | ||
} | ||
|
||
impl Display for FieldId { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
let output = match self { | ||
FieldId::NamedField(name) => name.to_owned(), | ||
FieldId::UnnamedField(tuple_index) => tuple_index.to_string(), | ||
}; | ||
write!(f, "{output}") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use std::fmt::Display; | ||
|
||
use super::DataType; | ||
|
||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct FunctionType { | ||
pub input_argument: DataType, | ||
pub output: DataType, | ||
} | ||
|
||
impl Display for FunctionType { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{} -> {}", self.input_argument, self.output) | ||
} | ||
} |
Oops, something went wrong.