Begin converting type assingment to declarations
This commit is contained in:
parent
0b8880ae55
commit
e429693364
83
dust-lang/src/abstract_tree/enum_declaration.rs
Normal file
83
dust-lang/src/abstract_tree/enum_declaration.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
identifier::Identifier,
|
||||
};
|
||||
|
||||
use super::{Evaluate, Evaluation, Type, TypeConstructor, WithPosition};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct EnumDeclaration {
|
||||
pub name: WithPosition<Identifier>,
|
||||
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
|
||||
pub variants: Vec<EnumVariant>,
|
||||
}
|
||||
|
||||
impl Evaluate for EnumDeclaration {
|
||||
fn validate(
|
||||
&self,
|
||||
_context: &mut Context,
|
||||
_manage_memory: bool,
|
||||
) -> Result<(), ValidationError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn evaluate(
|
||||
self,
|
||||
context: &mut Context,
|
||||
_manage_memory: bool,
|
||||
) -> Result<Evaluation, RuntimeError> {
|
||||
let EnumDeclaration {
|
||||
name,
|
||||
type_parameters,
|
||||
variants,
|
||||
} = self;
|
||||
|
||||
let type_parameters = type_parameters.as_ref().map(|parameters| {
|
||||
parameters
|
||||
.iter()
|
||||
.map(|identifier| Type::Generic {
|
||||
identifier: identifier.node.clone(),
|
||||
concrete_type: None,
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
let mut type_variants = Vec::with_capacity(variants.len());
|
||||
|
||||
for EnumVariant { name, content } in variants {
|
||||
let types = if let Some(content) = content {
|
||||
let mut types = Vec::with_capacity(content.len());
|
||||
|
||||
for constructor in content {
|
||||
let r#type = constructor.construct(&context)?;
|
||||
|
||||
types.push(r#type);
|
||||
}
|
||||
|
||||
Some(types)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
type_variants.push((name.node, types));
|
||||
}
|
||||
|
||||
let r#type = Type::Enum {
|
||||
name: name.node.clone(),
|
||||
type_parameters,
|
||||
variants: type_variants,
|
||||
};
|
||||
|
||||
context.set_type(name.node, r#type)?;
|
||||
|
||||
Ok(Evaluation::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct EnumVariant {
|
||||
pub name: WithPosition<Identifier>,
|
||||
pub content: Option<Vec<TypeConstructor>>,
|
||||
}
|
@ -3,6 +3,7 @@ pub mod assignment;
|
||||
pub mod async_block;
|
||||
pub mod block;
|
||||
pub mod built_in_function_call;
|
||||
pub mod enum_declaration;
|
||||
pub mod expression;
|
||||
pub mod function_call;
|
||||
pub mod if_else;
|
||||
@ -14,7 +15,7 @@ pub mod math;
|
||||
pub mod statement;
|
||||
pub mod structure_definition;
|
||||
pub mod r#type;
|
||||
pub mod type_assignment;
|
||||
pub mod type_alias;
|
||||
pub mod type_constructor;
|
||||
pub mod value_node;
|
||||
pub mod r#while;
|
||||
@ -29,6 +30,7 @@ pub use self::{
|
||||
async_block::AsyncBlock,
|
||||
block::Block,
|
||||
built_in_function_call::BuiltInFunctionCall,
|
||||
enum_declaration::{EnumDeclaration, EnumVariant},
|
||||
expression::Expression,
|
||||
function_call::FunctionCall,
|
||||
if_else::IfElse,
|
||||
@ -42,7 +44,7 @@ pub use self::{
|
||||
r#while::While,
|
||||
statement::Statement,
|
||||
structure_definition::StructureDefinition,
|
||||
type_assignment::TypeAssignment,
|
||||
type_alias::TypeAlias,
|
||||
type_constructor::{
|
||||
EnumTypeConstructor, FunctionTypeConstructor, ListTypeConstructor, TypeConstructor,
|
||||
},
|
||||
|
@ -6,8 +6,8 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
Assignment, AsyncBlock, Block, Evaluate, Evaluation, ExpectedType, Expression, IfElse, Loop,
|
||||
SourcePosition, StructureDefinition, Type, TypeAssignment, While, WithPosition,
|
||||
Assignment, AsyncBlock, Block, EnumDeclaration, Evaluate, Evaluation, ExpectedType, Expression,
|
||||
IfElse, Loop, SourcePosition, StructureDefinition, Type, TypeAlias, While, WithPosition,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
@ -19,7 +19,8 @@ pub enum Statement {
|
||||
IfElse(WithPosition<IfElse>),
|
||||
Loop(WithPosition<Loop>),
|
||||
StructureDefinition(WithPosition<StructureDefinition>),
|
||||
TypeAssignment(WithPosition<TypeAssignment>),
|
||||
TypeAlias(WithPosition<TypeAlias>),
|
||||
EnumDeclaration(WithPosition<EnumDeclaration>),
|
||||
Expression(Expression),
|
||||
While(WithPosition<While>),
|
||||
}
|
||||
@ -35,7 +36,8 @@ impl Statement {
|
||||
Statement::IfElse(inner) => inner.position,
|
||||
Statement::Loop(inner) => inner.position,
|
||||
Statement::StructureDefinition(inner) => inner.position,
|
||||
Statement::TypeAssignment(inner) => inner.position,
|
||||
Statement::TypeAlias(inner) => inner.position,
|
||||
Statement::EnumDeclaration(inner) => inner.position,
|
||||
Statement::While(inner) => inner.position,
|
||||
}
|
||||
}
|
||||
@ -68,8 +70,9 @@ impl Evaluate for Statement {
|
||||
Statement::StructureDefinition(structure_definition) => {
|
||||
structure_definition.node.validate(_context, _manage_memory)
|
||||
}
|
||||
Statement::TypeAssignment(type_alias) => {
|
||||
type_alias.node.validate(_context, _manage_memory)
|
||||
Statement::TypeAlias(type_alias) => type_alias.node.validate(_context, _manage_memory),
|
||||
Statement::EnumDeclaration(type_declaration) => {
|
||||
type_declaration.node.validate(_context, _manage_memory)
|
||||
}
|
||||
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory),
|
||||
}
|
||||
@ -91,7 +94,8 @@ impl Evaluate for Statement {
|
||||
Statement::StructureDefinition(structure_definition) => {
|
||||
structure_definition.node.evaluate(context, manage_memory)
|
||||
}
|
||||
Statement::TypeAssignment(type_alias) => {
|
||||
Statement::TypeAlias(type_alias) => type_alias.node.evaluate(context, manage_memory),
|
||||
Statement::EnumDeclaration(type_alias) => {
|
||||
type_alias.node.evaluate(context, manage_memory)
|
||||
}
|
||||
Statement::While(r#while) => r#while.node.evaluate(context, manage_memory),
|
||||
|
@ -16,6 +16,7 @@ pub enum Type {
|
||||
Any,
|
||||
Boolean,
|
||||
Enum {
|
||||
name: Identifier,
|
||||
type_parameters: Option<Vec<Type>>,
|
||||
variants: Vec<(Identifier, Option<Vec<Type>>)>,
|
||||
},
|
||||
|
@ -9,12 +9,12 @@ use crate::{
|
||||
use super::{Evaluate, Evaluation, TypeConstructor, WithPosition};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct TypeAssignment {
|
||||
pub struct TypeAlias {
|
||||
identifier: WithPosition<Identifier>,
|
||||
constructor: TypeConstructor,
|
||||
}
|
||||
|
||||
impl TypeAssignment {
|
||||
impl TypeAlias {
|
||||
pub fn new(identifier: WithPosition<Identifier>, constructor: TypeConstructor) -> Self {
|
||||
Self {
|
||||
identifier,
|
||||
@ -23,7 +23,7 @@ impl TypeAssignment {
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for TypeAssignment {
|
||||
impl Evaluate for TypeAlias {
|
||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||
let r#type = self.constructor.clone().construct(&context)?;
|
||||
|
@ -53,6 +53,7 @@ impl TypeConstructor {
|
||||
};
|
||||
|
||||
if let Type::Enum {
|
||||
name,
|
||||
type_parameters,
|
||||
variants,
|
||||
} = invoked_type
|
||||
@ -64,6 +65,7 @@ impl TypeConstructor {
|
||||
}
|
||||
|
||||
Type::Enum {
|
||||
name,
|
||||
type_parameters: type_parameters.clone(),
|
||||
variants: mapped_variants,
|
||||
}
|
||||
@ -73,6 +75,7 @@ impl TypeConstructor {
|
||||
}
|
||||
TypeConstructor::Enum(enum_type_constructor) => {
|
||||
let EnumTypeConstructor {
|
||||
name,
|
||||
type_parameters,
|
||||
variants,
|
||||
} = enum_type_constructor.node;
|
||||
@ -95,6 +98,7 @@ impl TypeConstructor {
|
||||
}
|
||||
|
||||
Type::Enum {
|
||||
name: name.node,
|
||||
type_parameters: type_parameters.map(|identifiers| {
|
||||
identifiers
|
||||
.into_iter()
|
||||
@ -165,6 +169,7 @@ impl Display for TypeConstructor {
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct EnumTypeConstructor {
|
||||
pub name: WithPosition<Identifier>,
|
||||
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
|
||||
pub variants: Vec<(WithPosition<Identifier>, Option<Vec<TypeConstructor>>)>,
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
lexer::{Control, Keyword, Operator, Token},
|
||||
};
|
||||
|
||||
use self::type_constructor::TypeInvokationConstructor;
|
||||
use self::{enum_declaration::EnumVariant, type_constructor::TypeInvokationConstructor};
|
||||
|
||||
pub type ParserInput<'src> =
|
||||
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
|
||||
@ -149,51 +149,6 @@ pub fn parser<'src>(
|
||||
TypeConstructor::ListOf(Box::new(item_type).with_position(state.span()))
|
||||
});
|
||||
|
||||
let enum_variant = positioned_identifier.clone().then(
|
||||
type_constructor
|
||||
.clone()
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::ParenOpen)),
|
||||
just(Token::Control(Control::ParenClose)),
|
||||
)
|
||||
.or_not(),
|
||||
);
|
||||
|
||||
let enum_type = just(Token::Keyword(Keyword::Enum))
|
||||
.ignore_then(
|
||||
positioned_identifier
|
||||
.clone()
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::Pipe)),
|
||||
just(Token::Control(Control::Pipe)),
|
||||
)
|
||||
.or_not(),
|
||||
)
|
||||
.then(
|
||||
enum_variant
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.at_least(1)
|
||||
.allow_trailing()
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::CurlyOpen)),
|
||||
just(Token::Control(Control::CurlyClose)),
|
||||
),
|
||||
)
|
||||
.map_with(|(type_parameters, variants), state| {
|
||||
TypeConstructor::Enum(
|
||||
EnumTypeConstructor {
|
||||
type_parameters,
|
||||
variants,
|
||||
}
|
||||
.with_position(state.span()),
|
||||
)
|
||||
});
|
||||
|
||||
let type_invokation = positioned_identifier
|
||||
.clone()
|
||||
.then(
|
||||
@ -222,7 +177,6 @@ pub fn parser<'src>(
|
||||
list_type,
|
||||
list_of_type,
|
||||
primitive_type,
|
||||
enum_type,
|
||||
))
|
||||
});
|
||||
|
||||
@ -709,13 +663,64 @@ pub fn parser<'src>(
|
||||
},
|
||||
);
|
||||
|
||||
let type_assignment = just(Token::Keyword(Keyword::Type))
|
||||
let type_alias = just(Token::Keyword(Keyword::Type))
|
||||
.ignore_then(positioned_identifier.clone())
|
||||
.then_ignore(just(Token::Operator(Operator::Assign)))
|
||||
.then(type_constructor.clone())
|
||||
.map_with(|(identifier, constructor), state| {
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(identifier, constructor).with_position(state.span()),
|
||||
Statement::TypeAlias(
|
||||
TypeAlias::new(identifier, constructor).with_position(state.span()),
|
||||
)
|
||||
});
|
||||
|
||||
let enum_variant = positioned_identifier
|
||||
.clone()
|
||||
.then(
|
||||
type_constructor
|
||||
.clone()
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::ParenOpen)),
|
||||
just(Token::Control(Control::ParenClose)),
|
||||
)
|
||||
.or_not(),
|
||||
)
|
||||
.map(|(identifier, constructors)| EnumVariant {
|
||||
name: identifier,
|
||||
content: constructors,
|
||||
});
|
||||
|
||||
let enum_declaration = just(Token::Keyword(Keyword::Enum))
|
||||
.ignore_then(positioned_identifier.clone())
|
||||
.then(
|
||||
positioned_identifier
|
||||
.clone()
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Operator(Operator::Less)),
|
||||
just(Token::Operator(Operator::Greater)),
|
||||
)
|
||||
.or_not(),
|
||||
)
|
||||
.then(
|
||||
enum_variant
|
||||
.separated_by(just(Token::Control(Control::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::CurlyOpen)),
|
||||
just(Token::Control(Control::CurlyClose)),
|
||||
),
|
||||
)
|
||||
.map_with(|((name, type_parameters), variants), state| {
|
||||
Statement::EnumDeclaration(
|
||||
EnumDeclaration {
|
||||
name,
|
||||
type_parameters,
|
||||
variants,
|
||||
}
|
||||
.with_position((0, 0)),
|
||||
)
|
||||
});
|
||||
|
||||
@ -731,7 +736,8 @@ pub fn parser<'src>(
|
||||
block_statement,
|
||||
r#loop,
|
||||
r#while,
|
||||
type_assignment,
|
||||
type_alias,
|
||||
enum_declaration,
|
||||
)))
|
||||
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
||||
});
|
||||
@ -741,6 +747,8 @@ pub fn parser<'src>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use tests::enum_declaration::{EnumDeclaration, EnumVariant};
|
||||
|
||||
use crate::lexer::lex;
|
||||
|
||||
use super::*;
|
||||
@ -793,103 +801,88 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_type_empty() {
|
||||
fn enum_declaration() {
|
||||
assert_eq!(
|
||||
parse(&lex("type MyEnum = enum { X, Y }").unwrap()).unwrap()[0],
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
Identifier::new("MyEnum").with_position((5, 11)),
|
||||
TypeConstructor::Enum(
|
||||
EnumTypeConstructor {
|
||||
parse(&lex("enum MyEnum { X, Y }").unwrap()).unwrap()[0],
|
||||
Statement::EnumDeclaration(TypeDeclaration::Enum(
|
||||
EnumDeclaration {
|
||||
name: Identifier::new("MyEnum").with_position((0, 0)),
|
||||
type_parameters: None,
|
||||
variants: vec![
|
||||
(Identifier::new("X").with_position((21, 22)), None),
|
||||
(Identifier::new("Y").with_position((24, 25)), None)
|
||||
EnumVariant {
|
||||
name: Identifier::new("X").with_position((0, 0)),
|
||||
content: None
|
||||
},
|
||||
EnumVariant {
|
||||
name: Identifier::new("Y").with_position((0, 0)),
|
||||
content: None
|
||||
}
|
||||
],
|
||||
}
|
||||
.with_position((14, 27))
|
||||
)
|
||||
)
|
||||
.with_position((0, 27))
|
||||
)
|
||||
.with_position((0, 0))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_type_with_contents() {
|
||||
fn enum_with_contents() {
|
||||
assert_eq!(
|
||||
parse(&lex("type MyEnum = enum { X(str, int), Y(int) }").unwrap()).unwrap()[0],
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
Identifier::new("MyEnum").with_position((5, 11)),
|
||||
TypeConstructor::Enum(
|
||||
EnumTypeConstructor {
|
||||
parse(&lex("enum MyEnum { X(str, int), Y(int) }").unwrap()).unwrap()[0],
|
||||
Statement::EnumDeclaration(TypeDeclaration::Enum(
|
||||
EnumDeclaration {
|
||||
name: Identifier::new("MyEnum").with_position((0, 0)),
|
||||
type_parameters: None,
|
||||
variants: vec![
|
||||
(
|
||||
Identifier::new("X").with_position((21, 22)),
|
||||
Some(vec![
|
||||
TypeConstructor::Raw(Type::String.with_position((23, 26))),
|
||||
TypeConstructor::Raw(Type::Integer.with_position((28, 31)))
|
||||
EnumVariant {
|
||||
name: Identifier::new("X").with_position((0, 0)),
|
||||
content: Some(vec![
|
||||
TypeConstructor::Raw(Type::String.with_position((0, 0))),
|
||||
TypeConstructor::Raw(Type::Integer.with_position((0, 0))),
|
||||
])
|
||||
),
|
||||
(
|
||||
Identifier::new("Y").with_position((34, 35)),
|
||||
Some(vec![TypeConstructor::Raw(
|
||||
Type::Integer.with_position((36, 39))
|
||||
)])
|
||||
)
|
||||
],
|
||||
},
|
||||
EnumVariant {
|
||||
name: Identifier::new("Y").with_position((0, 0)),
|
||||
content: Some(vec![TypeConstructor::Raw(
|
||||
Type::Integer.with_position((0, 0))
|
||||
),])
|
||||
}
|
||||
.with_position((14, 42))
|
||||
)
|
||||
)
|
||||
.with_position((0, 42))
|
||||
)
|
||||
]
|
||||
}
|
||||
.with_position((0, 0))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_type_with_type_parameters() {
|
||||
fn enum_with_type_parameters() {
|
||||
assert_eq!(
|
||||
parse(&lex("type MyEnum = enum |T, U| { X(T), Y(U) }").unwrap()).unwrap()[0],
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
Identifier::new("MyEnum").with_position((5, 11)),
|
||||
TypeConstructor::Enum(
|
||||
EnumTypeConstructor {
|
||||
parse(&lex("enum MyEnum <T, U> { X(T), Y(U) }").unwrap()).unwrap()[0],
|
||||
Statement::EnumDeclaration(TypeDeclaration::Enum(
|
||||
EnumDeclaration {
|
||||
name: Identifier::new("MyEnum").with_position((0, 0)),
|
||||
type_parameters: Some(vec![
|
||||
Identifier::new("T").with_position((20, 21)),
|
||||
Identifier::new("U").with_position((23, 24)),
|
||||
Identifier::new("T").with_position((0, 0)),
|
||||
Identifier::new("U").with_position((0, 0))
|
||||
]),
|
||||
variants: vec![
|
||||
(
|
||||
Identifier::new("X").with_position((28, 29)),
|
||||
Some(vec![TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T")
|
||||
.with_position((30, 31)),
|
||||
type_arguments: None,
|
||||
EnumVariant {
|
||||
name: Identifier::new("X").with_position((0, 0)),
|
||||
content: Some(vec![TypeConstructor::Raw(
|
||||
Type::Generic {
|
||||
identifier: Identifier::new("T"),
|
||||
concrete_type: None
|
||||
}
|
||||
.with_position((0, 0))
|
||||
)])
|
||||
),
|
||||
(
|
||||
Identifier::new("Y").with_position((34, 35)),
|
||||
Some(vec![TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("U")
|
||||
.with_position((36, 37)),
|
||||
type_arguments: None,
|
||||
},
|
||||
EnumVariant {
|
||||
name: todo!(),
|
||||
content: todo!()
|
||||
}
|
||||
)])
|
||||
),
|
||||
],
|
||||
]
|
||||
}
|
||||
.with_position((14, 40))
|
||||
)
|
||||
)
|
||||
.with_position((0, 40))
|
||||
)
|
||||
.with_position((0, 0))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@ -960,20 +953,6 @@ mod tests {
|
||||
// )
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn type_alias() {
|
||||
assert_eq!(
|
||||
parse(&lex("type MyType = str").unwrap()).unwrap()[0],
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
Identifier::new("MyType").with_position((5, 11)),
|
||||
TypeConstructor::Raw(Type::String.with_position((14, 17)))
|
||||
)
|
||||
.with_position((0, 17))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn r#as() {
|
||||
assert_eq!(
|
||||
@ -1191,28 +1170,26 @@ mod tests {
|
||||
fn function_type() {
|
||||
assert_eq!(
|
||||
parse(&lex("type Foo = fn |T| (int) -> T").unwrap()).unwrap()[0],
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
Identifier::new("Foo").with_position((5, 8)),
|
||||
Statement::TypeAlias(
|
||||
TypeAlias::new(
|
||||
Identifier::new("Foo").with_position((0, 0)),
|
||||
TypeConstructor::Function(
|
||||
FunctionTypeConstructor {
|
||||
type_parameters: Some(vec![
|
||||
Identifier::new("T").with_position((15, 16))
|
||||
]),
|
||||
type_parameters: Some(vec![Identifier::new("T").with_position((0, 0))]),
|
||||
value_parameters: vec![TypeConstructor::Raw(
|
||||
Type::Integer.with_position((19, 22))
|
||||
Type::Integer.with_position((0, 0))
|
||||
)],
|
||||
return_type: Box::new(TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((27, 28)),
|
||||
type_arguments: None,
|
||||
identifier: Identifier::new("T").with_position((0, 0)),
|
||||
type_arguments: None
|
||||
}
|
||||
)),
|
||||
))
|
||||
}
|
||||
.with_position((11, 28))
|
||||
.with_position((0, 0))
|
||||
)
|
||||
)
|
||||
.with_position((0, 28))
|
||||
.with_position((0, 0))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user