feat: some new features
- tuples `#(Int, Int)` - `trace` and `trace("text")`
This commit is contained in:
parent
6066e3176c
commit
0823b78bf8
|
@ -385,12 +385,18 @@ pub enum Annotation {
|
||||||
location: Span,
|
location: Span,
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Tuple {
|
||||||
|
location: Span,
|
||||||
|
elems: Vec<Self>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Annotation {
|
impl Annotation {
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Annotation::Fn { location, .. }
|
Annotation::Fn { location, .. }
|
||||||
|
| Annotation::Tuple { location, .. }
|
||||||
| Annotation::Var { location, .. }
|
| Annotation::Var { location, .. }
|
||||||
| Annotation::Hole { location, .. }
|
| Annotation::Hole { location, .. }
|
||||||
| Annotation::Constructor { location, .. } => *location,
|
| Annotation::Constructor { location, .. } => *location,
|
||||||
|
@ -421,6 +427,19 @@ impl Annotation {
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
Annotation::Tuple { elems, location: _ } => match other {
|
||||||
|
Annotation::Tuple {
|
||||||
|
elems: o_elems,
|
||||||
|
location: _,
|
||||||
|
} => {
|
||||||
|
elems.len() == o_elems.len()
|
||||||
|
&& elems
|
||||||
|
.iter()
|
||||||
|
.zip(o_elems)
|
||||||
|
.all(|a| a.0.is_logically_equal(a.1))
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
Annotation::Fn {
|
Annotation::Fn {
|
||||||
arguments,
|
arguments,
|
||||||
ret,
|
ret,
|
||||||
|
@ -584,10 +603,11 @@ pub enum Pattern<Constructor, Type> {
|
||||||
with_spread: bool,
|
with_spread: bool,
|
||||||
tipo: Type,
|
tipo: Type,
|
||||||
},
|
},
|
||||||
// Tuple {
|
|
||||||
// location: Span,
|
Tuple {
|
||||||
// elems: Vec<Self>,
|
location: Span,
|
||||||
// },
|
elems: Vec<Self>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B> Pattern<A, B> {
|
impl<A, B> Pattern<A, B> {
|
||||||
|
@ -600,7 +620,7 @@ impl<A, B> Pattern<A, B> {
|
||||||
| Pattern::List { location, .. }
|
| Pattern::List { location, .. }
|
||||||
| Pattern::Discard { location, .. }
|
| Pattern::Discard { location, .. }
|
||||||
| Pattern::String { location, .. }
|
| Pattern::String { location, .. }
|
||||||
// | Pattern::Tuple { location, .. }
|
| Pattern::Tuple { location, .. }
|
||||||
// | Pattern::Concatenate { location, .. }
|
// | Pattern::Concatenate { location, .. }
|
||||||
| Pattern::Constructor { location, .. } => *location,
|
| Pattern::Constructor { location, .. } => *location,
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,6 +438,10 @@ pub fn byte_array() -> Arc<Type> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tuple(elems: Vec<Arc<Type>>) -> Arc<Type> {
|
||||||
|
Arc::new(Type::Tuple { elems })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bool() -> Arc<Type> {
|
pub fn bool() -> Arc<Type> {
|
||||||
Arc::new(Type::App {
|
Arc::new(Type::App {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
|
|
@ -91,12 +91,10 @@ pub enum TypedExpr {
|
||||||
kind: AssignmentKind,
|
kind: AssignmentKind,
|
||||||
},
|
},
|
||||||
|
|
||||||
Try {
|
Trace {
|
||||||
location: Span,
|
location: Span,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
value: Box<Self>,
|
|
||||||
then: Box<Self>,
|
then: Box<Self>,
|
||||||
pattern: Pattern<PatternConstructor, Arc<Type>>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
When {
|
When {
|
||||||
|
@ -130,11 +128,11 @@ pub enum TypedExpr {
|
||||||
constructor: ModuleValueConstructor,
|
constructor: ModuleValueConstructor,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Tuple {
|
Tuple {
|
||||||
// location: Span,
|
location: Span,
|
||||||
// tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
// elems: Vec<Self>,
|
elems: Vec<Self>,
|
||||||
// },
|
},
|
||||||
|
|
||||||
// TupleIndex {
|
// TupleIndex {
|
||||||
// location: Span,
|
// location: Span,
|
||||||
|
@ -166,7 +164,7 @@ impl TypedExpr {
|
||||||
match self {
|
match self {
|
||||||
Self::Negate { .. } => bool(),
|
Self::Negate { .. } => bool(),
|
||||||
Self::Var { constructor, .. } => constructor.tipo.clone(),
|
Self::Var { constructor, .. } => constructor.tipo.clone(),
|
||||||
Self::Try { then, .. } => then.tipo(),
|
Self::Trace { then, .. } => then.tipo(),
|
||||||
Self::Fn { tipo, .. }
|
Self::Fn { tipo, .. }
|
||||||
| Self::Int { tipo, .. }
|
| Self::Int { tipo, .. }
|
||||||
| Self::Todo { tipo, .. }
|
| Self::Todo { tipo, .. }
|
||||||
|
@ -175,7 +173,7 @@ impl TypedExpr {
|
||||||
| Self::Call { tipo, .. }
|
| Self::Call { tipo, .. }
|
||||||
| Self::If { tipo, .. }
|
| Self::If { tipo, .. }
|
||||||
| Self::BinOp { tipo, .. }
|
| Self::BinOp { tipo, .. }
|
||||||
// | Self::Tuple { tipo, .. }
|
| Self::Tuple { tipo, .. }
|
||||||
| Self::String { tipo, .. }
|
| Self::String { tipo, .. }
|
||||||
| Self::ByteArray { tipo, .. }
|
| Self::ByteArray { tipo, .. }
|
||||||
// | Self::TupleIndex { tipo, .. }
|
// | Self::TupleIndex { tipo, .. }
|
||||||
|
@ -194,7 +192,7 @@ impl TypedExpr {
|
||||||
self,
|
self,
|
||||||
Self::Int { .. }
|
Self::Int { .. }
|
||||||
| Self::List { .. }
|
| Self::List { .. }
|
||||||
// | Self::Tuple { .. }
|
| Self::Tuple { .. }
|
||||||
| Self::String { .. }
|
| Self::String { .. }
|
||||||
| Self::ByteArray { .. }
|
| Self::ByteArray { .. }
|
||||||
)
|
)
|
||||||
|
@ -209,13 +207,13 @@ impl TypedExpr {
|
||||||
match self {
|
match self {
|
||||||
TypedExpr::Fn { .. }
|
TypedExpr::Fn { .. }
|
||||||
| TypedExpr::Int { .. }
|
| TypedExpr::Int { .. }
|
||||||
| TypedExpr::Try { .. }
|
| TypedExpr::Trace { .. }
|
||||||
| TypedExpr::List { .. }
|
| TypedExpr::List { .. }
|
||||||
| TypedExpr::Call { .. }
|
| TypedExpr::Call { .. }
|
||||||
| TypedExpr::When { .. }
|
| TypedExpr::When { .. }
|
||||||
| TypedExpr::Todo { .. }
|
| TypedExpr::Todo { .. }
|
||||||
| TypedExpr::BinOp { .. }
|
| TypedExpr::BinOp { .. }
|
||||||
// | TypedExpr::Tuple { .. }
|
| TypedExpr::Tuple { .. }
|
||||||
| TypedExpr::Negate { .. }
|
| TypedExpr::Negate { .. }
|
||||||
| TypedExpr::String { .. }
|
| TypedExpr::String { .. }
|
||||||
| TypedExpr::Sequence { .. }
|
| TypedExpr::Sequence { .. }
|
||||||
|
@ -249,14 +247,14 @@ impl TypedExpr {
|
||||||
match self {
|
match self {
|
||||||
Self::Fn { location, .. }
|
Self::Fn { location, .. }
|
||||||
| Self::Int { location, .. }
|
| Self::Int { location, .. }
|
||||||
| Self::Try { location, .. }
|
| Self::Trace { location, .. }
|
||||||
| Self::Var { location, .. }
|
| Self::Var { location, .. }
|
||||||
| Self::Todo { location, .. }
|
| Self::Todo { location, .. }
|
||||||
| Self::When { location, .. }
|
| Self::When { location, .. }
|
||||||
| Self::Call { location, .. }
|
| Self::Call { location, .. }
|
||||||
| Self::List { location, .. }
|
| Self::List { location, .. }
|
||||||
| Self::BinOp { location, .. }
|
| Self::BinOp { location, .. }
|
||||||
// | Self::Tuple { location, .. }
|
| Self::Tuple { location, .. }
|
||||||
| Self::String { location, .. }
|
| Self::String { location, .. }
|
||||||
| Self::Negate { location, .. }
|
| Self::Negate { location, .. }
|
||||||
| Self::Pipeline { location, .. }
|
| Self::Pipeline { location, .. }
|
||||||
|
@ -286,7 +284,7 @@ impl TypedExpr {
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::Fn { location, .. }
|
Self::Fn { location, .. }
|
||||||
| Self::Try { location, .. }
|
| Self::Trace { location, .. }
|
||||||
| Self::Int { location, .. }
|
| Self::Int { location, .. }
|
||||||
| Self::Var { location, .. }
|
| Self::Var { location, .. }
|
||||||
| Self::Todo { location, .. }
|
| Self::Todo { location, .. }
|
||||||
|
@ -295,7 +293,7 @@ impl TypedExpr {
|
||||||
| Self::If { location, .. }
|
| Self::If { location, .. }
|
||||||
| Self::List { location, .. }
|
| Self::List { location, .. }
|
||||||
| Self::BinOp { location, .. }
|
| Self::BinOp { location, .. }
|
||||||
// | Self::Tuple { location, .. }
|
| Self::Tuple { location, .. }
|
||||||
| Self::String { location, .. }
|
| Self::String { location, .. }
|
||||||
| Self::Negate { location, .. }
|
| Self::Negate { location, .. }
|
||||||
| Self::Sequence { location, .. }
|
| Self::Sequence { location, .. }
|
||||||
|
@ -376,12 +374,10 @@ pub enum UntypedExpr {
|
||||||
annotation: Option<Annotation>,
|
annotation: Option<Annotation>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Try {
|
Trace {
|
||||||
location: Span,
|
location: Span,
|
||||||
value: Box<Self>,
|
|
||||||
pattern: Pattern<(), ()>,
|
|
||||||
then: Box<Self>,
|
then: Box<Self>,
|
||||||
annotation: Option<Annotation>,
|
text: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
When {
|
When {
|
||||||
|
@ -402,10 +398,10 @@ pub enum UntypedExpr {
|
||||||
container: Box<Self>,
|
container: Box<Self>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Tuple {
|
Tuple {
|
||||||
// location: Span,
|
location: Span,
|
||||||
// elems: Vec<Self>,
|
elems: Vec<Self>,
|
||||||
// },
|
},
|
||||||
// TupleIndex {
|
// TupleIndex {
|
||||||
// location: Span,
|
// location: Span,
|
||||||
// index: u64,
|
// index: u64,
|
||||||
|
@ -481,7 +477,7 @@ impl UntypedExpr {
|
||||||
|
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::Try { then, .. } => then.location(),
|
Self::Trace { then, .. } => then.location(),
|
||||||
Self::PipeLine { expressions, .. } => expressions.last().location(),
|
Self::PipeLine { expressions, .. } => expressions.last().location(),
|
||||||
Self::Fn { location, .. }
|
Self::Fn { location, .. }
|
||||||
| Self::Var { location, .. }
|
| Self::Var { location, .. }
|
||||||
|
@ -492,7 +488,7 @@ impl UntypedExpr {
|
||||||
| Self::List { location, .. }
|
| Self::List { location, .. }
|
||||||
| Self::ByteArray { location, .. }
|
| Self::ByteArray { location, .. }
|
||||||
| Self::BinOp { location, .. }
|
| Self::BinOp { location, .. }
|
||||||
// | Self::Tuple { location, .. }
|
| Self::Tuple { location, .. }
|
||||||
| Self::String { location, .. }
|
| Self::String { location, .. }
|
||||||
| Self::Assignment { location, .. }
|
| Self::Assignment { location, .. }
|
||||||
// | Self::TupleIndex { location, .. }
|
// | Self::TupleIndex { location, .. }
|
||||||
|
@ -519,7 +515,7 @@ impl UntypedExpr {
|
||||||
.map(|e| e.start_byte_index())
|
.map(|e| e.start_byte_index())
|
||||||
.unwrap_or(location.start),
|
.unwrap_or(location.start),
|
||||||
Self::PipeLine { expressions, .. } => expressions.first().start_byte_index(),
|
Self::PipeLine { expressions, .. } => expressions.first().start_byte_index(),
|
||||||
Self::Try { location, .. } | Self::Assignment { location, .. } => location.start,
|
Self::Trace { location, .. } | Self::Assignment { location, .. } => location.start,
|
||||||
_ => self.location().start,
|
_ => self.location().start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
let head = pub_(*public).append("const ").append(name.as_str());
|
let head = pub_(*public).append("const ").append(name.as_str());
|
||||||
let head = match annotation {
|
let head = match annotation {
|
||||||
None => head,
|
None => head,
|
||||||
Some(t) => head.append(": ").append(self.type_ast(t)),
|
Some(t) => head.append(": ").append(self.annotation(t)),
|
||||||
};
|
};
|
||||||
head.append(" = ").append(self.const_expr(value))
|
head.append(" = ").append(self.const_expr(value))
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_ast<'a>(&mut self, t: &'a Annotation) -> Document<'a> {
|
fn annotation<'a>(&mut self, t: &'a Annotation) -> Document<'a> {
|
||||||
match t {
|
match t {
|
||||||
Annotation::Hole { name, .. } => name.to_doc(),
|
Annotation::Hole { name, .. } => name.to_doc(),
|
||||||
|
|
||||||
|
@ -430,15 +430,16 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append(self.type_arguments(args))
|
.append(self.type_arguments(args))
|
||||||
.group()
|
.group()
|
||||||
.append(" ->")
|
.append(" ->")
|
||||||
.append(break_("", " ").append(self.type_ast(retrn)).nest(INDENT)),
|
.append(break_("", " ").append(self.annotation(retrn)).nest(INDENT)),
|
||||||
|
|
||||||
Annotation::Var { name, .. } => name.to_doc(),
|
Annotation::Var { name, .. } => name.to_doc(),
|
||||||
|
Annotation::Tuple { elems, .. } => "#".to_doc().append(self.type_arguments(elems)),
|
||||||
}
|
}
|
||||||
.group()
|
.group()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_arguments<'a>(&mut self, args: &'a [Annotation]) -> Document<'a> {
|
fn type_arguments<'a>(&mut self, args: &'a [Annotation]) -> Document<'a> {
|
||||||
wrap_args(args.iter().map(|t| (self.type_ast(t), false)))
|
wrap_args(args.iter().map(|t| (self.annotation(t), false)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_alias<'a>(
|
pub fn type_alias<'a>(
|
||||||
|
@ -457,7 +458,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
};
|
};
|
||||||
|
|
||||||
head.append(" =")
|
head.append(" =")
|
||||||
.append(line().append(self.type_ast(typ)).group().nest(INDENT))
|
.append(line().append(self.annotation(typ)).group().nest(INDENT))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_arg<'a, A>(&mut self, arg: &'a Arg<A>) -> Document<'a> {
|
fn fn_arg<'a, A>(&mut self, arg: &'a Arg<A>) -> Document<'a> {
|
||||||
|
@ -465,7 +466,11 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
let doc = match &arg.annotation {
|
let doc = match &arg.annotation {
|
||||||
None => arg.arg_name.to_doc(),
|
None => arg.arg_name.to_doc(),
|
||||||
Some(a) => arg.arg_name.to_doc().append(": ").append(self.type_ast(a)),
|
Some(a) => arg
|
||||||
|
.arg_name
|
||||||
|
.to_doc()
|
||||||
|
.append(": ")
|
||||||
|
.append(self.annotation(a)),
|
||||||
}
|
}
|
||||||
.group();
|
.group();
|
||||||
|
|
||||||
|
@ -489,7 +494,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
// Add return annotation
|
// Add return annotation
|
||||||
let head = match return_annotation {
|
let head = match return_annotation {
|
||||||
Some(anno) => head.append(" -> ").append(self.type_ast(anno)),
|
Some(anno) => head.append(" -> ").append(self.annotation(anno)),
|
||||||
None => head,
|
None => head,
|
||||||
}
|
}
|
||||||
.group();
|
.group();
|
||||||
|
@ -526,7 +531,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
let header = match return_annotation {
|
let header = match return_annotation {
|
||||||
None => header,
|
None => header,
|
||||||
Some(t) => header.append(" -> ").append(self.type_ast(t)),
|
Some(t) => header.append(" -> ").append(self.annotation(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
header
|
header
|
||||||
|
@ -576,7 +581,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
let annotation = annotation
|
let annotation = annotation
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|a| ": ".to_doc().append(self.type_ast(a)));
|
.map(|a| ": ".to_doc().append(self.annotation(a)));
|
||||||
|
|
||||||
let doc = if then.is_some() {
|
let doc = if then.is_some() {
|
||||||
keyword.to_doc().force_break()
|
keyword.to_doc().force_break()
|
||||||
|
@ -697,13 +702,28 @@ impl<'comments> Formatter<'comments> {
|
||||||
..
|
..
|
||||||
} => self.assignment(pattern, value, None, Some(*kind), annotation),
|
} => self.assignment(pattern, value, None, Some(*kind), annotation),
|
||||||
|
|
||||||
UntypedExpr::Try {
|
UntypedExpr::Trace {
|
||||||
value,
|
text: None, then, ..
|
||||||
pattern,
|
} => "trace"
|
||||||
annotation,
|
.to_doc()
|
||||||
|
.append(if self.pop_empty_lines(then.start_byte_index()) {
|
||||||
|
lines(2)
|
||||||
|
} else {
|
||||||
|
line()
|
||||||
|
})
|
||||||
|
.append(self.expr(then)),
|
||||||
|
|
||||||
|
UntypedExpr::Trace {
|
||||||
|
text: Some(l),
|
||||||
then,
|
then,
|
||||||
..
|
..
|
||||||
} => self.assignment(pattern, value, Some(then), None, annotation),
|
} => docvec!["trace(\"", l, "\")"]
|
||||||
|
.append(if self.pop_empty_lines(then.start_byte_index()) {
|
||||||
|
lines(2)
|
||||||
|
} else {
|
||||||
|
line()
|
||||||
|
})
|
||||||
|
.append(self.expr(then)),
|
||||||
|
|
||||||
UntypedExpr::When {
|
UntypedExpr::When {
|
||||||
subjects, clauses, ..
|
subjects, clauses, ..
|
||||||
|
@ -719,6 +739,11 @@ impl<'comments> Formatter<'comments> {
|
||||||
arguments: args,
|
arguments: args,
|
||||||
..
|
..
|
||||||
} => self.record_update(constructor, spread, args),
|
} => self.record_update(constructor, spread, args),
|
||||||
|
|
||||||
|
UntypedExpr::Tuple { elems, .. } => "#"
|
||||||
|
.to_doc()
|
||||||
|
.append(wrap_args(elems.iter().map(|e| (self.wrap_expr(e), false))))
|
||||||
|
.group(),
|
||||||
};
|
};
|
||||||
commented(document, comments)
|
commented(document, comments)
|
||||||
}
|
}
|
||||||
|
@ -742,7 +767,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
fn is_breakable(expr: &UntypedPattern) -> bool {
|
fn is_breakable(expr: &UntypedPattern) -> bool {
|
||||||
match expr {
|
match expr {
|
||||||
Pattern::List { .. } => true,
|
Pattern::Tuple { .. } | Pattern::List { .. } => true,
|
||||||
Pattern::Constructor {
|
Pattern::Constructor {
|
||||||
arguments: args, ..
|
arguments: args, ..
|
||||||
} => !args.is_empty(),
|
} => !args.is_empty(),
|
||||||
|
@ -982,8 +1007,8 @@ impl<'comments> Formatter<'comments> {
|
||||||
let arg_comments = self.pop_comments(location.start);
|
let arg_comments = self.pop_comments(location.start);
|
||||||
|
|
||||||
let arg = match label {
|
let arg = match label {
|
||||||
Some(l) => l.to_doc().append(": ").append(self.type_ast(annotation)),
|
Some(l) => l.to_doc().append(": ").append(self.annotation(annotation)),
|
||||||
None => self.type_ast(annotation),
|
None => self.annotation(annotation),
|
||||||
};
|
};
|
||||||
|
|
||||||
commented(
|
commented(
|
||||||
|
@ -1007,8 +1032,8 @@ impl<'comments> Formatter<'comments> {
|
||||||
let arg_comments = self.pop_comments(location.start);
|
let arg_comments = self.pop_comments(location.start);
|
||||||
|
|
||||||
let arg = match label {
|
let arg = match label {
|
||||||
Some(l) => l.to_doc().append(": ").append(self.type_ast(annotation)),
|
Some(l) => l.to_doc().append(": ").append(self.annotation(annotation)),
|
||||||
None => self.type_ast(annotation),
|
None => self.annotation(annotation),
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -1127,7 +1152,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
match expr {
|
match expr {
|
||||||
UntypedExpr::Sequence { .. }
|
UntypedExpr::Sequence { .. }
|
||||||
| UntypedExpr::Assignment { .. }
|
| UntypedExpr::Assignment { .. }
|
||||||
| UntypedExpr::Try { .. } => "{"
|
| UntypedExpr::Trace { .. } => "{"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(line().append(self.expr(expr)).nest(INDENT))
|
.append(line().append(self.expr(expr)).nest(INDENT))
|
||||||
.append(line())
|
.append(line())
|
||||||
|
@ -1158,7 +1183,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
fn case_clause_value<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
fn case_clause_value<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||||
match expr {
|
match expr {
|
||||||
UntypedExpr::Try { .. }
|
UntypedExpr::Trace { .. }
|
||||||
| UntypedExpr::Sequence { .. }
|
| UntypedExpr::Sequence { .. }
|
||||||
| UntypedExpr::Assignment { .. } => " {"
|
| UntypedExpr::Assignment { .. } => " {"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
|
@ -1245,6 +1270,11 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
Pattern::Discard { name, .. } => name.to_doc(),
|
Pattern::Discard { name, .. } => name.to_doc(),
|
||||||
|
|
||||||
|
Pattern::Tuple { elems, .. } => "#"
|
||||||
|
.to_doc()
|
||||||
|
.append(wrap_args(elems.iter().map(|e| (self.pattern(e), false))))
|
||||||
|
.group(),
|
||||||
|
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
let elements_document =
|
let elements_document =
|
||||||
join(elements.iter().map(|e| self.pattern(e)), break_(",", ", "));
|
join(elements.iter().map(|e| self.pattern(e)), break_(",", ", "));
|
||||||
|
|
|
@ -327,20 +327,17 @@ pub fn anon_fn_param_parser() -> impl Parser<Token, ast::UntypedArg, Error = Par
|
||||||
pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
|
pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseError> {
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
choice((
|
choice((
|
||||||
just(Token::Try)
|
just(Token::Trace)
|
||||||
.ignore_then(pattern_parser())
|
.ignore_then(
|
||||||
.then(just(Token::Colon).ignore_then(type_parser()).or_not())
|
select! {Token::String {value} => value}
|
||||||
.then_ignore(just(Token::Equal))
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||||
.then(expr_parser(r.clone()))
|
.or_not(),
|
||||||
|
)
|
||||||
.then(r.clone())
|
.then(r.clone())
|
||||||
.map_with_span(|(((pattern, annotation), value), then_), span| {
|
.map_with_span(|(text, then_), span| expr::UntypedExpr::Trace {
|
||||||
expr::UntypedExpr::Try {
|
location: span,
|
||||||
location: span,
|
then: Box::new(then_),
|
||||||
value: Box::new(value),
|
text,
|
||||||
pattern,
|
|
||||||
then: Box::new(then_),
|
|
||||||
annotation,
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
expr_parser(r.clone())
|
expr_parser(r.clone())
|
||||||
.then(r.repeated())
|
.then(r.repeated())
|
||||||
|
@ -389,6 +386,18 @@ pub fn expr_parser(
|
||||||
label,
|
label,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let tuple = just(Token::Hash)
|
||||||
|
.ignore_then(
|
||||||
|
r.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.allow_trailing()
|
||||||
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
||||||
|
)
|
||||||
|
.map_with_span(|elems, span| expr::UntypedExpr::Tuple {
|
||||||
|
location: span,
|
||||||
|
elems,
|
||||||
|
});
|
||||||
|
|
||||||
let list_parser = just(Token::LeftSquare)
|
let list_parser = just(Token::LeftSquare)
|
||||||
.ignore_then(r.clone().separated_by(just(Token::Comma)))
|
.ignore_then(r.clone().separated_by(just(Token::Comma)))
|
||||||
.then(choice((
|
.then(choice((
|
||||||
|
@ -562,6 +571,7 @@ pub fn expr_parser(
|
||||||
int_parser,
|
int_parser,
|
||||||
var_parser,
|
var_parser,
|
||||||
todo_parser,
|
todo_parser,
|
||||||
|
tuple,
|
||||||
list_parser,
|
list_parser,
|
||||||
anon_fn_parser,
|
anon_fn_parser,
|
||||||
block_parser,
|
block_parser,
|
||||||
|
@ -835,12 +845,24 @@ pub fn expr_parser(
|
||||||
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError> {
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
choice((
|
choice((
|
||||||
|
// Type hole
|
||||||
select! {Token::DiscardName { name } => name}.map_with_span(|name, span| {
|
select! {Token::DiscardName { name } => name}.map_with_span(|name, span| {
|
||||||
ast::Annotation::Hole {
|
ast::Annotation::Hole {
|
||||||
location: span,
|
location: span,
|
||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
just(Token::Hash)
|
||||||
|
.ignore_then(
|
||||||
|
r.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
||||||
|
)
|
||||||
|
.map_with_span(|elems, span| ast::Annotation::Tuple {
|
||||||
|
location: span,
|
||||||
|
elems,
|
||||||
|
}),
|
||||||
|
// Function
|
||||||
just(Token::Fn)
|
just(Token::Fn)
|
||||||
.ignore_then(
|
.ignore_then(
|
||||||
r.clone()
|
r.clone()
|
||||||
|
@ -855,6 +877,7 @@ pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError>
|
||||||
arguments,
|
arguments,
|
||||||
ret: Box::new(ret),
|
ret: Box::new(ret),
|
||||||
}),
|
}),
|
||||||
|
// Constructor function
|
||||||
select! {Token::UpName { name } => name}
|
select! {Token::UpName { name } => name}
|
||||||
.then(
|
.then(
|
||||||
r.clone()
|
r.clone()
|
||||||
|
@ -869,6 +892,7 @@ pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError>
|
||||||
name,
|
name,
|
||||||
arguments: arguments.unwrap_or_default(),
|
arguments: arguments.unwrap_or_default(),
|
||||||
}),
|
}),
|
||||||
|
// Constructor Module or type Variable
|
||||||
select! {Token::Name { name } => name}
|
select! {Token::Name { name } => name}
|
||||||
.then(
|
.then(
|
||||||
just(Token::Dot)
|
just(Token::Dot)
|
||||||
|
@ -890,6 +914,7 @@ pub fn type_parser() -> impl Parser<Token, ast::Annotation, Error = ParseError>
|
||||||
arguments: arguments.unwrap_or_default(),
|
arguments: arguments.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: parse_error(ParseErrorType::NotConstType, SrcSpan { start, end })
|
||||||
ast::Annotation::Var {
|
ast::Annotation::Var {
|
||||||
location: span,
|
location: span,
|
||||||
name: mod_name,
|
name: mod_name,
|
||||||
|
@ -1058,6 +1083,16 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
value,
|
value,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
just(Token::Hash)
|
||||||
|
.ignore_then(
|
||||||
|
r.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
||||||
|
)
|
||||||
|
.map_with_span(|elems, span| ast::UntypedPattern::Tuple {
|
||||||
|
location: span,
|
||||||
|
elems,
|
||||||
|
}),
|
||||||
just(Token::LeftSquare)
|
just(Token::LeftSquare)
|
||||||
.ignore_then(r.clone().separated_by(just(Token::Comma)))
|
.ignore_then(r.clone().separated_by(just(Token::Comma)))
|
||||||
.then(choice((
|
.then(choice((
|
||||||
|
@ -1066,7 +1101,7 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
just(Token::Comma).ignored().or_not().map(|_| None),
|
just(Token::Comma).ignored().or_not().map(|_| None),
|
||||||
)))
|
)))
|
||||||
.then_ignore(just(Token::RightSquare))
|
.then_ignore(just(Token::RightSquare))
|
||||||
.validate(|(elements, tail), span: Span, _emit| {
|
.validate(|(elements, tail), span: Span, emit| {
|
||||||
let tail = match tail {
|
let tail = match tail {
|
||||||
// There is a tail and it has a Pattern::Var or Pattern::Discard
|
// There is a tail and it has a Pattern::Var or Pattern::Discard
|
||||||
Some(Some(
|
Some(Some(
|
||||||
|
@ -1074,8 +1109,12 @@ pub fn pattern_parser() -> impl Parser<Token, ast::UntypedPattern, Error = Parse
|
||||||
| ast::UntypedPattern::Discard { .. }),
|
| ast::UntypedPattern::Discard { .. }),
|
||||||
)) => Some(pat),
|
)) => Some(pat),
|
||||||
Some(Some(pat)) => {
|
Some(Some(pat)) => {
|
||||||
// use emit
|
emit(ParseError::expected_input_found(
|
||||||
// return parse_error(ParseErrorType::InvalidTailPattern, pat.location())
|
pat.location(),
|
||||||
|
None,
|
||||||
|
Some(error::Pattern::Match),
|
||||||
|
));
|
||||||
|
|
||||||
Some(pat)
|
Some(pat)
|
||||||
}
|
}
|
||||||
// There is a tail but it has no content, implicit discard
|
// There is a tail but it has no content, implicit discard
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::HashSet, fmt};
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ pub enum ErrorKind {
|
||||||
#[error("unexpected end")]
|
#[error("unexpected end")]
|
||||||
UnexpectedEnd,
|
UnexpectedEnd,
|
||||||
#[error("unexpected {0}")]
|
#[error("unexpected {0}")]
|
||||||
#[diagnostic(help("try removing it"))]
|
#[diagnostic(help("{}", .0.help().unwrap_or_else(|| Box::new(""))))]
|
||||||
Unexpected(Pattern),
|
Unexpected(Pattern),
|
||||||
#[error("unclosed {start}")]
|
#[error("unclosed {start}")]
|
||||||
Unclosed {
|
Unclosed {
|
||||||
|
@ -87,12 +87,22 @@ pub enum ErrorKind {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
||||||
pub enum Pattern {
|
pub enum Pattern {
|
||||||
|
#[error("{0:?}")]
|
||||||
Char(char),
|
Char(char),
|
||||||
|
#[error("{0}")]
|
||||||
|
#[diagnostic(help("try removing it"))]
|
||||||
Token(Token),
|
Token(Token),
|
||||||
|
#[error("literal")]
|
||||||
Literal,
|
Literal,
|
||||||
|
#[error("type name")]
|
||||||
TypeIdent,
|
TypeIdent,
|
||||||
|
#[error("indentifier")]
|
||||||
TermIdent,
|
TermIdent,
|
||||||
|
#[error("end of input")]
|
||||||
End,
|
End,
|
||||||
|
#[error("pattern")]
|
||||||
|
#[diagnostic(help("list spread in match can only have a discard or var"))]
|
||||||
|
Match,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<char> for Pattern {
|
impl From<char> for Pattern {
|
||||||
|
@ -105,16 +115,3 @@ impl From<Token> for Pattern {
|
||||||
Self::Token(tok)
|
Self::Token(tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Pattern {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Pattern::Token(token) => write!(f, "{}", token),
|
|
||||||
Pattern::Char(c) => write!(f, "{:?}", c),
|
|
||||||
Pattern::Literal => write!(f, "literal"),
|
|
||||||
Pattern::TypeIdent => write!(f, "type name"),
|
|
||||||
Pattern::TermIdent => write!(f, "identifier"),
|
|
||||||
Pattern::End => write!(f, "end of input"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
just('|').to(Token::Vbar),
|
just('|').to(Token::Vbar),
|
||||||
just("&&").to(Token::AmperAmper),
|
just("&&").to(Token::AmperAmper),
|
||||||
just("\n\n").to(Token::EmptyLine),
|
just("\n\n").to(Token::EmptyLine),
|
||||||
|
just('#').to(Token::Hash),
|
||||||
));
|
));
|
||||||
|
|
||||||
let grouping = choice((
|
let grouping = choice((
|
||||||
|
@ -74,7 +75,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
"pub" => Token::Pub,
|
"pub" => Token::Pub,
|
||||||
"use" => Token::Use,
|
"use" => Token::Use,
|
||||||
"todo" => Token::Todo,
|
"todo" => Token::Todo,
|
||||||
"try" => Token::Try,
|
"trace" => Token::Trace,
|
||||||
"type" => Token::Type,
|
"type" => Token::Type,
|
||||||
"when" => Token::When,
|
"when" => Token::When,
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub enum Token {
|
||||||
Pub,
|
Pub,
|
||||||
Use,
|
Use,
|
||||||
Todo,
|
Todo,
|
||||||
Try,
|
Trace,
|
||||||
Type,
|
Type,
|
||||||
When,
|
When,
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ impl fmt::Display for Token {
|
||||||
Token::Opaque => "opaque",
|
Token::Opaque => "opaque",
|
||||||
Token::Pub => "pub",
|
Token::Pub => "pub",
|
||||||
Token::Todo => "todo",
|
Token::Todo => "todo",
|
||||||
Token::Try => "try",
|
Token::Trace => "try",
|
||||||
Token::Type => "type",
|
Token::Type => "type",
|
||||||
};
|
};
|
||||||
write!(f, "\"{}\"", s)
|
write!(f, "\"{}\"", s)
|
||||||
|
|
|
@ -45,12 +45,16 @@ pub enum Type {
|
||||||
|
|
||||||
/// A type variable. See the contained `TypeVar` enum for more information.
|
/// A type variable. See the contained `TypeVar` enum for more information.
|
||||||
///
|
///
|
||||||
Var { tipo: Arc<RefCell<TypeVar>> },
|
Var {
|
||||||
|
tipo: Arc<RefCell<TypeVar>>,
|
||||||
|
},
|
||||||
// /// 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
|
||||||
// /// contained types.
|
// /// contained types.
|
||||||
// ///
|
// ///
|
||||||
// Tuple { elems: Vec<Arc<Type>> },
|
Tuple {
|
||||||
|
elems: Vec<Arc<Type>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
@ -185,7 +189,7 @@ impl Type {
|
||||||
|
|
||||||
Self::App { args, .. } => args.iter().find_map(|t| t.find_private_type()),
|
Self::App { args, .. } => args.iter().find_map(|t| t.find_private_type()),
|
||||||
|
|
||||||
// Self::Tuple { elems, .. } => elems.iter().find_map(|t| t.find_private_type()),
|
Self::Tuple { elems, .. } => elems.iter().find_map(|t| t.find_private_type()),
|
||||||
Self::Fn { ret, args, .. } => ret
|
Self::Fn { ret, args, .. } => ret
|
||||||
.find_private_type()
|
.find_private_type()
|
||||||
.or_else(|| args.iter().find_map(|t| t.find_private_type())),
|
.or_else(|| args.iter().find_map(|t| t.find_private_type())),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
RecordConstructor, RecordConstructorArg, Span, TypeAlias, TypedDefinition,
|
RecordConstructor, RecordConstructorArg, Span, TypeAlias, TypedDefinition,
|
||||||
UnqualifiedImport, UntypedDefinition, Use, PIPE_VARIABLE,
|
UnqualifiedImport, UntypedDefinition, Use, PIPE_VARIABLE,
|
||||||
},
|
},
|
||||||
builtins::{self, function, generic_var, unbound_var},
|
builtins::{self, function, generic_var, tuple, unbound_var},
|
||||||
tipo::fields::FieldMap,
|
tipo::fields::FieldMap,
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
@ -564,12 +564,13 @@ impl<'a> Environment<'a> {
|
||||||
.collect(),
|
.collect(),
|
||||||
self.instantiate(ret.clone(), ids, hydrator),
|
self.instantiate(ret.clone(), ids, hydrator),
|
||||||
),
|
),
|
||||||
// Type::Tuple { elems } => tuple(
|
|
||||||
// elems
|
Type::Tuple { elems } => tuple(
|
||||||
// .iter()
|
elems
|
||||||
// .map(|t| self.instantiate(t.clone(), ids, hydrator))
|
.iter()
|
||||||
// .collect(),
|
.map(|t| self.instantiate(t.clone(), ids, hydrator))
|
||||||
// ),
|
.collect(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,6 +1401,7 @@ fn unify_unbound_type(tipo: Arc<Type>, own_id: u64, location: Span) -> Result<()
|
||||||
for arg in args {
|
for arg in args {
|
||||||
unify_unbound_type(arg.clone(), own_id, location)?
|
unify_unbound_type(arg.clone(), own_id, location)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,9 +1409,18 @@ fn unify_unbound_type(tipo: Arc<Type>, own_id: u64, location: Span) -> Result<()
|
||||||
for arg in args {
|
for arg in args {
|
||||||
unify_unbound_type(arg.clone(), own_id, location)?;
|
unify_unbound_type(arg.clone(), own_id, location)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
unify_unbound_type(ret.clone(), own_id, location)
|
unify_unbound_type(ret.clone(), own_id, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type::Tuple { elems, .. } => {
|
||||||
|
for elem in elems {
|
||||||
|
unify_unbound_type(elem.clone(), own_id, location)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
Type::Var { .. } => unreachable!(),
|
Type::Var { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1591,11 +1602,12 @@ pub(crate) fn generalise(t: Arc<Type>, ctx_level: usize) -> Arc<Type> {
|
||||||
.collect(),
|
.collect(),
|
||||||
generalise(ret.clone(), ctx_level),
|
generalise(ret.clone(), ctx_level),
|
||||||
),
|
),
|
||||||
// Type::Tuple { elems } => tuple(
|
|
||||||
// elems
|
Type::Tuple { elems } => tuple(
|
||||||
// .iter()
|
elems
|
||||||
// .map(|t| generalise(t.clone(), ctx_level))
|
.iter()
|
||||||
// .collect(),
|
.map(|t| generalise(t.clone(), ctx_level))
|
||||||
// ),
|
.collect(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedIfBranch, UntypedMultiPattern,
|
UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedIfBranch, UntypedMultiPattern,
|
||||||
UntypedPattern, UntypedRecordUpdateArg,
|
UntypedPattern, UntypedRecordUpdateArg,
|
||||||
},
|
},
|
||||||
builtins::{bool, byte_array, function, int, list, result, string},
|
builtins::{bool, byte_array, function, int, list, string, tuple},
|
||||||
expr::{TypedExpr, UntypedExpr},
|
expr::{TypedExpr, UntypedExpr},
|
||||||
tipo::fields::FieldMap,
|
tipo::fields::FieldMap,
|
||||||
};
|
};
|
||||||
|
@ -245,9 +245,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location,
|
location,
|
||||||
} => self.infer_seq(location, expressions),
|
} => self.infer_seq(location, expressions),
|
||||||
|
|
||||||
// UntypedExpr::Tuple {
|
UntypedExpr::Tuple {
|
||||||
// location, elems, ..
|
location, elems, ..
|
||||||
// } => self.infer_tuple(elems, location),
|
} => self.infer_tuple(elems, location),
|
||||||
|
|
||||||
UntypedExpr::String {
|
UntypedExpr::String {
|
||||||
location, value, ..
|
location, value, ..
|
||||||
} => Ok(self.infer_string(value, location)),
|
} => Ok(self.infer_string(value, location)),
|
||||||
|
@ -278,14 +279,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
..
|
..
|
||||||
} => self.infer_assignment(pattern, *value, kind, &annotation, location),
|
} => self.infer_assignment(pattern, *value, kind, &annotation, location),
|
||||||
|
|
||||||
UntypedExpr::Try {
|
UntypedExpr::Trace { location, then, .. } => self.infer_trace(*then, location),
|
||||||
location,
|
|
||||||
pattern,
|
|
||||||
value,
|
|
||||||
then,
|
|
||||||
annotation,
|
|
||||||
..
|
|
||||||
} => self.infer_try(pattern, *value, *then, &annotation, location),
|
|
||||||
|
|
||||||
UntypedExpr::When {
|
UntypedExpr::When {
|
||||||
location,
|
location,
|
||||||
|
@ -1665,6 +1659,24 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn infer_tuple(&mut self, elems: Vec<UntypedExpr>, location: Span) -> Result<TypedExpr, Error> {
|
||||||
|
let mut typed_elems = vec![];
|
||||||
|
|
||||||
|
for elem in elems {
|
||||||
|
let typed_elem = self.infer(elem)?;
|
||||||
|
|
||||||
|
typed_elems.push(typed_elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tipo = tuple(typed_elems.iter().map(|e| e.tipo()).collect());
|
||||||
|
|
||||||
|
Ok(TypedExpr::Tuple {
|
||||||
|
location,
|
||||||
|
elems: typed_elems,
|
||||||
|
tipo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_todo(&mut self, location: Span, kind: TodoKind, label: Option<String>) -> TypedExpr {
|
fn infer_todo(&mut self, location: Span, kind: TodoKind, label: Option<String>) -> TypedExpr {
|
||||||
let tipo = self.new_unbound_var();
|
let tipo = self.new_unbound_var();
|
||||||
|
|
||||||
|
@ -1681,66 +1693,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_try(
|
fn infer_trace(&mut self, then: UntypedExpr, location: Span) -> Result<TypedExpr, Error> {
|
||||||
&mut self,
|
|
||||||
pattern: UntypedPattern,
|
|
||||||
value: UntypedExpr,
|
|
||||||
then: UntypedExpr,
|
|
||||||
annotation: &Option<Annotation>,
|
|
||||||
location: Span,
|
|
||||||
) -> Result<TypedExpr, Error> {
|
|
||||||
let value = self.in_new_scope(|value_typer| value_typer.infer(value))?;
|
|
||||||
|
|
||||||
let value_type = self.new_unbound_var();
|
|
||||||
let try_error_type = self.new_unbound_var();
|
|
||||||
|
|
||||||
// Ensure that the value is a result
|
|
||||||
{
|
|
||||||
let v = value_type.clone();
|
|
||||||
|
|
||||||
let e = try_error_type.clone();
|
|
||||||
|
|
||||||
self.unify(result(v, e), value.tipo(), value.type_defining_location())?;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure the pattern matches the type of the value
|
|
||||||
let pattern = PatternTyper::new(self.environment, &self.hydrator).unify(
|
|
||||||
pattern,
|
|
||||||
value_type.clone(),
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Check the type of the following code
|
// Check the type of the following code
|
||||||
let then = self.infer(then)?;
|
let then = self.infer(then)?;
|
||||||
|
|
||||||
let tipo = then.tipo();
|
let tipo = then.tipo();
|
||||||
|
|
||||||
// Ensure that a Result with the right error type is returned for `try`
|
Ok(TypedExpr::Trace {
|
||||||
{
|
|
||||||
let t = self.new_unbound_var();
|
|
||||||
|
|
||||||
self.unify(
|
|
||||||
result(t, try_error_type),
|
|
||||||
tipo.clone(),
|
|
||||||
then.type_defining_location(),
|
|
||||||
)
|
|
||||||
.map_err(|e| e.inconsistent_try(tipo.is_result()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that any type annotation is accurate.
|
|
||||||
if let Some(ann) = annotation {
|
|
||||||
let ann_typ = self
|
|
||||||
.type_from_annotation(ann)
|
|
||||||
.map(|t| self.instantiate(t, &mut HashMap::new()))?;
|
|
||||||
|
|
||||||
self.unify(ann_typ, value_type, value.type_defining_location())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(TypedExpr::Try {
|
|
||||||
location,
|
location,
|
||||||
tipo,
|
tipo,
|
||||||
pattern,
|
|
||||||
value: Box::new(value),
|
|
||||||
then: Box::new(then),
|
then: Box::new(then),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::{ast::Annotation, builtins::function};
|
use crate::{
|
||||||
|
ast::Annotation,
|
||||||
|
builtins::{function, tuple},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{environment::Environment, error::Error, Type, TypeConstructor};
|
use super::{environment::Environment, error::Error, Type, TypeConstructor};
|
||||||
|
|
||||||
|
@ -208,6 +211,18 @@ impl Hydrator {
|
||||||
Annotation::Hole { location, .. } => Err(Error::UnexpectedTypeHole {
|
Annotation::Hole { location, .. } => Err(Error::UnexpectedTypeHole {
|
||||||
location: *location,
|
location: *location,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
Annotation::Tuple { elems, .. } => {
|
||||||
|
let mut typed_elems = vec![];
|
||||||
|
|
||||||
|
for elem in elems {
|
||||||
|
let typed_elem = self.type_from_annotation(elem, environment)?;
|
||||||
|
|
||||||
|
typed_elems.push(typed_elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tuple(typed_elems))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,7 +459,7 @@ fn str_to_keyword(word: &str) -> Option<Token> {
|
||||||
"opaque" => Some(Token::Opaque),
|
"opaque" => Some(Token::Opaque),
|
||||||
"pub" => Some(Token::Pub),
|
"pub" => Some(Token::Pub),
|
||||||
"todo" => Some(Token::Todo),
|
"todo" => Some(Token::Todo),
|
||||||
"try" => Some(Token::Try),
|
"try" => Some(Token::Trace),
|
||||||
"type" => Some(Token::Type),
|
"type" => Some(Token::Type),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,14 @@ use std::{
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
environment::{assert_no_labeled_arguments, EntityKind, Environment},
|
environment::{assert_no_labeled_arguments, collapse_links, EntityKind, Environment},
|
||||||
error::Error,
|
error::Error,
|
||||||
hydrator::Hydrator,
|
hydrator::Hydrator,
|
||||||
PatternConstructor, Type, ValueConstructor, ValueConstructorVariant,
|
PatternConstructor, Type, ValueConstructor, ValueConstructorVariant,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{CallArg, Pattern, Span, TypedPattern, UntypedMultiPattern, UntypedPattern},
|
ast::{CallArg, Pattern, Span, TypedPattern, UntypedMultiPattern, UntypedPattern},
|
||||||
builtins::{int, list, string},
|
builtins::{int, list, string, tuple},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PatternTyper<'a, 'b> {
|
pub struct PatternTyper<'a, 'b> {
|
||||||
|
@ -354,55 +354,68 @@ 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::IncorrectArity {
|
return Err(Error::IncorrectArity {
|
||||||
// labels: vec![],
|
labels: vec![],
|
||||||
// location,
|
location,
|
||||||
// expected: type_elems.len(),
|
expected: type_elems.len(),
|
||||||
// given: elems.len(),
|
given: elems.len(),
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let elems = elems
|
let mut patterns = vec![];
|
||||||
// .into_iter()
|
|
||||||
// .zip(type_elems)
|
|
||||||
// .map(|(pattern, typ)| self.unify(pattern, typ.clone()))
|
|
||||||
// .try_collect()?;
|
|
||||||
|
|
||||||
// Ok(Pattern::Tuple { elems, location })
|
for (pattern, typ) in elems.into_iter().zip(type_elems) {
|
||||||
// }
|
let typed_pattern = self.unify(pattern, typ.clone(), None)?;
|
||||||
|
|
||||||
// Type::Var { .. } => {
|
patterns.push(typed_pattern);
|
||||||
// let elems_types: Vec<_> = (0..(elems.len()))
|
}
|
||||||
// .map(|_| self.environment.new_unbound_var())
|
|
||||||
// .collect();
|
|
||||||
// self.environment
|
|
||||||
// .unify(tuple(elems_types.clone()), type_)
|
|
||||||
// .map_err(|e| convert_unify_error(e, location))?;
|
|
||||||
// let elems = elems
|
|
||||||
// .into_iter()
|
|
||||||
// .zip(elems_types)
|
|
||||||
// .map(|(pattern, type_)| self.unify(pattern, type_))
|
|
||||||
// .try_collect()?;
|
|
||||||
// Ok(Pattern::Tuple { elems, location })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _ => {
|
Ok(Pattern::Tuple {
|
||||||
// let elems_types = (0..(elems.len()))
|
elems: patterns,
|
||||||
// .map(|_| self.environment.new_unbound_var())
|
location,
|
||||||
// .collect();
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Var { .. } => {
|
||||||
|
let elems_types: Vec<_> = (0..(elems.len()))
|
||||||
|
.map(|_| self.environment.new_unbound_var())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
self.environment
|
||||||
|
.unify(tuple(elems_types.clone()), tipo, location)?;
|
||||||
|
|
||||||
|
let mut patterns = vec![];
|
||||||
|
|
||||||
|
for (pattern, type_) in elems.into_iter().zip(elems_types) {
|
||||||
|
let typed_pattern = self.unify(pattern, type_, None)?;
|
||||||
|
|
||||||
|
patterns.push(typed_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Pattern::Tuple {
|
||||||
|
elems: patterns,
|
||||||
|
location,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
let elems_types = (0..(elems.len()))
|
||||||
|
.map(|_| self.environment.new_unbound_var())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Err(Error::CouldNotUnify {
|
||||||
|
given: tuple(elems_types),
|
||||||
|
expected: tipo,
|
||||||
|
situation: None,
|
||||||
|
location,
|
||||||
|
rigid_type_names: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Err(Error::CouldNotUnify {
|
|
||||||
// given: tuple(elems_types),
|
|
||||||
// expected: type_,
|
|
||||||
// situation: None,
|
|
||||||
// location,
|
|
||||||
// rigid_type_names: hashmap![],
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
Pattern::Constructor {
|
Pattern::Constructor {
|
||||||
location,
|
location,
|
||||||
module,
|
module,
|
||||||
|
|
|
@ -74,6 +74,8 @@ impl Printer {
|
||||||
.append(break_("", " ").append(self.print(ret)).nest(INDENT).group()),
|
.append(break_("", " ").append(self.print(ret)).nest(INDENT).group()),
|
||||||
|
|
||||||
Type::Var { tipo: typ, .. } => self.type_var_doc(&typ.borrow()),
|
Type::Var { tipo: typ, .. } => self.type_var_doc(&typ.borrow()),
|
||||||
|
|
||||||
|
Type::Tuple { elems, .. } => self.args_to_aiken_doc(elems).surround("#(", ")"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -317,7 +317,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
ValueConstructorVariant::Record { .. } => {
|
ValueConstructorVariant::Record { .. } => {
|
||||||
match &*constructor.tipo {
|
match &*constructor.tipo {
|
||||||
Type::App { .. } => {}
|
Type::App { .. } => {}
|
||||||
Type::Fn { .. } | Type::Var { .. } => {}
|
Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -351,7 +351,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
scope_level.scope_increment(1),
|
scope_level.scope_increment(1),
|
||||||
&[],
|
&[],
|
||||||
),
|
),
|
||||||
TypedExpr::Try { .. } => todo!(),
|
TypedExpr::Trace { .. } => todo!(),
|
||||||
TypedExpr::When {
|
TypedExpr::When {
|
||||||
subjects, clauses, ..
|
subjects, clauses, ..
|
||||||
} => {
|
} => {
|
||||||
|
@ -531,6 +531,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::Todo { .. } => todo!(),
|
TypedExpr::Todo { .. } => todo!(),
|
||||||
TypedExpr::RecordUpdate { .. } => todo!(),
|
TypedExpr::RecordUpdate { .. } => todo!(),
|
||||||
TypedExpr::Negate { .. } => todo!(),
|
TypedExpr::Negate { .. } => todo!(),
|
||||||
|
TypedExpr::Tuple { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,6 +764,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Pattern::Tuple { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,6 +820,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(data_type) = self.data_types.get(&data_type_key) {
|
if let Some(data_type) = self.data_types.get(&data_type_key) {
|
||||||
|
@ -871,6 +874,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Type::App { args, .. } => (*args[0]).clone(),
|
Type::App { args, .. } => (*args[0]).clone(),
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
while !is_final_type {
|
while !is_final_type {
|
||||||
match current_tipo.clone() {
|
match current_tipo.clone() {
|
||||||
|
@ -891,6 +895,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
tipo::TypeVar::Generic { .. } => todo!(),
|
tipo::TypeVar::Generic { .. } => todo!(),
|
||||||
},
|
},
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1282,6 +1287,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
},
|
},
|
||||||
BinOp::And => Term::Force(
|
BinOp::And => Term::Force(
|
||||||
Term::Apply {
|
Term::Apply {
|
||||||
|
@ -1411,6 +1417,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
},
|
},
|
||||||
BinOp::LtInt => Term::Apply {
|
BinOp::LtInt => Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
|
@ -1508,8 +1515,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Discard { .. } => todo!(),
|
Pattern::Discard { .. } => todo!(),
|
||||||
Pattern::List { .. } => todo!(),
|
Pattern::List { .. } => todo!(),
|
||||||
Pattern::Constructor { .. } => todo!(),
|
Pattern::Constructor { .. } => todo!(),
|
||||||
|
Pattern::Tuple { .. } => todo!(),
|
||||||
},
|
},
|
||||||
TypedExpr::Try { .. } => todo!(),
|
TypedExpr::Trace { .. } => todo!(),
|
||||||
TypedExpr::When {
|
TypedExpr::When {
|
||||||
subjects, clauses, ..
|
subjects, clauses, ..
|
||||||
} => {
|
} => {
|
||||||
|
@ -1753,6 +1761,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Type::App { args, .. } => (*args[0]).clone(),
|
Type::App { args, .. } => (*args[0]).clone(),
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
while !is_final_type {
|
while !is_final_type {
|
||||||
|
@ -1774,6 +1783,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
tipo::TypeVar::Generic { .. } => todo!(),
|
tipo::TypeVar::Generic { .. } => todo!(),
|
||||||
},
|
},
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2356,6 +2366,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::Todo { .. } => todo!(),
|
TypedExpr::Todo { .. } => todo!(),
|
||||||
TypedExpr::RecordUpdate { .. } => todo!(),
|
TypedExpr::RecordUpdate { .. } => todo!(),
|
||||||
TypedExpr::Negate { .. } => todo!(),
|
TypedExpr::Negate { .. } => todo!(),
|
||||||
|
TypedExpr::Tuple { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2617,6 +2628,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Type::App { name, .. } => name,
|
Type::App { name, .. } => name,
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
(index, name.clone())
|
(index, name.clone())
|
||||||
}
|
}
|
||||||
|
@ -2628,6 +2640,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Type::App { name, .. } => name,
|
Type::App { name, .. } => name,
|
||||||
Type::Fn { .. } => todo!(),
|
Type::Fn { .. } => todo!(),
|
||||||
Type::Var { .. } => todo!(),
|
Type::Var { .. } => todo!(),
|
||||||
|
Type::Tuple { .. } => todo!(),
|
||||||
};
|
};
|
||||||
(index, name.clone())
|
(index, name.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,17 @@ pub fn incrementor(counter: Int, target: Int) -> Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn who(a: #(Int, Int)) -> #(Int, Int) {
|
||||||
|
#(1, 2)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spend(
|
pub fn spend(
|
||||||
datum: sample.Datum,
|
datum: sample.Datum,
|
||||||
rdmr: Redeemer,
|
rdmr: Redeemer,
|
||||||
ctx: spend.ScriptContext,
|
ctx: spend.ScriptContext,
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
let x = Sell
|
when [1, 2, 3] is {
|
||||||
let z = incrementor(0, 4) == 4
|
[a, b, ..] -> True
|
||||||
z
|
[] -> False
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue