Merge pull request #860 from aiken-lang/preserve-type-aliases
Preserve type-aliases in (pretty-printed) type annotations
This commit is contained in:
commit
bc161f761b
|
@ -1197,7 +1197,7 @@ impl TypedPattern {
|
||||||
| Pattern::Tuple {
|
| Pattern::Tuple {
|
||||||
elems: elements, ..
|
elems: elements, ..
|
||||||
} => match &**value {
|
} => match &**value {
|
||||||
Type::Tuple { elems } => elements
|
Type::Tuple { elems, .. } => elements
|
||||||
.iter()
|
.iter()
|
||||||
.zip(elems.iter())
|
.zip(elems.iter())
|
||||||
.find_map(|(e, t)| e.find_node(byte_index, t))
|
.find_map(|(e, t)| e.find_node(byte_index, t))
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Arg, ArgName, CallArg, DataTypeKey, Function, FunctionAccessKey, ModuleKind, Span,
|
Annotation, Arg, ArgName, CallArg, DataTypeKey, Function, FunctionAccessKey, ModuleKind,
|
||||||
TypedDataType, TypedFunction, UnOp,
|
Span, TypedDataType, TypedFunction, UnOp,
|
||||||
},
|
},
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
tipo::{
|
tipo::{
|
||||||
fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
|
fields::FieldMap, Type, TypeAliasAnnotation, TypeConstructor, TypeInfo, TypeVar,
|
||||||
ValueConstructorVariant,
|
ValueConstructor, ValueConstructorVariant,
|
||||||
},
|
},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
@ -1270,6 +1270,7 @@ pub fn int() -> Rc<Type> {
|
||||||
name: INT.to_string(),
|
name: INT.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,6 +1280,7 @@ pub fn data() -> Rc<Type> {
|
||||||
name: DATA.to_string(),
|
name: DATA.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,6 +1290,7 @@ pub fn byte_array() -> Rc<Type> {
|
||||||
public: true,
|
public: true,
|
||||||
name: BYTE_ARRAY.to_string(),
|
name: BYTE_ARRAY.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1297,6 +1300,7 @@ pub fn g1_element() -> Rc<Type> {
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
name: G1_ELEMENT.to_string(),
|
name: G1_ELEMENT.to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1306,6 +1310,7 @@ pub fn g2_element() -> Rc<Type> {
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
name: G2_ELEMENT.to_string(),
|
name: G2_ELEMENT.to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,11 +1320,12 @@ pub fn miller_loop_result() -> Rc<Type> {
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
name: MILLER_LOOP_RESULT.to_string(),
|
name: MILLER_LOOP_RESULT.to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tuple(elems: Vec<Rc<Type>>) -> Rc<Type> {
|
pub fn tuple(elems: Vec<Rc<Type>>) -> Rc<Type> {
|
||||||
Rc::new(Type::Tuple { elems })
|
Rc::new(Type::Tuple { elems, alias: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bool() -> Rc<Type> {
|
pub fn bool() -> Rc<Type> {
|
||||||
|
@ -1328,6 +1334,7 @@ pub fn bool() -> Rc<Type> {
|
||||||
public: true,
|
public: true,
|
||||||
name: BOOL.to_string(),
|
name: BOOL.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1337,13 +1344,47 @@ pub fn prng() -> Rc<Type> {
|
||||||
public: true,
|
public: true,
|
||||||
name: PRNG.to_string(),
|
name: PRNG.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fuzzer(a: Rc<Type>) -> Rc<Type> {
|
pub fn fuzzer(a: Rc<Type>) -> Rc<Type> {
|
||||||
|
let prng_annotation = Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
};
|
||||||
Rc::new(Type::Fn {
|
Rc::new(Type::Fn {
|
||||||
args: vec![prng()],
|
args: vec![prng()],
|
||||||
ret: option(tuple(vec![prng(), a])),
|
ret: option(tuple(vec![prng(), a])),
|
||||||
|
alias: Some(
|
||||||
|
TypeAliasAnnotation {
|
||||||
|
alias: "Fuzzer".to_string(),
|
||||||
|
parameters: vec!["a".to_string()],
|
||||||
|
annotation: Annotation::Fn {
|
||||||
|
location: Span::empty(),
|
||||||
|
arguments: vec![prng_annotation.clone()],
|
||||||
|
ret: Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "Option".to_string(),
|
||||||
|
arguments: vec![Annotation::Tuple {
|
||||||
|
location: Span::empty(),
|
||||||
|
elems: vec![
|
||||||
|
prng_annotation,
|
||||||
|
Annotation::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,6 +1394,7 @@ pub fn list(t: Rc<Type>) -> Rc<Type> {
|
||||||
name: LIST.to_string(),
|
name: LIST.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
args: vec![t],
|
args: vec![t],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,6 +1404,7 @@ pub fn string() -> Rc<Type> {
|
||||||
public: true,
|
public: true,
|
||||||
name: STRING.to_string(),
|
name: STRING.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1371,6 +1414,7 @@ pub fn void() -> Rc<Type> {
|
||||||
public: true,
|
public: true,
|
||||||
name: VOID.to_string(),
|
name: VOID.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,6 +1424,7 @@ pub fn option(a: Rc<Type>) -> Rc<Type> {
|
||||||
name: OPTION.to_string(),
|
name: OPTION.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
args: vec![a],
|
args: vec![a],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,23 +1434,26 @@ pub fn ordering() -> Rc<Type> {
|
||||||
name: ORDERING.to_string(),
|
name: ORDERING.to_string(),
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(args: Vec<Rc<Type>>, ret: Rc<Type>) -> Rc<Type> {
|
pub fn function(args: Vec<Rc<Type>>, ret: Rc<Type>) -> Rc<Type> {
|
||||||
Rc::new(Type::Fn { ret, args })
|
Rc::new(Type::Fn {
|
||||||
|
ret,
|
||||||
|
args,
|
||||||
|
alias: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generic_var(id: u64) -> Rc<Type> {
|
pub fn generic_var(id: u64) -> Rc<Type> {
|
||||||
let tipo = Rc::new(RefCell::new(TypeVar::Generic { id }));
|
let tipo = Rc::new(RefCell::new(TypeVar::Generic { id }));
|
||||||
|
Rc::new(Type::Var { tipo, alias: None })
|
||||||
Rc::new(Type::Var { tipo })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unbound_var(id: u64) -> Rc<Type> {
|
pub fn unbound_var(id: u64) -> Rc<Type> {
|
||||||
let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id }));
|
let tipo = Rc::new(RefCell::new(TypeVar::Unbound { id }));
|
||||||
|
Rc::new(Type::Var { tipo, alias: None })
|
||||||
Rc::new(Type::Var { tipo })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrapped_redeemer(redeemer: Rc<Type>) -> Rc<Type> {
|
pub fn wrapped_redeemer(redeemer: Rc<Type>) -> Rc<Type> {
|
||||||
|
@ -1414,5 +1462,6 @@ pub fn wrapped_redeemer(redeemer: Rc<Type>) -> Rc<Type> {
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
name: REDEEMER_WRAPPER.to_string(),
|
name: REDEEMER_WRAPPER.to_string(),
|
||||||
args: vec![redeemer],
|
args: vec![redeemer],
|
||||||
|
alias: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,7 @@ impl UntypedExpr {
|
||||||
&Type,
|
&Type,
|
||||||
) -> Result<Self, String>,
|
) -> Result<Self, String>,
|
||||||
{
|
{
|
||||||
if let Type::Var { tipo: var_tipo } = tipo {
|
if let Type::Var { tipo: var_tipo, .. } = tipo {
|
||||||
match &*var_tipo.borrow() {
|
match &*var_tipo.borrow() {
|
||||||
TypeVar::Link { tipo } => {
|
TypeVar::Link { tipo } => {
|
||||||
return Self::reify_with(generics, data_types, t, tipo, with);
|
return Self::reify_with(generics, data_types, t, tipo, with);
|
||||||
|
@ -724,7 +724,7 @@ impl UntypedExpr {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Tuple { elems } => Ok(UntypedExpr::Tuple {
|
Type::Tuple { elems, .. } => Ok(UntypedExpr::Tuple {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
elems: args
|
elems: args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -740,7 +740,7 @@ impl UntypedExpr {
|
||||||
},
|
},
|
||||||
|
|
||||||
uplc::ast::Constant::ProtoPair(_, _, left, right) => match tipo {
|
uplc::ast::Constant::ProtoPair(_, _, left, right) => match tipo {
|
||||||
Type::Tuple { elems } => Ok(UntypedExpr::Tuple {
|
Type::Tuple { elems, .. } => Ok(UntypedExpr::Tuple {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
elems: [left.as_ref(), right.as_ref()]
|
elems: [left.as_ref(), right.as_ref()]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -959,7 +959,7 @@ impl UntypedExpr {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Tuple { elems } => Ok(UntypedExpr::Tuple {
|
Type::Tuple { elems, .. } => Ok(UntypedExpr::Tuple {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
elems: args
|
elems: args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use indexmap::IndexSet;
|
use super::air::{Air, ExpectLevel};
|
||||||
use itertools::Itertools;
|
|
||||||
use std::{borrow::BorrowMut, rc::Rc, slice::Iter};
|
|
||||||
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{BinOp, Curve, Span, UnOp},
|
ast::{BinOp, Curve, Span, UnOp},
|
||||||
builtins::{bool, byte_array, data, int, list, string, void},
|
builtins::{bool, byte_array, data, int, list, string, void},
|
||||||
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
||||||
};
|
};
|
||||||
|
use indexmap::IndexSet;
|
||||||
use super::air::{Air, ExpectLevel};
|
use itertools::Itertools;
|
||||||
|
use std::{borrow::BorrowMut, rc::Rc, slice::Iter};
|
||||||
|
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct TreePath {
|
pub struct TreePath {
|
||||||
|
@ -720,6 +718,7 @@ impl AirTree {
|
||||||
Type::Fn {
|
Type::Fn {
|
||||||
args: vec![list(data())],
|
args: vec![list(data())],
|
||||||
ret: data(),
|
ret: data(),
|
||||||
|
alias: None,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
ValueConstructorVariant::ModuleFn {
|
ValueConstructorVariant::ModuleFn {
|
||||||
|
|
|
@ -23,7 +23,14 @@ mod pattern;
|
||||||
mod pipe;
|
mod pipe;
|
||||||
pub mod pretty;
|
pub mod pretty;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TypeAliasAnnotation {
|
||||||
|
pub alias: String,
|
||||||
|
pub parameters: Vec<String>,
|
||||||
|
pub annotation: Annotation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// A nominal (named) type such as `Int`, `Float`, or a programmer defined
|
/// A nominal (named) type such as `Int`, `Float`, or a programmer defined
|
||||||
/// custom type such as `Person`. The type can take other types as
|
/// custom type such as `Person`. The type can take other types as
|
||||||
|
@ -38,6 +45,7 @@ pub enum Type {
|
||||||
module: String,
|
module: String,
|
||||||
name: String,
|
name: String,
|
||||||
args: Vec<Rc<Type>>,
|
args: Vec<Rc<Type>>,
|
||||||
|
alias: Option<Rc<TypeAliasAnnotation>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The type of a function. It takes arguments and returns a value.
|
/// The type of a function. It takes arguments and returns a value.
|
||||||
|
@ -45,12 +53,14 @@ pub enum Type {
|
||||||
Fn {
|
Fn {
|
||||||
args: Vec<Rc<Type>>,
|
args: Vec<Rc<Type>>,
|
||||||
ret: Rc<Type>,
|
ret: Rc<Type>,
|
||||||
|
alias: Option<Rc<TypeAliasAnnotation>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A type variable. See the contained `TypeVar` enum for more information.
|
/// A type variable. See the contained `TypeVar` enum for more information.
|
||||||
///
|
///
|
||||||
Var {
|
Var {
|
||||||
tipo: Rc<RefCell<TypeVar>>,
|
tipo: Rc<RefCell<TypeVar>>,
|
||||||
|
alias: Option<Rc<TypeAliasAnnotation>>,
|
||||||
},
|
},
|
||||||
// /// A tuple is an ordered collection of 0 or more values, each of which
|
// /// A tuple is an ordered collection of 0 or more values, each of which
|
||||||
// /// can have a different type, so the `tuple` type is the sum of all the
|
// /// can have a different type, so the `tuple` type is the sum of all the
|
||||||
|
@ -58,15 +68,112 @@ pub enum Type {
|
||||||
// ///
|
// ///
|
||||||
Tuple {
|
Tuple {
|
||||||
elems: Vec<Rc<Type>>,
|
elems: Vec<Rc<Type>>,
|
||||||
|
alias: Option<Rc<TypeAliasAnnotation>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Type {
|
||||||
|
fn eq(&self, other: &Type) -> bool {
|
||||||
|
match self {
|
||||||
|
Type::App {
|
||||||
|
public,
|
||||||
|
module,
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if let Type::App {
|
||||||
|
public: public2,
|
||||||
|
module: module2,
|
||||||
|
name: name2,
|
||||||
|
args: args2,
|
||||||
|
..
|
||||||
|
} = other
|
||||||
|
{
|
||||||
|
name == name2
|
||||||
|
&& module == module2
|
||||||
|
&& public == public2
|
||||||
|
&& args.iter().zip(args2).all(|(left, right)| left == right)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Fn { args, ret, .. } => {
|
||||||
|
if let Type::Fn {
|
||||||
|
args: args2,
|
||||||
|
ret: ret2,
|
||||||
|
..
|
||||||
|
} = other
|
||||||
|
{
|
||||||
|
ret == ret2 && args.iter().zip(args2).all(|(left, right)| left == right)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Tuple { elems, .. } => {
|
||||||
|
if let Type::Tuple { elems: elems2, .. } = other {
|
||||||
|
elems.iter().zip(elems2).all(|(left, right)| left == right)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Var { tipo, .. } => {
|
||||||
|
if let Type::Var { tipo: tipo2, .. } = other {
|
||||||
|
tipo == tipo2
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
pub fn alias(&self) -> Option<Rc<TypeAliasAnnotation>> {
|
||||||
|
match self {
|
||||||
|
Type::App { alias, .. }
|
||||||
|
| Type::Fn { alias, .. }
|
||||||
|
| Type::Var { alias, .. }
|
||||||
|
| Type::Tuple { alias, .. } => alias.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_alias(tipo: Rc<Type>, alias: Option<Rc<TypeAliasAnnotation>>) -> Rc<Type> {
|
||||||
|
match alias {
|
||||||
|
None => tipo,
|
||||||
|
Some(alias) => tipo.deref().to_owned().set_alias(Some(alias)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_alias(self, alias: Option<Rc<TypeAliasAnnotation>>) -> Rc<Type> {
|
||||||
|
Rc::new(match self {
|
||||||
|
Type::App {
|
||||||
|
public,
|
||||||
|
module,
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
..
|
||||||
|
} => Type::App {
|
||||||
|
public,
|
||||||
|
module,
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
alias,
|
||||||
|
},
|
||||||
|
Type::Fn { args, ret, .. } => Type::Fn { args, ret, alias },
|
||||||
|
Type::Var { tipo, .. } => Type::Var { tipo, alias },
|
||||||
|
Type::Tuple { elems, .. } => Type::Tuple { elems, alias },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn qualifier(&self) -> Option<(String, String)> {
|
pub fn qualifier(&self) -> Option<(String, String)> {
|
||||||
match self {
|
match self {
|
||||||
Type::App { module, name, .. } => Some((module.to_string(), name.to_string())),
|
Type::App { module, name, .. } => Some((module.to_string(), name.to_string())),
|
||||||
Type::Fn { .. } => None,
|
Type::Fn { .. } => None,
|
||||||
Type::Var { ref tipo } => match &*tipo.borrow() {
|
Type::Var { ref tipo, .. } => match &*tipo.borrow() {
|
||||||
TypeVar::Link { ref tipo } => tipo.qualifier(),
|
TypeVar::Link { ref tipo } => tipo.qualifier(),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
@ -86,7 +193,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unbound(&self) -> bool {
|
pub fn is_unbound(&self) -> bool {
|
||||||
matches!(self, Self::Var { tipo } if tipo.borrow().is_unbound())
|
matches!(self, Self::Var { tipo, .. } if tipo.borrow().is_unbound())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_function(&self) -> bool {
|
pub fn is_function(&self) -> bool {
|
||||||
|
@ -119,7 +226,7 @@ impl Type {
|
||||||
pub fn is_void(&self) -> bool {
|
pub fn is_void(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "Void" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "Void" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_void(),
|
Self::Var { tipo, .. } => tipo.borrow().is_void(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +234,7 @@ impl Type {
|
||||||
pub fn is_bool(&self) -> bool {
|
pub fn is_bool(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "Bool" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "Bool" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_bool(),
|
Self::Var { tipo, .. } => tipo.borrow().is_bool(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +242,7 @@ impl Type {
|
||||||
pub fn is_int(&self) -> bool {
|
pub fn is_int(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "Int" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "Int" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_int(),
|
Self::Var { tipo, .. } => tipo.borrow().is_int(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +250,7 @@ impl Type {
|
||||||
pub fn is_bytearray(&self) -> bool {
|
pub fn is_bytearray(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "ByteArray" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "ByteArray" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_bytearray(),
|
Self::Var { tipo, .. } => tipo.borrow().is_bytearray(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +259,7 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } => G1_ELEMENT == name && module.is_empty(),
|
Self::App { module, name, .. } => G1_ELEMENT == name && module.is_empty(),
|
||||||
|
|
||||||
Self::Var { tipo } => tipo.borrow().is_bls381_12_g1(),
|
Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g1(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +268,7 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } => G2_ELEMENT == name && module.is_empty(),
|
Self::App { module, name, .. } => G2_ELEMENT == name && module.is_empty(),
|
||||||
|
|
||||||
Self::Var { tipo } => tipo.borrow().is_bls381_12_g2(),
|
Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g2(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +277,7 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } => MILLER_LOOP_RESULT == name && module.is_empty(),
|
Self::App { module, name, .. } => MILLER_LOOP_RESULT == name && module.is_empty(),
|
||||||
|
|
||||||
Self::Var { tipo } => tipo.borrow().is_ml_result(),
|
Self::Var { tipo, .. } => tipo.borrow().is_ml_result(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +285,7 @@ impl Type {
|
||||||
pub fn is_string(&self) -> bool {
|
pub fn is_string(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "String" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "String" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_string(),
|
Self::Var { tipo, .. } => tipo.borrow().is_string(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +293,7 @@ impl Type {
|
||||||
pub fn is_list(&self) -> bool {
|
pub fn is_list(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "List" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "List" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_list(),
|
Self::Var { tipo, .. } => tipo.borrow().is_list(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +301,7 @@ impl Type {
|
||||||
pub fn is_option(&self) -> bool {
|
pub fn is_option(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } if "Option" == name && module.is_empty() => true,
|
Self::App { module, name, .. } if "Option" == name && module.is_empty() => true,
|
||||||
Self::Var { tipo } => tipo.borrow().is_option(),
|
Self::Var { tipo, .. } => tipo.borrow().is_option(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,14 +314,14 @@ impl Type {
|
||||||
.first()
|
.first()
|
||||||
.expect("unreachable: List should have an inner type")
|
.expect("unreachable: List should have an inner type")
|
||||||
.is_2_tuple(),
|
.is_2_tuple(),
|
||||||
Self::Var { tipo } => tipo.borrow().is_map(),
|
Self::Var { tipo, .. } => tipo.borrow().is_map(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_tuple(&self) -> bool {
|
pub fn is_tuple(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::Var { tipo } => tipo.borrow().is_tuple(),
|
Type::Var { tipo, .. } => tipo.borrow().is_tuple(),
|
||||||
Type::Tuple { .. } => true,
|
Type::Tuple { .. } => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -222,8 +329,8 @@ impl Type {
|
||||||
|
|
||||||
pub fn is_2_tuple(&self) -> bool {
|
pub fn is_2_tuple(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::Var { tipo } => tipo.borrow().is_2_tuple(),
|
Type::Var { tipo, .. } => tipo.borrow().is_2_tuple(),
|
||||||
Type::Tuple { elems } => elems.len() == 2,
|
Type::Tuple { elems, .. } => elems.len() == 2,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +338,7 @@ impl Type {
|
||||||
pub fn is_data(&self) -> bool {
|
pub fn is_data(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } => "Data" == name && module.is_empty(),
|
Self::App { module, name, .. } => "Data" == name && module.is_empty(),
|
||||||
Self::Var { tipo } => tipo.borrow().is_data(),
|
Self::Var { tipo, .. } => tipo.borrow().is_data(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,15 +353,15 @@ impl Type {
|
||||||
is_a_generic
|
is_a_generic
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Var { tipo } => tipo.borrow().is_generic(),
|
Type::Var { tipo, .. } => tipo.borrow().is_generic(),
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, .. } => {
|
||||||
let mut is_a_generic = false;
|
let mut is_a_generic = false;
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
is_a_generic = is_a_generic || elem.is_generic();
|
is_a_generic = is_a_generic || elem.is_generic();
|
||||||
}
|
}
|
||||||
is_a_generic
|
is_a_generic
|
||||||
}
|
}
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, .. } => {
|
||||||
let mut is_a_generic = false;
|
let mut is_a_generic = false;
|
||||||
for arg in args {
|
for arg in args {
|
||||||
is_a_generic = is_a_generic || arg.is_generic();
|
is_a_generic = is_a_generic || arg.is_generic();
|
||||||
|
@ -268,14 +375,14 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Self::Fn { args, .. } => Some(args.clone()),
|
Self::Fn { args, .. } => Some(args.clone()),
|
||||||
Self::App { args, .. } => Some(args.clone()),
|
Self::App { args, .. } => Some(args.clone()),
|
||||||
Self::Var { tipo } => tipo.borrow().arg_types(),
|
Self::Var { tipo, .. } => tipo.borrow().arg_types(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_generic(&self) -> Option<u64> {
|
pub fn get_generic(&self) -> Option<u64> {
|
||||||
match self {
|
match self {
|
||||||
Type::Var { tipo } => tipo.borrow().get_generic(),
|
Type::Var { tipo, .. } => tipo.borrow().get_generic(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,24 +391,24 @@ impl Type {
|
||||||
if self.is_list() {
|
if self.is_list() {
|
||||||
match self {
|
match self {
|
||||||
Self::App { args, .. } => args.clone(),
|
Self::App { args, .. } => args.clone(),
|
||||||
Self::Var { tipo } => tipo.borrow().get_inner_types(),
|
Self::Var { tipo, .. } => tipo.borrow().get_inner_types(),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
} else if self.is_tuple() {
|
} else if self.is_tuple() {
|
||||||
match self {
|
match self {
|
||||||
Self::Tuple { elems } => elems.to_vec(),
|
Self::Tuple { elems, .. } => elems.to_vec(),
|
||||||
Self::Var { tipo } => tipo.borrow().get_inner_types(),
|
Self::Var { tipo, .. } => tipo.borrow().get_inner_types(),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
} else if matches!(self.get_uplc_type(), UplcType::Data) {
|
} else if matches!(self.get_uplc_type(), UplcType::Data) {
|
||||||
match self {
|
match self {
|
||||||
Type::App { args, .. } => args.clone(),
|
Type::App { args, .. } => args.clone(),
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, .. } => {
|
||||||
let mut args = args.clone();
|
let mut args = args.clone();
|
||||||
args.push(ret.clone());
|
args.push(ret.clone());
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
Type::Var { tipo } => tipo.borrow().get_inner_types(),
|
Type::Var { tipo, .. } => tipo.borrow().get_inner_types(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -324,14 +431,14 @@ impl Type {
|
||||||
UplcType::List(UplcType::Data.into())
|
UplcType::List(UplcType::Data.into())
|
||||||
} else if self.is_tuple() {
|
} else if self.is_tuple() {
|
||||||
match self {
|
match self {
|
||||||
Self::Tuple { elems } => {
|
Self::Tuple { elems, .. } => {
|
||||||
if elems.len() == 2 {
|
if elems.len() == 2 {
|
||||||
UplcType::Pair(UplcType::Data.into(), UplcType::Data.into())
|
UplcType::Pair(UplcType::Data.into(), UplcType::Data.into())
|
||||||
} else {
|
} else {
|
||||||
UplcType::List(UplcType::Data.into())
|
UplcType::List(UplcType::Data.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Var { tipo } => tipo.borrow().get_uplc_type().unwrap(),
|
Self::Var { tipo, .. } => tipo.borrow().get_uplc_type().unwrap(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
} else if self.is_bls381_12_g1() {
|
} else if self.is_bls381_12_g1() {
|
||||||
|
@ -371,7 +478,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Var { tipo } => {
|
Self::Var { tipo, alias } => {
|
||||||
let args: Vec<_> = match tipo.borrow().deref() {
|
let args: Vec<_> = match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo } => {
|
TypeVar::Link { tipo } => {
|
||||||
return tipo.get_app_args(public, module, name, arity, environment);
|
return tipo.get_app_args(public, module, name, arity, environment);
|
||||||
|
@ -388,10 +495,11 @@ impl Type {
|
||||||
// to the desired type.
|
// to the desired type.
|
||||||
*tipo.borrow_mut() = TypeVar::Link {
|
*tipo.borrow_mut() = TypeVar::Link {
|
||||||
tipo: Rc::new(Self::App {
|
tipo: Rc::new(Self::App {
|
||||||
|
public,
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
module: module.to_owned(),
|
module: module.to_owned(),
|
||||||
args: args.clone(),
|
args: args.clone(),
|
||||||
public,
|
alias: alias.to_owned(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
Some(args)
|
Some(args)
|
||||||
|
@ -465,7 +573,7 @@ pub fn lookup_data_type_by_tipo(
|
||||||
|
|
||||||
data_types.get(&data_type_key).map(|item| (*item).clone())
|
data_types.get(&data_type_key).map(|item| (*item).clone())
|
||||||
}
|
}
|
||||||
Type::Var { tipo } => {
|
Type::Var { tipo, .. } => {
|
||||||
if let TypeVar::Link { tipo } = &*tipo.borrow() {
|
if let TypeVar::Link { tipo } = &*tipo.borrow() {
|
||||||
lookup_data_type_by_tipo(data_types, tipo)
|
lookup_data_type_by_tipo(data_types, tipo)
|
||||||
} else {
|
} else {
|
||||||
|
@ -500,11 +608,11 @@ pub fn get_arg_type_name(tipo: &Type) -> String {
|
||||||
let inner_args = args.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
|
let inner_args = args.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
|
||||||
format!("{}_{}", name, inner_args.join("_"))
|
format!("{}_{}", name, inner_args.join("_"))
|
||||||
}
|
}
|
||||||
Type::Var { tipo } => match tipo.borrow().clone() {
|
Type::Var { tipo, .. } => match tipo.borrow().clone() {
|
||||||
TypeVar::Link { tipo } => get_arg_type_name(tipo.as_ref()),
|
TypeVar::Link { tipo } => get_arg_type_name(tipo.as_ref()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, .. } => {
|
||||||
let inner_args = elems.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
|
let inner_args = elems.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
|
||||||
inner_args.join("_")
|
inner_args.join("_")
|
||||||
}
|
}
|
||||||
|
@ -545,6 +653,7 @@ pub fn convert_opaque_type(
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
|
alias,
|
||||||
} => {
|
} => {
|
||||||
let mut new_args = vec![];
|
let mut new_args = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -556,10 +665,11 @@ pub fn convert_opaque_type(
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
args: new_args,
|
args: new_args,
|
||||||
|
alias: alias.clone(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, alias } => {
|
||||||
let mut new_args = vec![];
|
let mut new_args = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = convert_opaque_type(arg, data_types, deep);
|
let arg = convert_opaque_type(arg, data_types, deep);
|
||||||
|
@ -571,23 +681,28 @@ pub fn convert_opaque_type(
|
||||||
Type::Fn {
|
Type::Fn {
|
||||||
args: new_args,
|
args: new_args,
|
||||||
ret,
|
ret,
|
||||||
|
alias: alias.clone(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
Type::Var { tipo: var_tipo } => {
|
Type::Var { tipo: var_tipo, .. } => {
|
||||||
if let TypeVar::Link { tipo } = &var_tipo.borrow().clone() {
|
if let TypeVar::Link { tipo } = &var_tipo.borrow().clone() {
|
||||||
convert_opaque_type(tipo, data_types, deep)
|
convert_opaque_type(tipo, data_types, deep)
|
||||||
} else {
|
} else {
|
||||||
t.clone()
|
t.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, alias } => {
|
||||||
let mut new_elems = vec![];
|
let mut new_elems = vec![];
|
||||||
for arg in elems {
|
for arg in elems {
|
||||||
let arg = convert_opaque_type(arg, data_types, deep);
|
let arg = convert_opaque_type(arg, data_types, deep);
|
||||||
new_elems.push(arg);
|
new_elems.push(arg);
|
||||||
}
|
}
|
||||||
Type::Tuple { elems: new_elems }.into()
|
Type::Tuple {
|
||||||
|
elems: new_elems,
|
||||||
|
alias: alias.clone(),
|
||||||
|
}
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,6 +738,7 @@ pub fn find_and_replace_generics(
|
||||||
public,
|
public,
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
|
alias,
|
||||||
} => {
|
} => {
|
||||||
let mut new_args = vec![];
|
let mut new_args = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -634,10 +750,11 @@ pub fn find_and_replace_generics(
|
||||||
public: *public,
|
public: *public,
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
alias: alias.clone(),
|
||||||
};
|
};
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, alias } => {
|
||||||
let mut new_args = vec![];
|
let mut new_args = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg = find_and_replace_generics(arg, mono_types);
|
let arg = find_and_replace_generics(arg, mono_types);
|
||||||
|
@ -649,20 +766,24 @@ pub fn find_and_replace_generics(
|
||||||
let t = Type::Fn {
|
let t = Type::Fn {
|
||||||
args: new_args,
|
args: new_args,
|
||||||
ret,
|
ret,
|
||||||
|
alias: alias.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, alias } => {
|
||||||
let mut new_elems = vec![];
|
let mut new_elems = vec![];
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
let elem = find_and_replace_generics(elem, mono_types);
|
let elem = find_and_replace_generics(elem, mono_types);
|
||||||
new_elems.push(elem);
|
new_elems.push(elem);
|
||||||
}
|
}
|
||||||
let t = Type::Tuple { elems: new_elems };
|
let t = Type::Tuple {
|
||||||
|
elems: new_elems,
|
||||||
|
alias: alias.clone(),
|
||||||
|
};
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
Type::Var { tipo: var_tipo } => {
|
Type::Var { tipo: var_tipo, .. } => {
|
||||||
let var_type = var_tipo.as_ref().borrow().clone();
|
let var_type = var_tipo.as_ref().borrow().clone();
|
||||||
|
|
||||||
match var_type {
|
match var_type {
|
||||||
|
@ -835,6 +956,7 @@ impl TypeVar {
|
||||||
var => {
|
var => {
|
||||||
vec![Type::Var {
|
vec![Type::Var {
|
||||||
tipo: RefCell::new(var.clone()).into(),
|
tipo: RefCell::new(var.clone()).into(),
|
||||||
|
alias: None,
|
||||||
}
|
}
|
||||||
.into()]
|
.into()]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::{
|
use super::{
|
||||||
collections::{HashMap, HashSet},
|
error::{Error, Snippet, Warning},
|
||||||
ops::Deref,
|
exhaustive::{simplify, Matrix, PatternStack},
|
||||||
rc::Rc,
|
hydrator::Hydrator,
|
||||||
|
AccessorsMap, RecordAccessor, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
|
||||||
|
ValueConstructorVariant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, CallArg, DataType, Definition, Function, ModuleConstant, ModuleKind,
|
Annotation, CallArg, DataType, Definition, Function, ModuleConstant, ModuleKind,
|
||||||
|
@ -11,16 +12,13 @@ use crate::{
|
||||||
UnqualifiedImport, UntypedArg, UntypedDefinition, Use, Validator, PIPE_VARIABLE,
|
UnqualifiedImport, UntypedArg, UntypedDefinition, Use, Validator, PIPE_VARIABLE,
|
||||||
},
|
},
|
||||||
builtins::{function, generic_var, tuple, unbound_var},
|
builtins::{function, generic_var, tuple, unbound_var},
|
||||||
tipo::fields::FieldMap,
|
tipo::{fields::FieldMap, TypeAliasAnnotation},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
use std::{
|
||||||
use super::{
|
collections::{HashMap, HashSet},
|
||||||
error::{Error, Snippet, Warning},
|
ops::Deref,
|
||||||
exhaustive::{simplify, Matrix, PatternStack},
|
rc::Rc,
|
||||||
hydrator::Hydrator,
|
|
||||||
AccessorsMap, RecordAccessor, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
|
|
||||||
ValueConstructorVariant,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -119,7 +117,7 @@ impl<'a> Environment<'a> {
|
||||||
fn_location: Span,
|
fn_location: Span,
|
||||||
call_location: Span,
|
call_location: Span,
|
||||||
) -> Result<(Vec<Rc<Type>>, Rc<Type>), Error> {
|
) -> Result<(Vec<Rc<Type>>, Rc<Type>), Error> {
|
||||||
if let Type::Var { tipo } = tipo.deref() {
|
if let Type::Var { tipo, .. } = tipo.deref() {
|
||||||
let new_value = match tipo.borrow().deref() {
|
let new_value = match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo, .. } => {
|
TypeVar::Link { tipo, .. } => {
|
||||||
return self.match_fun_type(tipo.clone(), arity, fn_location, call_location);
|
return self.match_fun_type(tipo.clone(), arity, fn_location, call_location);
|
||||||
|
@ -145,7 +143,7 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Type::Fn { args, ret } = tipo.deref() {
|
if let Type::Fn { args, ret, .. } = tipo.deref() {
|
||||||
return if args.len() != arity {
|
return if args.len() != arity {
|
||||||
Err(Error::IncorrectFunctionCallArity {
|
Err(Error::IncorrectFunctionCallArity {
|
||||||
expected: args.len(),
|
expected: args.len(),
|
||||||
|
@ -549,6 +547,7 @@ impl<'a> Environment<'a> {
|
||||||
name,
|
name,
|
||||||
module,
|
module,
|
||||||
args,
|
args,
|
||||||
|
alias,
|
||||||
} => {
|
} => {
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -558,15 +557,26 @@ impl<'a> Environment<'a> {
|
||||||
public: *public,
|
public: *public,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
|
alias: alias.clone(),
|
||||||
args,
|
args,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Var { tipo } => {
|
Type::Var { tipo, alias } => {
|
||||||
match tipo.borrow().deref() {
|
match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo } => return self.instantiate(tipo.clone(), ids, hydrator),
|
TypeVar::Link { tipo } => {
|
||||||
|
return Type::with_alias(
|
||||||
|
self.instantiate(tipo.clone(), ids, hydrator),
|
||||||
|
alias.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
TypeVar::Unbound { .. } => return Rc::new(Type::Var { tipo: tipo.clone() }),
|
TypeVar::Unbound { .. } => {
|
||||||
|
return Rc::new(Type::Var {
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
alias: alias.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
TypeVar::Generic { id } => match ids.get(id) {
|
TypeVar::Generic { id } => match ids.get(id) {
|
||||||
Some(t) => return t.clone(),
|
Some(t) => return t.clone(),
|
||||||
|
@ -576,27 +586,34 @@ impl<'a> Environment<'a> {
|
||||||
let v = self.new_unbound_var();
|
let v = self.new_unbound_var();
|
||||||
ids.insert(*id, v.clone());
|
ids.insert(*id, v.clone());
|
||||||
return v;
|
return v;
|
||||||
} else {
|
|
||||||
// tracing::trace!(id = id, "not_instantiating_rigid_type_var")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Rc::new(Type::Var { tipo: tipo.clone() })
|
Rc::new(Type::Var {
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
alias: alias.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Fn { args, ret, .. } => function(
|
Type::Fn { args, ret, alias } => Type::with_alias(
|
||||||
args.iter()
|
function(
|
||||||
.map(|t| self.instantiate(t.clone(), ids, hydrator))
|
args.iter()
|
||||||
.collect(),
|
.map(|t| self.instantiate(t.clone(), ids, hydrator))
|
||||||
self.instantiate(ret.clone(), ids, hydrator),
|
.collect(),
|
||||||
|
self.instantiate(ret.clone(), ids, hydrator),
|
||||||
|
),
|
||||||
|
alias.clone(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Type::Tuple { elems } => tuple(
|
Type::Tuple { elems, alias } => Type::with_alias(
|
||||||
elems
|
tuple(
|
||||||
.iter()
|
elems
|
||||||
.map(|t| self.instantiate(t.clone(), ids, hydrator))
|
.iter()
|
||||||
.collect(),
|
.map(|t| self.instantiate(t.clone(), ids, hydrator))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
alias.clone(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,6 +998,7 @@ impl<'a> Environment<'a> {
|
||||||
module: module.to_owned(),
|
module: module.to_owned(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
args: parameters.clone(),
|
args: parameters.clone(),
|
||||||
|
alias: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
hydrators.insert(name.to_string(), hydrator);
|
hydrators.insert(name.to_string(), hydrator);
|
||||||
|
@ -1024,7 +1042,18 @@ impl<'a> Environment<'a> {
|
||||||
hydrator.disallow_new_type_variables();
|
hydrator.disallow_new_type_variables();
|
||||||
|
|
||||||
// Create the type that the alias resolves to
|
// Create the type that the alias resolves to
|
||||||
let tipo = hydrator.type_from_annotation(resolved_type, self)?;
|
let tipo = hydrator
|
||||||
|
.type_from_annotation(resolved_type, self)?
|
||||||
|
.as_ref()
|
||||||
|
.to_owned()
|
||||||
|
.set_alias(Some(
|
||||||
|
TypeAliasAnnotation {
|
||||||
|
alias: name.to_string(),
|
||||||
|
parameters: args.to_vec(),
|
||||||
|
annotation: resolved_type.clone(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
|
||||||
self.insert_type_constructor(
|
self.insert_type_constructor(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
@ -1353,13 +1382,13 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collapse right hand side type links. Left hand side will be collapsed in the next block.
|
// Collapse right hand side type links. Left hand side will be collapsed in the next block.
|
||||||
if let Type::Var { tipo } = t2.deref() {
|
if let Type::Var { tipo, .. } = t2.deref() {
|
||||||
if let TypeVar::Link { tipo } = tipo.borrow().deref() {
|
if let TypeVar::Link { tipo, .. } = tipo.borrow().deref() {
|
||||||
return self.unify(t1, tipo.clone(), location, allow_cast);
|
return self.unify(t1, tipo.clone(), location, allow_cast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Type::Var { tipo } = t1.deref() {
|
if let Type::Var { tipo, .. } = t1.deref() {
|
||||||
enum Action {
|
enum Action {
|
||||||
Unify(Rc<Type>),
|
Unify(Rc<Type>),
|
||||||
CouldNotUnify,
|
CouldNotUnify,
|
||||||
|
@ -1375,7 +1404,7 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeVar::Generic { id } => {
|
TypeVar::Generic { id } => {
|
||||||
if let Type::Var { tipo } = t2.deref() {
|
if let Type::Var { tipo, .. } = t2.deref() {
|
||||||
if tipo.borrow().is_unbound() {
|
if tipo.borrow().is_unbound() {
|
||||||
*tipo.borrow_mut() = TypeVar::Generic { id: *id };
|
*tipo.borrow_mut() = TypeVar::Generic { id: *id };
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -1642,10 +1671,10 @@ pub enum EntityKind {
|
||||||
/// could cause naively-implemented type checking to diverge.
|
/// could cause naively-implemented type checking to diverge.
|
||||||
/// While traversing the type tree.
|
/// While traversing the type tree.
|
||||||
fn unify_unbound_type(tipo: Rc<Type>, own_id: u64, location: Span) -> Result<(), Error> {
|
fn unify_unbound_type(tipo: Rc<Type>, own_id: u64, location: Span) -> Result<(), Error> {
|
||||||
if let Type::Var { tipo } = tipo.deref() {
|
if let Type::Var { tipo, .. } = tipo.deref() {
|
||||||
let new_value = match tipo.borrow().deref() {
|
let new_value = match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo, .. } => {
|
TypeVar::Link { tipo, .. } => {
|
||||||
return unify_unbound_type(tipo.clone(), own_id, location)
|
return unify_unbound_type(tipo.clone(), own_id, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeVar::Unbound { id } => {
|
TypeVar::Unbound { id } => {
|
||||||
|
@ -1674,7 +1703,7 @@ fn unify_unbound_type(tipo: Rc<Type>, own_id: u64, location: Span) -> Result<(),
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, .. } => {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
unify_unbound_type(arg.clone(), own_id, location)?;
|
unify_unbound_type(arg.clone(), own_id, location)?;
|
||||||
}
|
}
|
||||||
|
@ -1769,7 +1798,7 @@ pub(super) fn assert_no_labeled_arguments<A>(args: &[CallArg<A>]) -> Option<(Spa
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn collapse_links(t: Rc<Type>) -> Rc<Type> {
|
pub(super) fn collapse_links(t: Rc<Type>) -> Rc<Type> {
|
||||||
if let Type::Var { tipo } = t.deref() {
|
if let Type::Var { tipo, .. } = t.deref() {
|
||||||
if let TypeVar::Link { tipo } = tipo.borrow().deref() {
|
if let TypeVar::Link { tipo } = tipo.borrow().deref() {
|
||||||
return tipo.clone();
|
return tipo.clone();
|
||||||
}
|
}
|
||||||
|
@ -1811,17 +1840,24 @@ fn get_compatible_record_fields<A>(
|
||||||
#[allow(clippy::only_used_in_recursion)]
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
|
pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
|
||||||
match t.deref() {
|
match t.deref() {
|
||||||
Type::Var { tipo } => match tipo.borrow().deref() {
|
Type::Var { tipo, alias } => Type::with_alias(
|
||||||
TypeVar::Unbound { id } => generic_var(*id),
|
match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo } => generalise(tipo.clone(), ctx_level),
|
TypeVar::Unbound { id } => generic_var(*id),
|
||||||
TypeVar::Generic { .. } => Rc::new(Type::Var { tipo: tipo.clone() }),
|
TypeVar::Link { tipo } => generalise(tipo.clone(), ctx_level),
|
||||||
},
|
TypeVar::Generic { .. } => Rc::new(Type::Var {
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
alias.clone(),
|
||||||
|
),
|
||||||
|
|
||||||
Type::App {
|
Type::App {
|
||||||
public,
|
public,
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
|
alias,
|
||||||
} => {
|
} => {
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1833,21 +1869,28 @@ pub(crate) fn generalise(t: Rc<Type>, ctx_level: usize) -> Rc<Type> {
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
args,
|
args,
|
||||||
|
alias: alias.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Fn { args, ret } => function(
|
Type::Fn { args, ret, alias } => Type::with_alias(
|
||||||
args.iter()
|
function(
|
||||||
.map(|t| generalise(t.clone(), ctx_level))
|
args.iter()
|
||||||
.collect(),
|
.map(|t| generalise(t.clone(), ctx_level))
|
||||||
generalise(ret.clone(), ctx_level),
|
.collect(),
|
||||||
|
generalise(ret.clone(), ctx_level),
|
||||||
|
),
|
||||||
|
alias.clone(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Type::Tuple { elems } => tuple(
|
Type::Tuple { elems, alias } => Type::with_alias(
|
||||||
elems
|
tuple(
|
||||||
.iter()
|
elems
|
||||||
.map(|t| generalise(t.clone(), ctx_level))
|
.iter()
|
||||||
.collect(),
|
.map(|t| generalise(t.clone(), ctx_level))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
alias.clone(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,11 @@ pub(super) fn simplify(
|
||||||
Ok(Pattern::Constructor(
|
Ok(Pattern::Constructor(
|
||||||
TUPLE_NAME.to_string(),
|
TUPLE_NAME.to_string(),
|
||||||
vec![tipo::ValueConstructor {
|
vec![tipo::ValueConstructor {
|
||||||
tipo: tipo::Type::Tuple { elems: vec![] }.into(),
|
tipo: tipo::Type::Tuple {
|
||||||
|
elems: vec![],
|
||||||
|
alias: None,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
public: true,
|
public: true,
|
||||||
variant: tipo::ValueConstructorVariant::Record {
|
variant: tipo::ValueConstructorVariant::Record {
|
||||||
name: TUPLE_NAME.to_string(),
|
name: TUPLE_NAME.to_string(),
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
use std::{collections::HashMap, rc::Rc};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
ast::Annotation,
|
|
||||||
builtins::{function, tuple},
|
|
||||||
tipo::Span,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
environment::Environment,
|
environment::Environment,
|
||||||
error::{Error, Warning},
|
error::{Error, Warning},
|
||||||
Type, TypeConstructor,
|
Type, TypeConstructor,
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
ast::Annotation,
|
||||||
|
builtins::{function, tuple},
|
||||||
|
tipo::Span,
|
||||||
|
};
|
||||||
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
/// The Hydrator takes an AST representing a type (i.e. a type annotation
|
/// The Hydrator takes an AST representing a type (i.e. a type annotation
|
||||||
/// for a function argument) and returns a Type for that annotation.
|
/// for a function argument) and returns a Type for that annotation.
|
||||||
|
|
|
@ -382,10 +382,14 @@ fn infer_definition(
|
||||||
.scope
|
.scope
|
||||||
.get_mut(&f.name)
|
.get_mut(&f.name)
|
||||||
.expect("Could not find preregistered type for test");
|
.expect("Could not find preregistered type for test");
|
||||||
if let Type::Fn { ref ret, .. } = scope.tipo.as_ref() {
|
if let Type::Fn {
|
||||||
|
ref ret, ref alias, ..
|
||||||
|
} = scope.tipo.as_ref()
|
||||||
|
{
|
||||||
scope.tipo = Rc::new(Type::Fn {
|
scope.tipo = Rc::new(Type::Fn {
|
||||||
ret: ret.clone(),
|
ret: ret.clone(),
|
||||||
args: vec![inferred_inner_type.clone()],
|
args: vec![inferred_inner_type.clone()],
|
||||||
|
alias: alias.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +786,7 @@ fn infer_fuzzer(
|
||||||
module, name, args, ..
|
module, name, args, ..
|
||||||
} if module.is_empty() && name == "Option" && args.len() == 1 => {
|
} if module.is_empty() && name == "Option" && args.len() == 1 => {
|
||||||
match args.first().expect("args.len() == 1").borrow() {
|
match args.first().expect("args.len() == 1").borrow() {
|
||||||
Type::Tuple { elems } if elems.len() == 2 => {
|
Type::Tuple { elems, .. } if elems.len() == 2 => {
|
||||||
let wrapped = elems.get(1).expect("Tuple has two elements");
|
let wrapped = elems.get(1).expect("Tuple has two elements");
|
||||||
|
|
||||||
// NOTE: Although we've drilled through the Fuzzer structure to get here,
|
// NOTE: Although we've drilled through the Fuzzer structure to get here,
|
||||||
|
@ -843,7 +847,7 @@ fn annotate_fuzzer(tipo: &Type, location: &Span) -> Result<Annotation, Error> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, .. } => {
|
||||||
let elems = elems
|
let elems = elems
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| annotate_fuzzer(arg, location))
|
.map(|arg| annotate_fuzzer(arg, location))
|
||||||
|
@ -854,7 +858,7 @@ fn annotate_fuzzer(tipo: &Type, location: &Span) -> Result<Annotation, Error> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Var { tipo } => match &*tipo.deref().borrow() {
|
Type::Var { tipo, .. } => match &*tipo.deref().borrow() {
|
||||||
TypeVar::Link { tipo } => annotate_fuzzer(tipo, location),
|
TypeVar::Link { tipo } => annotate_fuzzer(tipo, location),
|
||||||
_ => Err(Error::GenericLeftAtBoundary {
|
_ => Err(Error::GenericLeftAtBoundary {
|
||||||
location: *location,
|
location: *location,
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
//! Type inference and checking of patterns used in case expressions
|
//! Type inference and checking of patterns used in case expressions
|
||||||
//! and variables bindings.
|
//! and variables bindings.
|
||||||
use std::{
|
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
ops::Deref,
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
environment::{assert_no_labeled_arguments, collapse_links, EntityKind, Environment},
|
environment::{assert_no_labeled_arguments, collapse_links, EntityKind, Environment},
|
||||||
error::{Error, Warning},
|
error::{Error, Warning},
|
||||||
|
@ -18,6 +10,12 @@ use crate::{
|
||||||
ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern},
|
ast::{CallArg, Pattern, Span, TypedPattern, UntypedPattern},
|
||||||
builtins::{int, list, tuple},
|
builtins::{int, list, tuple},
|
||||||
};
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
ops::Deref,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct PatternTyper<'a, 'b> {
|
pub struct PatternTyper<'a, 'b> {
|
||||||
environment: &'a mut Environment<'b>,
|
environment: &'a mut Environment<'b>,
|
||||||
|
@ -238,7 +236,9 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
},
|
},
|
||||||
|
|
||||||
Pattern::Tuple { elems, location } => match collapse_links(tipo.clone()).deref() {
|
Pattern::Tuple { elems, location } => match collapse_links(tipo.clone()).deref() {
|
||||||
Type::Tuple { elems: type_elems } => {
|
Type::Tuple {
|
||||||
|
elems: type_elems, ..
|
||||||
|
} => {
|
||||||
if elems.len() != type_elems.len() {
|
if elems.len() != type_elems.len() {
|
||||||
return Err(Error::IncorrectTupleArity {
|
return Err(Error::IncorrectTupleArity {
|
||||||
location,
|
location,
|
||||||
|
@ -403,7 +403,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
);
|
);
|
||||||
|
|
||||||
match instantiated_constructor_type.deref() {
|
match instantiated_constructor_type.deref() {
|
||||||
Type::Fn { args, ret } => {
|
Type::Fn { args, ret, .. } => {
|
||||||
if with_spread && has_no_fields {
|
if with_spread && has_no_fields {
|
||||||
if pattern_args.len() == args.len() {
|
if pattern_args.len() == args.len() {
|
||||||
return Err(Error::UnnecessarySpreadOperator {
|
return Err(Error::UnnecessarySpreadOperator {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use std::{collections::HashMap, rc::Rc};
|
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
use super::{Type, TypeVar};
|
use super::{Type, TypeVar};
|
||||||
use crate::{
|
use crate::{
|
||||||
docvec,
|
docvec,
|
||||||
pretty::{nil, *},
|
pretty::{nil, *},
|
||||||
|
tipo::{Annotation, TypeAliasAnnotation},
|
||||||
};
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
const INDENT: isize = 2;
|
const INDENT: isize = 2;
|
||||||
|
|
||||||
|
@ -48,6 +47,17 @@ impl Printer {
|
||||||
// Is this possible? The lifetime would have to go through the Rc<Refcell<Type>>
|
// Is this possible? The lifetime would have to go through the Rc<Refcell<Type>>
|
||||||
// for TypeVar::Link'd types.
|
// for TypeVar::Link'd types.
|
||||||
pub fn print<'a>(&mut self, typ: &Type) -> Document<'a> {
|
pub fn print<'a>(&mut self, typ: &Type) -> Document<'a> {
|
||||||
|
if let Some(TypeAliasAnnotation {
|
||||||
|
alias,
|
||||||
|
parameters,
|
||||||
|
annotation,
|
||||||
|
}) = typ.alias().as_deref()
|
||||||
|
{
|
||||||
|
if let Some(resolved_parameters) = resolve_alias(parameters, annotation, typ) {
|
||||||
|
return self.type_alias_doc(alias.to_string(), resolved_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match typ {
|
match typ {
|
||||||
Type::App {
|
Type::App {
|
||||||
name, args, module, ..
|
name, args, module, ..
|
||||||
|
@ -67,7 +77,7 @@ impl Printer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Fn { args, ret } => "fn("
|
Type::Fn { args, ret, .. } => "fn("
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(self.args_to_aiken_doc(args))
|
.append(self.args_to_aiken_doc(args))
|
||||||
.append(") ->")
|
.append(") ->")
|
||||||
|
@ -79,6 +89,26 @@ impl Printer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_alias_doc<'a>(&mut self, alias: String, parameters: Vec<Rc<Type>>) -> Document<'a> {
|
||||||
|
let doc = Document::String(alias);
|
||||||
|
|
||||||
|
if !parameters.is_empty() {
|
||||||
|
doc.append(
|
||||||
|
break_("", "")
|
||||||
|
.append(concat(Itertools::intersperse(
|
||||||
|
parameters.iter().map(|t| self.print(t)),
|
||||||
|
break_(",", ", "),
|
||||||
|
)))
|
||||||
|
.nest(INDENT)
|
||||||
|
.append(break_(",", ""))
|
||||||
|
.group()
|
||||||
|
.surround("<", ">"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn name_clashes_if_unqualified(&mut self, tipo: &String, module: &String) -> bool {
|
fn name_clashes_if_unqualified(&mut self, tipo: &String, module: &String) -> bool {
|
||||||
match self.printed_types.get(tipo) {
|
match self.printed_types.get(tipo) {
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -167,15 +197,79 @@ fn qualify_type_name(module: &String, typ_name: &str) -> Document<'static> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_alias(
|
||||||
|
parameters: &[String],
|
||||||
|
annotation: &Annotation,
|
||||||
|
typ: &Type,
|
||||||
|
) -> Option<Vec<Rc<Type>>> {
|
||||||
|
let mut types = Vec::new();
|
||||||
|
|
||||||
|
fn resolve_one(parameter: &str, annotation: &Annotation, typ: Rc<Type>) -> Option<Rc<Type>> {
|
||||||
|
match (annotation, typ.as_ref()) {
|
||||||
|
(
|
||||||
|
Annotation::Fn {
|
||||||
|
arguments: args,
|
||||||
|
ret,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
Type::Fn {
|
||||||
|
args: t_args,
|
||||||
|
ret: t_ret,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let mut result = resolve_one(parameter, ret, t_ret.clone());
|
||||||
|
for (ann, t) in args.iter().zip(t_args) {
|
||||||
|
result = result.or_else(|| resolve_one(parameter, ann, t.clone()));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
Annotation::Constructor {
|
||||||
|
arguments: args, ..
|
||||||
|
},
|
||||||
|
Type::App { args: t_args, .. },
|
||||||
|
) => {
|
||||||
|
let mut result = None;
|
||||||
|
for (ann, t) in args.iter().zip(t_args) {
|
||||||
|
result = result.or_else(|| resolve_one(parameter, ann, t.clone()));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
(Annotation::Tuple { elems, .. }, Type::Tuple { elems: t_elems, .. }) => {
|
||||||
|
let mut result = None;
|
||||||
|
for (ann, t) in elems.iter().zip(t_elems) {
|
||||||
|
result = result.or_else(|| resolve_one(parameter, ann, t.clone()));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
(Annotation::Var { name, .. }, ..) if name == parameter => Some(typ),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rc: Rc<Type> = typ.to_owned().into();
|
||||||
|
|
||||||
|
for parameter in parameters {
|
||||||
|
types.push(resolve_one(parameter, annotation, rc.clone())?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(types)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
|
|
||||||
use crate::builtins::{function, int};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::{
|
||||||
|
builtins::{function, int},
|
||||||
|
tipo::Span,
|
||||||
|
};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn next_letter_test() {
|
fn next_letter_test() {
|
||||||
|
@ -275,6 +369,7 @@ mod tests {
|
||||||
name: "Int".to_string(),
|
name: "Int".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None
|
||||||
},
|
},
|
||||||
"Int",
|
"Int",
|
||||||
);
|
);
|
||||||
|
@ -283,18 +378,21 @@ mod tests {
|
||||||
module: "".to_string(),
|
module: "".to_string(),
|
||||||
name: "Pair".to_string(),
|
name: "Pair".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
|
alias: None,
|
||||||
args: vec![
|
args: vec![
|
||||||
Rc::new(Type::App {
|
Rc::new(Type::App {
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Int".to_string(),
|
name: "Int".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None
|
||||||
}),
|
}),
|
||||||
Rc::new(Type::App {
|
Rc::new(Type::App {
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Bool".to_string(),
|
name: "Bool".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
alias: None
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -308,12 +406,14 @@ mod tests {
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Int".to_string(),
|
name: "Int".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
|
alias: None,
|
||||||
}),
|
}),
|
||||||
Rc::new(Type::App {
|
Rc::new(Type::App {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Bool".to_string(),
|
name: "Bool".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
|
alias: None,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
ret: Rc::new(Type::App {
|
ret: Rc::new(Type::App {
|
||||||
|
@ -321,14 +421,18 @@ mod tests {
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Bool".to_string(),
|
name: "Bool".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
|
alias: None,
|
||||||
}),
|
}),
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
"fn(Int, Bool) -> Bool",
|
"fn(Int, Bool) -> Bool",
|
||||||
);
|
);
|
||||||
assert_string!(
|
assert_string!(
|
||||||
Type::Var {
|
Type::Var {
|
||||||
|
alias: None,
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Link {
|
tipo: Rc::new(RefCell::new(TypeVar::Link {
|
||||||
tipo: Rc::new(Type::App {
|
tipo: Rc::new(Type::App {
|
||||||
|
alias: None,
|
||||||
args: vec![],
|
args: vec![],
|
||||||
module: "whatever".to_string(),
|
module: "whatever".to_string(),
|
||||||
name: "Int".to_string(),
|
name: "Int".to_string(),
|
||||||
|
@ -341,6 +445,7 @@ mod tests {
|
||||||
assert_string!(
|
assert_string!(
|
||||||
Type::Var {
|
Type::Var {
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 2231 })),
|
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 2231 })),
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
"a",
|
"a",
|
||||||
);
|
);
|
||||||
|
@ -348,9 +453,11 @@ mod tests {
|
||||||
function(
|
function(
|
||||||
vec![Rc::new(Type::Var {
|
vec![Rc::new(Type::Var {
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 78 })),
|
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 78 })),
|
||||||
|
alias: None,
|
||||||
})],
|
})],
|
||||||
Rc::new(Type::Var {
|
Rc::new(Type::Var {
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 2 })),
|
tipo: Rc::new(RefCell::new(TypeVar::Unbound { id: 2 })),
|
||||||
|
alias: None,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
"fn(a) -> b",
|
"fn(a) -> b",
|
||||||
|
@ -359,13 +466,152 @@ mod tests {
|
||||||
function(
|
function(
|
||||||
vec![Rc::new(Type::Var {
|
vec![Rc::new(Type::Var {
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 78 })),
|
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 78 })),
|
||||||
|
alias: None,
|
||||||
})],
|
})],
|
||||||
Rc::new(Type::Var {
|
Rc::new(Type::Var {
|
||||||
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 2 })),
|
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 2 })),
|
||||||
|
alias: None,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
"fn(a) -> b",
|
"fn(a) -> b",
|
||||||
);
|
);
|
||||||
|
assert_string!(
|
||||||
|
Type::Fn {
|
||||||
|
args: vec![Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
|
})],
|
||||||
|
ret: Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "Option".to_string(),
|
||||||
|
args: vec![Rc::new(Type::Tuple {
|
||||||
|
elems: vec![
|
||||||
|
Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "Bool".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
alias: None,
|
||||||
|
})],
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
alias: Some(Rc::new(TypeAliasAnnotation {
|
||||||
|
alias: "Fuzzer".to_string(),
|
||||||
|
parameters: vec!["a".to_string(),],
|
||||||
|
annotation: Annotation::Fn {
|
||||||
|
location: Span::empty(),
|
||||||
|
arguments: vec![Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
},],
|
||||||
|
ret: Box::new(Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "Option".to_string(),
|
||||||
|
arguments: vec![Annotation::Tuple {
|
||||||
|
location: Span::empty(),
|
||||||
|
elems: vec![
|
||||||
|
Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
},
|
||||||
|
Annotation::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
"Fuzzer<Bool>",
|
||||||
|
);
|
||||||
|
assert_string!(
|
||||||
|
Type::Fn {
|
||||||
|
args: vec![Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
|
})],
|
||||||
|
ret: Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "Option".to_string(),
|
||||||
|
args: vec![Rc::new(Type::Tuple {
|
||||||
|
elems: vec![
|
||||||
|
Rc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
module: "".to_string(),
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
Rc::new(Type::Var {
|
||||||
|
tipo: Rc::new(RefCell::new(TypeVar::Generic { id: 0 })),
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
alias: None,
|
||||||
|
})],
|
||||||
|
alias: None,
|
||||||
|
}),
|
||||||
|
alias: Some(Rc::new(TypeAliasAnnotation {
|
||||||
|
alias: "Fuzzer".to_string(),
|
||||||
|
parameters: vec!["a".to_string(),],
|
||||||
|
annotation: Annotation::Fn {
|
||||||
|
location: Span::empty(),
|
||||||
|
arguments: vec![Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
},],
|
||||||
|
ret: Box::new(Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "Option".to_string(),
|
||||||
|
arguments: vec![Annotation::Tuple {
|
||||||
|
location: Span::empty(),
|
||||||
|
elems: vec![
|
||||||
|
Annotation::Constructor {
|
||||||
|
location: Span::empty(),
|
||||||
|
module: None,
|
||||||
|
name: "PRNG".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
},
|
||||||
|
Annotation::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: "a".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
"Fuzzer<a>",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
use crate::quickfix::Quickfix;
|
use self::lsp_project::LspProject;
|
||||||
use std::{
|
use crate::{
|
||||||
collections::{HashMap, HashSet},
|
cast::{cast_notification, cast_request},
|
||||||
fs,
|
error::Error as ServerError,
|
||||||
path::{Path, PathBuf},
|
quickfix,
|
||||||
|
quickfix::Quickfix,
|
||||||
|
utils::{
|
||||||
|
path_to_uri, span_to_lsp_range, text_edit_replace, uri_to_module_name,
|
||||||
|
COMPILING_PROGRESS_TOKEN, CREATE_COMPILING_PROGRESS_TOKEN,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{Definition, Located, ModuleKind, Span, Use},
|
ast::{Definition, Located, ModuleKind, Span, Use},
|
||||||
error::ExtraData,
|
error::ExtraData,
|
||||||
|
@ -32,19 +36,12 @@ use lsp_types::{
|
||||||
DocumentFormattingParams, InitializeParams, TextEdit,
|
DocumentFormattingParams, InitializeParams, TextEdit,
|
||||||
};
|
};
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
|
use std::{
|
||||||
use crate::{
|
collections::{HashMap, HashSet},
|
||||||
cast::{cast_notification, cast_request},
|
fs,
|
||||||
error::Error as ServerError,
|
path::{Path, PathBuf},
|
||||||
quickfix,
|
|
||||||
utils::{
|
|
||||||
path_to_uri, span_to_lsp_range, text_edit_replace, uri_to_module_name,
|
|
||||||
COMPILING_PROGRESS_TOKEN, CREATE_COMPILING_PROGRESS_TOKEN,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::lsp_project::LspProject;
|
|
||||||
|
|
||||||
pub mod lsp_project;
|
pub mod lsp_project;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ impl Reference {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Tuple { elems } => Self {
|
Type::Tuple { elems, .. } => Self {
|
||||||
inner: format!(
|
inner: format!(
|
||||||
"Tuple{elems}",
|
"Tuple{elems}",
|
||||||
elems = Self::from_types(elems, type_parameters)
|
elems = Self::from_types(elems, type_parameters)
|
||||||
|
@ -150,7 +150,7 @@ impl Reference {
|
||||||
//
|
//
|
||||||
// Implementations below are only there for completeness. In practice, we should never
|
// Implementations below are only there for completeness. In practice, we should never
|
||||||
// end up creating references for 'Var' or 'Fn' in the context of blueprints.
|
// end up creating references for 'Var' or 'Fn' in the context of blueprints.
|
||||||
Type::Var { tipo } => match tipo.borrow().deref() {
|
Type::Var { tipo, .. } => match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo } => Self::from_type(tipo.as_ref(), type_parameters),
|
TypeVar::Link { tipo } => Self::from_type(tipo.as_ref(), type_parameters),
|
||||||
TypeVar::Generic { id } | TypeVar::Unbound { id } => {
|
TypeVar::Generic { id } | TypeVar::Unbound { id } => {
|
||||||
let tipo = type_parameters.get(id).unwrap();
|
let tipo = type_parameters.get(id).unwrap();
|
||||||
|
@ -158,7 +158,7 @@ impl Reference {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::Fn { args, ret } => Self {
|
Type::Fn { args, ret, .. } => Self {
|
||||||
inner: format!(
|
inner: format!(
|
||||||
"Fn{args}_{ret}",
|
"Fn{args}_{ret}",
|
||||||
args = Self::from_types(args, type_parameters),
|
args = Self::from_types(args, type_parameters),
|
||||||
|
|
|
@ -350,7 +350,7 @@ impl Annotated<Schema> {
|
||||||
annotated,
|
annotated,
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
Type::Tuple { elems } => {
|
Type::Tuple { elems, .. } => {
|
||||||
definitions.register(type_info, &type_parameters.clone(), |definitions| {
|
definitions.register(type_info, &type_parameters.clone(), |definitions| {
|
||||||
let elems = elems
|
let elems = elems
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -368,7 +368,7 @@ impl Annotated<Schema> {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Type::Var { tipo } => match tipo.borrow().deref() {
|
Type::Var { tipo, .. } => match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo } => {
|
TypeVar::Link { tipo } => {
|
||||||
Annotated::do_from_type(tipo, modules, type_parameters, definitions)
|
Annotated::do_from_type(tipo, modules, type_parameters, definitions)
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@ fn collect_type_parameters<'a>(
|
||||||
) {
|
) {
|
||||||
for (index, generic) in generics.iter().enumerate() {
|
for (index, generic) in generics.iter().enumerate() {
|
||||||
match &**generic {
|
match &**generic {
|
||||||
Type::Var { tipo } => match *tipo.borrow() {
|
Type::Var { tipo, .. } => match *tipo.borrow() {
|
||||||
TypeVar::Generic { id } => {
|
TypeVar::Generic { id } => {
|
||||||
type_parameters.insert(
|
type_parameters.insert(
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -11,6 +11,7 @@ Schema {
|
||||||
module: "test_module",
|
module: "test_module",
|
||||||
name: "Rational",
|
name: "Rational",
|
||||||
args: [],
|
args: [],
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,9 +19,11 @@ Schema {
|
||||||
module: "test_module",
|
module: "test_module",
|
||||||
name: "UUID",
|
name: "UUID",
|
||||||
args: [],
|
args: [],
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
Var {
|
Var {
|
||||||
tipo: RefCell {
|
tipo: RefCell {
|
||||||
|
@ -31,11 +33,14 @@ Schema {
|
||||||
module: "",
|
module: "",
|
||||||
name: "Int",
|
name: "Int",
|
||||||
args: [],
|
args: [],
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
alias: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue