Merge pull request #379 from aiken-lang/trace-rework-and-unification
Trace rework and unification
This commit is contained in:
commit
000a24b41c
|
@ -29,15 +29,6 @@ dependencies = [
|
|||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
|
||||
dependencies = [
|
||||
"const-random",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
|
@ -390,11 +381,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "chumsky"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4"
|
||||
checksum = "c4d619fba796986dd538d82660b76e0b9756c6e19b2e4d4559ba5a57f9f00810"
|
||||
dependencies = [
|
||||
"ahash 0.3.8",
|
||||
"hashbrown",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -451,28 +443,6 @@ version = "0.9.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b"
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"proc-macro-hack",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
|
@ -556,12 +526,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
|
@ -955,7 +919,7 @@ version = "0.12.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1800,12 +1764,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.20+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.49"
|
||||
|
@ -1835,6 +1793,15 @@ dependencies = [
|
|||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.8.0"
|
||||
|
@ -2275,6 +2242,19 @@ dependencies = [
|
|||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
|
@ -2461,15 +2441,6 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
|
|
@ -11,7 +11,7 @@ authors = ["Lucas Rosa <x@rvcas.dev>", "Kasey White <kwhitemsg@gmail.com>"]
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chumsky = "0.8.0"
|
||||
chumsky = "0.9.0"
|
||||
hex = "0.4.3"
|
||||
indexmap = "1.9.1"
|
||||
indoc = "1.0.7"
|
||||
|
|
|
@ -235,21 +235,13 @@ pub enum Air {
|
|||
},
|
||||
|
||||
// Misc.
|
||||
Todo {
|
||||
scope: Vec<u64>,
|
||||
label: Option<String>,
|
||||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
ErrorTerm {
|
||||
scope: Vec<u64>,
|
||||
tipo: Arc<Type>,
|
||||
label: Option<String>,
|
||||
},
|
||||
|
||||
Trace {
|
||||
scope: Vec<u64>,
|
||||
text: Option<String>,
|
||||
tipo: Arc<Type>,
|
||||
},
|
||||
}
|
||||
|
@ -292,7 +284,6 @@ impl Air {
|
|||
| Air::ListExpose { scope, .. }
|
||||
| Air::TupleAccessor { scope, .. }
|
||||
| Air::TupleIndex { scope, .. }
|
||||
| Air::Todo { scope, .. }
|
||||
| Air::ErrorTerm { scope, .. }
|
||||
| Air::Trace { scope, .. } => scope.clone(),
|
||||
}
|
||||
|
@ -375,7 +366,6 @@ impl Air {
|
|||
| Air::ListExpose { tipo, .. }
|
||||
| Air::TupleAccessor { tipo, .. }
|
||||
| Air::TupleIndex { tipo, .. }
|
||||
| Air::Todo { tipo, .. }
|
||||
| Air::ErrorTerm { tipo, .. }
|
||||
| Air::Trace { tipo, .. } => Some(tipo.clone()),
|
||||
|
||||
|
|
|
@ -995,9 +995,10 @@ pub struct RecordUpdateSpread {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum TodoKind {
|
||||
Keyword,
|
||||
EmptyFunction,
|
||||
pub enum TraceKind {
|
||||
Trace,
|
||||
Todo,
|
||||
Error,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
|
|
|
@ -433,11 +433,22 @@ pub fn rearrange_clauses(
|
|||
sorted_clauses[sorted_clauses.len() - 1].clone().then
|
||||
}
|
||||
Pattern::Discard { .. } => sorted_clauses[sorted_clauses.len() - 1].clone().then,
|
||||
_ => TypedExpr::ErrorTerm {
|
||||
_ => {
|
||||
let tipo = sorted_clauses[sorted_clauses.len() - 1].then.tipo();
|
||||
TypedExpr::Trace {
|
||||
location: Span::empty(),
|
||||
tipo: sorted_clauses[sorted_clauses.len() - 1].then.tipo(),
|
||||
label: Some("Clause not filled".to_string()),
|
||||
},
|
||||
tipo: tipo.clone(),
|
||||
text: Box::new(TypedExpr::String {
|
||||
location: Span::empty(),
|
||||
tipo: crate::builtins::string(),
|
||||
value: "Clause not filled".to_string(),
|
||||
}),
|
||||
then: Box::new(TypedExpr::ErrorTerm {
|
||||
location: Span::empty(),
|
||||
tipo,
|
||||
}),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (index, clause) in sorted_clauses.iter().enumerate() {
|
||||
|
@ -1667,30 +1678,21 @@ pub fn monomorphize(
|
|||
needs_variant = true;
|
||||
}
|
||||
}
|
||||
Air::Todo { scope, label, tipo } => {
|
||||
Air::ErrorTerm { scope, tipo } => {
|
||||
if tipo.is_generic() {
|
||||
let mut tipo = tipo.clone();
|
||||
find_generics_to_replace(&mut tipo, &generic_types);
|
||||
|
||||
new_air[index] = Air::Todo { scope, tipo, label };
|
||||
new_air[index] = Air::ErrorTerm { scope, tipo };
|
||||
needs_variant = true;
|
||||
}
|
||||
}
|
||||
Air::ErrorTerm { scope, label, tipo } => {
|
||||
Air::Trace { scope, tipo } => {
|
||||
if tipo.is_generic() {
|
||||
let mut tipo = tipo.clone();
|
||||
find_generics_to_replace(&mut tipo, &generic_types);
|
||||
|
||||
new_air[index] = Air::ErrorTerm { scope, tipo, label };
|
||||
needs_variant = true;
|
||||
}
|
||||
}
|
||||
Air::Trace { scope, text, tipo } => {
|
||||
if tipo.is_generic() {
|
||||
let mut tipo = tipo.clone();
|
||||
find_generics_to_replace(&mut tipo, &generic_types);
|
||||
|
||||
new_air[index] = Air::Trace { scope, tipo, text };
|
||||
new_air[index] = Air::Trace { scope, tipo };
|
||||
needs_variant = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use vec1::Vec1;
|
|||
use crate::{
|
||||
ast::{
|
||||
Annotation, Arg, AssignmentKind, BinOp, CallArg, Clause, DefinitionLocation, IfBranch,
|
||||
Pattern, RecordUpdateSpread, Span, TodoKind, TypedRecordUpdateArg, UnOp,
|
||||
Pattern, RecordUpdateSpread, Span, TraceKind, TypedRecordUpdateArg, UnOp,
|
||||
UntypedRecordUpdateArg,
|
||||
},
|
||||
builtins::void,
|
||||
|
@ -96,7 +96,7 @@ pub enum TypedExpr {
|
|||
location: Span,
|
||||
tipo: Arc<Type>,
|
||||
then: Box<Self>,
|
||||
text: Option<String>,
|
||||
text: Box<Self>,
|
||||
},
|
||||
|
||||
When {
|
||||
|
@ -143,16 +143,9 @@ pub enum TypedExpr {
|
|||
tuple: Box<Self>,
|
||||
},
|
||||
|
||||
Todo {
|
||||
location: Span,
|
||||
label: Option<String>,
|
||||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
ErrorTerm {
|
||||
location: Span,
|
||||
tipo: Arc<Type>,
|
||||
label: Option<String>,
|
||||
},
|
||||
|
||||
RecordUpdate {
|
||||
|
@ -177,7 +170,6 @@ impl TypedExpr {
|
|||
Self::Trace { then, .. } => then.tipo(),
|
||||
Self::Fn { tipo, .. }
|
||||
| Self::Int { tipo, .. }
|
||||
| Self::Todo { tipo, .. }
|
||||
| Self::ErrorTerm { tipo, .. }
|
||||
| Self::When { tipo, .. }
|
||||
| Self::List { tipo, .. }
|
||||
|
@ -223,7 +215,6 @@ impl TypedExpr {
|
|||
| TypedExpr::List { .. }
|
||||
| TypedExpr::Call { .. }
|
||||
| TypedExpr::When { .. }
|
||||
| TypedExpr::Todo { .. }
|
||||
| TypedExpr::ErrorTerm { .. }
|
||||
| TypedExpr::BinOp { .. }
|
||||
| TypedExpr::Tuple { .. }
|
||||
|
@ -262,7 +253,6 @@ impl TypedExpr {
|
|||
| Self::Int { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Trace { location, .. }
|
||||
| Self::Todo { location, .. }
|
||||
| Self::ErrorTerm { location, .. }
|
||||
| Self::When { location, .. }
|
||||
| Self::Call { location, .. }
|
||||
|
@ -298,7 +288,6 @@ impl TypedExpr {
|
|||
| Self::Int { location, .. }
|
||||
| Self::Trace { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Todo { location, .. }
|
||||
| Self::ErrorTerm { location, .. }
|
||||
| Self::When { location, .. }
|
||||
| Self::Call { location, .. }
|
||||
|
@ -387,9 +376,10 @@ pub enum UntypedExpr {
|
|||
},
|
||||
|
||||
Trace {
|
||||
kind: TraceKind,
|
||||
location: Span,
|
||||
then: Box<Self>,
|
||||
text: Option<String>,
|
||||
text: Box<Self>,
|
||||
},
|
||||
|
||||
When {
|
||||
|
@ -421,15 +411,8 @@ pub enum UntypedExpr {
|
|||
tuple: Box<Self>,
|
||||
},
|
||||
|
||||
Todo {
|
||||
kind: TodoKind,
|
||||
location: Span,
|
||||
label: Option<String>,
|
||||
},
|
||||
|
||||
ErrorTerm {
|
||||
location: Span,
|
||||
label: Option<String>,
|
||||
},
|
||||
|
||||
RecordUpdate {
|
||||
|
@ -446,7 +429,35 @@ pub enum UntypedExpr {
|
|||
},
|
||||
}
|
||||
|
||||
pub const DEFAULT_TODO_STR: &str = "aiken::todo";
|
||||
|
||||
pub const DEFAULT_ERROR_STR: &str = "aiken::error";
|
||||
|
||||
impl UntypedExpr {
|
||||
pub fn todo(location: Span, reason: Option<Self>) -> Self {
|
||||
UntypedExpr::Trace {
|
||||
location,
|
||||
kind: TraceKind::Todo,
|
||||
then: Box::new(UntypedExpr::ErrorTerm { location }),
|
||||
text: Box::new(reason.unwrap_or_else(|| UntypedExpr::String {
|
||||
location,
|
||||
value: DEFAULT_TODO_STR.to_string(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(location: Span, reason: Option<Self>) -> Self {
|
||||
UntypedExpr::Trace {
|
||||
location,
|
||||
kind: TraceKind::Error,
|
||||
then: Box::new(UntypedExpr::ErrorTerm { location }),
|
||||
text: Box::new(reason.unwrap_or_else(|| UntypedExpr::String {
|
||||
location,
|
||||
value: DEFAULT_ERROR_STR.to_string(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append_in_sequence(self, next: Self) -> Self {
|
||||
let location = Span {
|
||||
start: self.location().start,
|
||||
|
@ -502,7 +513,6 @@ impl UntypedExpr {
|
|||
Self::Fn { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Int { location, .. }
|
||||
| Self::Todo { location, .. }
|
||||
| Self::ErrorTerm { location, .. }
|
||||
| Self::When { location, .. }
|
||||
| Self::Call { location, .. }
|
||||
|
|
|
@ -7,12 +7,13 @@ use crate::{
|
|||
ast::{
|
||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, ClauseGuard, Constant, DataType,
|
||||
Definition, Function, IfBranch, ModuleConstant, Pattern, RecordConstructor,
|
||||
RecordConstructorArg, RecordUpdateSpread, Span, TypeAlias, TypedArg, TypedConstant, UnOp,
|
||||
UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedDefinition,
|
||||
UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, CAPTURE_VARIABLE,
|
||||
RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg,
|
||||
TypedConstant, UnOp, UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard,
|
||||
UntypedDefinition, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use,
|
||||
CAPTURE_VARIABLE,
|
||||
},
|
||||
docvec,
|
||||
expr::UntypedExpr,
|
||||
expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
|
||||
parser::extra::{Comment, ModuleExtra},
|
||||
pretty::{break_, concat, flex_break, join, line, lines, nil, Document, Documentable},
|
||||
tipo::{self, Type},
|
||||
|
@ -654,9 +655,6 @@ impl<'comments> Formatter<'comments> {
|
|||
final_else,
|
||||
..
|
||||
} => self.if_expr(branches, final_else),
|
||||
UntypedExpr::Todo { label: None, .. } => "todo".to_doc(),
|
||||
|
||||
UntypedExpr::Todo { label: Some(l), .. } => docvec!["todo(\"", l, "\")"],
|
||||
|
||||
UntypedExpr::PipeLine { expressions, .. } => self.pipeline(expressions),
|
||||
|
||||
|
@ -706,27 +704,8 @@ impl<'comments> Formatter<'comments> {
|
|||
} => self.assignment(pattern, value, None, Some(*kind), annotation),
|
||||
|
||||
UntypedExpr::Trace {
|
||||
text: None, then, ..
|
||||
} => "trace"
|
||||
.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,
|
||||
..
|
||||
} => docvec!["trace(\"", l, "\")"]
|
||||
.append(if self.pop_empty_lines(then.start_byte_index()) {
|
||||
lines(2)
|
||||
} else {
|
||||
line()
|
||||
})
|
||||
.append(self.expr(then)),
|
||||
kind, text, then, ..
|
||||
} => self.trace(kind, text, then),
|
||||
|
||||
UntypedExpr::When {
|
||||
subjects, clauses, ..
|
||||
|
@ -755,9 +734,7 @@ impl<'comments> Formatter<'comments> {
|
|||
.append(suffix)
|
||||
}
|
||||
|
||||
UntypedExpr::ErrorTerm { label: None, .. } => "error".to_doc(),
|
||||
|
||||
UntypedExpr::ErrorTerm { label: Some(l), .. } => docvec!["error(\"", l, "\")"],
|
||||
UntypedExpr::ErrorTerm { .. } => "error".to_doc(),
|
||||
};
|
||||
|
||||
commented(document, comments)
|
||||
|
@ -772,6 +749,41 @@ impl<'comments> Formatter<'comments> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn trace<'a>(
|
||||
&mut self,
|
||||
kind: &'a TraceKind,
|
||||
text: &'a UntypedExpr,
|
||||
then: &'a UntypedExpr,
|
||||
) -> Document<'a> {
|
||||
let (keyword, default_text) = match kind {
|
||||
TraceKind::Trace => ("trace", None),
|
||||
TraceKind::Error => ("error", Some(DEFAULT_ERROR_STR.to_string())),
|
||||
TraceKind::Todo => ("todo", Some(DEFAULT_TODO_STR.to_string())),
|
||||
};
|
||||
|
||||
let body = match text {
|
||||
UntypedExpr::String { value, .. } if Some(value) == default_text.as_ref() => {
|
||||
keyword.to_doc()
|
||||
}
|
||||
_ => keyword
|
||||
.to_doc()
|
||||
.append(" ")
|
||||
.append(self.wrap_expr(text))
|
||||
.group(),
|
||||
};
|
||||
|
||||
match kind {
|
||||
TraceKind::Error | TraceKind::Todo => body,
|
||||
TraceKind::Trace => body
|
||||
.append(if self.pop_empty_lines(then.start_byte_index()) {
|
||||
lines(2)
|
||||
} else {
|
||||
line()
|
||||
})
|
||||
.append(self.expr(then)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pattern_constructor<'a>(
|
||||
&mut self,
|
||||
name: &'a str,
|
||||
|
@ -1322,7 +1334,10 @@ impl<'comments> Formatter<'comments> {
|
|||
|
||||
fn wrap_expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||
match expr {
|
||||
UntypedExpr::Trace { .. }
|
||||
UntypedExpr::Trace {
|
||||
kind: TraceKind::Trace,
|
||||
..
|
||||
}
|
||||
| UntypedExpr::Sequence { .. }
|
||||
| UntypedExpr::Assignment { .. } => "{"
|
||||
.to_doc()
|
||||
|
@ -1361,7 +1376,10 @@ impl<'comments> Formatter<'comments> {
|
|||
|
||||
fn case_clause_value<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||
match expr {
|
||||
UntypedExpr::Trace { .. }
|
||||
UntypedExpr::Trace {
|
||||
kind: TraceKind::Trace,
|
||||
..
|
||||
}
|
||||
| UntypedExpr::Sequence { .. }
|
||||
| UntypedExpr::Assignment { .. } => " {"
|
||||
.to_doc()
|
||||
|
|
|
@ -7,7 +7,7 @@ pub mod lexer;
|
|||
pub mod token;
|
||||
|
||||
use crate::{
|
||||
ast::{self, BinOp, Span, TodoKind, UnOp, UntypedDefinition, CAPTURE_VARIABLE},
|
||||
ast::{self, BinOp, Span, TraceKind, UnOp, UntypedDefinition, CAPTURE_VARIABLE},
|
||||
expr,
|
||||
};
|
||||
|
||||
|
@ -254,11 +254,7 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
|
|||
|((((opt_pub, name), (arguments, args_span)), return_annotation), body), span| {
|
||||
ast::UntypedDefinition::Fn(ast::Function {
|
||||
arguments,
|
||||
body: body.unwrap_or(expr::UntypedExpr::Todo {
|
||||
kind: TodoKind::EmptyFunction,
|
||||
location: span,
|
||||
label: None,
|
||||
}),
|
||||
body: body.unwrap_or_else(|| expr::UntypedExpr::todo(span, None)),
|
||||
doc: None,
|
||||
location: Span {
|
||||
start: span.start,
|
||||
|
@ -291,11 +287,7 @@ pub fn test_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
|||
.map_with_span(|((name, span_end), body), span| {
|
||||
ast::UntypedDefinition::Test(ast::Function {
|
||||
arguments: vec![],
|
||||
body: body.unwrap_or(expr::UntypedExpr::Todo {
|
||||
kind: TodoKind::EmptyFunction,
|
||||
location: span,
|
||||
label: None,
|
||||
}),
|
||||
body: body.unwrap_or_else(|| expr::UntypedExpr::todo(span, None)),
|
||||
doc: None,
|
||||
location: span_end,
|
||||
end_position: span.end - 1,
|
||||
|
@ -591,17 +583,20 @@ pub fn expr_seq_parser() -> impl Parser<Token, expr::UntypedExpr, Error = ParseE
|
|||
recursive(|r| {
|
||||
choice((
|
||||
just(Token::Trace)
|
||||
.ignore_then(
|
||||
select! {Token::String {value} => value}
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.or_not(),
|
||||
)
|
||||
.ignore_then(expr_parser(r.clone()))
|
||||
.then(r.clone())
|
||||
.map_with_span(|(text, then_), span| expr::UntypedExpr::Trace {
|
||||
kind: TraceKind::Trace,
|
||||
location: span,
|
||||
then: Box::new(then_),
|
||||
text,
|
||||
text: Box::new(text),
|
||||
}),
|
||||
just(Token::ErrorTerm)
|
||||
.ignore_then(expr_parser(r.clone()).or_not())
|
||||
.map_with_span(|reason, span| expr::UntypedExpr::error(span, reason)),
|
||||
just(Token::Todo)
|
||||
.ignore_then(expr_parser(r.clone()).or_not())
|
||||
.map_with_span(|reason, span| expr::UntypedExpr::todo(span, reason)),
|
||||
expr_parser(r.clone())
|
||||
.then(r.repeated())
|
||||
.foldl(|current, next| current.append_in_sequence(next)),
|
||||
|
@ -871,29 +866,6 @@ pub fn expr_parser(
|
|||
name,
|
||||
});
|
||||
|
||||
let todo_parser = just(Token::Todo)
|
||||
.ignore_then(
|
||||
select! {Token::String {value} => value}
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.or_not(),
|
||||
)
|
||||
.map_with_span(|label, span| expr::UntypedExpr::Todo {
|
||||
kind: TodoKind::Keyword,
|
||||
location: span,
|
||||
label,
|
||||
});
|
||||
|
||||
let error_parser = just(Token::ErrorTerm)
|
||||
.ignore_then(
|
||||
select! {Token::String {value} => value}
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.or_not(),
|
||||
)
|
||||
.map_with_span(|label, span| expr::UntypedExpr::ErrorTerm {
|
||||
location: span,
|
||||
label,
|
||||
});
|
||||
|
||||
let tuple = r
|
||||
.clone()
|
||||
.separated_by(just(Token::Comma))
|
||||
|
@ -988,7 +960,23 @@ pub fn expr_parser(
|
|||
}),
|
||||
)))
|
||||
// TODO: add hint "Did you mean to wrap a multi line clause in curly braces?"
|
||||
.then(r.clone())
|
||||
.then(choice((
|
||||
r.clone(),
|
||||
just(Token::Todo)
|
||||
.ignore_then(
|
||||
r.clone()
|
||||
.then_ignore(one_of(Token::RArrow).not().rewind())
|
||||
.or_not(),
|
||||
)
|
||||
.map_with_span(|reason, span| expr::UntypedExpr::todo(span, reason)),
|
||||
just(Token::ErrorTerm)
|
||||
.ignore_then(
|
||||
r.clone()
|
||||
.then_ignore(just(Token::RArrow).not().rewind())
|
||||
.or_not(),
|
||||
)
|
||||
.map_with_span(|reason, span| expr::UntypedExpr::error(span, reason)),
|
||||
)))
|
||||
.map_with_span(
|
||||
|(((patterns, alternative_patterns_opt), guard), then), span| ast::UntypedClause {
|
||||
location: span,
|
||||
|
@ -1084,8 +1072,6 @@ pub fn expr_parser(
|
|||
record_parser,
|
||||
field_access_constructor,
|
||||
var_parser,
|
||||
todo_parser,
|
||||
error_parser,
|
||||
tuple,
|
||||
bytearray,
|
||||
list_parser,
|
||||
|
|
|
@ -126,3 +126,35 @@ fn list_pattern_6() {
|
|||
"#;
|
||||
assert!(check(parse(source_code)).is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_strings() {
|
||||
let source_code = r#"
|
||||
fn bar() {
|
||||
"BAR"
|
||||
}
|
||||
|
||||
test foo() {
|
||||
let msg1 = "FOO"
|
||||
trace("INLINE")
|
||||
trace(msg1)
|
||||
trace(bar())
|
||||
True
|
||||
}
|
||||
"#;
|
||||
assert!(check(parse(source_code)).is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_non_strings() {
|
||||
let source_code = r#"
|
||||
test foo() {
|
||||
trace(14 + 42)
|
||||
True
|
||||
}
|
||||
"#;
|
||||
assert!(matches!(
|
||||
check(parse(source_code)),
|
||||
Err((_, Error::CouldNotUnify { .. }))
|
||||
))
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ fn test_nested_function_calls() {
|
|||
,
|
||||
when output.datum is {
|
||||
InlineDatum(_) -> True
|
||||
_ -> error("expected inline datum")
|
||||
_ -> error "expected inline datum"
|
||||
},
|
||||
]
|
||||
|> list.and
|
||||
|
@ -339,7 +339,7 @@ fn test_nested_function_calls() {
|
|||
),
|
||||
when output.datum is {
|
||||
InlineDatum(_) -> True
|
||||
_ -> error("expected inline datum")
|
||||
_ -> error "expected inline datum"
|
||||
},
|
||||
]
|
||||
|> list.and
|
||||
|
@ -348,3 +348,34 @@ fn test_nested_function_calls() {
|
|||
|
||||
assert_fmt(src, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_trace_todo_error() {
|
||||
let src = indoc! {r#"
|
||||
fn foo_1() {
|
||||
todo
|
||||
}
|
||||
|
||||
fn foo_2() {
|
||||
todo "my custom message"
|
||||
}
|
||||
|
||||
fn foo_3() {
|
||||
when x is {
|
||||
Foo -> True
|
||||
_ -> error
|
||||
}
|
||||
}
|
||||
|
||||
fn foo_4() {
|
||||
if 14 == 42 {
|
||||
error "I don't think so"
|
||||
} else {
|
||||
trace "been there"
|
||||
True
|
||||
}
|
||||
}
|
||||
"#};
|
||||
|
||||
assert_fmt(src, src);
|
||||
}
|
||||
|
|
|
@ -308,10 +308,16 @@ fn empty_function() {
|
|||
code,
|
||||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Todo {
|
||||
kind: ast::TodoKind::EmptyFunction,
|
||||
body: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Todo,
|
||||
location: Span::new((), 0..15),
|
||||
label: None,
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
value: "aiken::todo".to_string(),
|
||||
location: Span::new((), 0..15),
|
||||
}),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 0..15),
|
||||
}),
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 0..12),
|
||||
|
@ -1781,10 +1787,16 @@ fn function_def() {
|
|||
vec![ast::UntypedDefinition::Fn(Function {
|
||||
doc: None,
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Todo {
|
||||
kind: ast::TodoKind::EmptyFunction,
|
||||
body: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Todo,
|
||||
location: Span::new((), 0..11),
|
||||
label: None,
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
value: "aiken::todo".to_string(),
|
||||
location: Span::new((), 0..11),
|
||||
}),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 0..11),
|
||||
}),
|
||||
},
|
||||
location: Span::new((), 0..8),
|
||||
name: "foo".to_string(),
|
||||
|
@ -2586,3 +2598,345 @@ fn scope_logical_expression() {
|
|||
})],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_expressions() {
|
||||
let code = indoc! {r#"
|
||||
fn foo() {
|
||||
let msg1 = "FOO"
|
||||
trace "INLINE"
|
||||
trace msg1
|
||||
trace string.concat(msg1, "BAR")
|
||||
trace ( 14 + 42 * 1337 )
|
||||
Void
|
||||
}
|
||||
"#};
|
||||
assert_definitions(
|
||||
code,
|
||||
vec![ast::Definition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Sequence {
|
||||
location: Span::new((), 13..128),
|
||||
expressions: vec![
|
||||
expr::UntypedExpr::Assignment {
|
||||
location: Span::new((), 13..29),
|
||||
value: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 24..29),
|
||||
value: "FOO".to_string(),
|
||||
}),
|
||||
pattern: ast::Pattern::Var {
|
||||
location: Span::new((), 17..21),
|
||||
name: "msg1".to_string(),
|
||||
},
|
||||
kind: ast::AssignmentKind::Let,
|
||||
annotation: None,
|
||||
},
|
||||
expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Trace,
|
||||
location: Span::new((), 32..128),
|
||||
then: Box::new(expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Trace,
|
||||
location: Span::new((), 49..128),
|
||||
then: Box::new(expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Trace,
|
||||
location: Span::new((), 62..128),
|
||||
then: Box::new(expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Trace,
|
||||
location: Span::new((), 97..128),
|
||||
then: Box::new(expr::UntypedExpr::Var {
|
||||
location: Span::new((), 124..128),
|
||||
name: "Void".to_string(),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::BinOp {
|
||||
location: Span::new((), 105..119),
|
||||
name: ast::BinOp::AddInt,
|
||||
left: Box::new(expr::UntypedExpr::Int {
|
||||
location: Span::new((), 105..107),
|
||||
value: "14".to_string(),
|
||||
}),
|
||||
right: Box::new(expr::UntypedExpr::BinOp {
|
||||
location: Span::new((), 110..119),
|
||||
name: ast::BinOp::MultInt,
|
||||
left: Box::new(expr::UntypedExpr::Int {
|
||||
location: Span::new((), 110..112),
|
||||
value: "42".to_string(),
|
||||
}),
|
||||
right: Box::new(expr::UntypedExpr::Int {
|
||||
location: Span::new((), 115..119),
|
||||
value: "1337".to_string(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::Call {
|
||||
arguments: vec![
|
||||
ast::CallArg {
|
||||
label: None,
|
||||
location: Span::new((), 82..86),
|
||||
value: expr::UntypedExpr::Var {
|
||||
location: Span::new((), 82..86),
|
||||
name: "msg1".to_string(),
|
||||
},
|
||||
},
|
||||
ast::CallArg {
|
||||
label: None,
|
||||
location: Span::new((), 88..93),
|
||||
value: expr::UntypedExpr::String {
|
||||
location: Span::new((), 88..93),
|
||||
value: "BAR".to_string(),
|
||||
},
|
||||
},
|
||||
],
|
||||
fun: Box::new(expr::UntypedExpr::FieldAccess {
|
||||
location: Span::new((), 68..81),
|
||||
label: "concat".to_string(),
|
||||
container: Box::new(expr::UntypedExpr::Var {
|
||||
location: Span::new((), 68..74),
|
||||
name: "string".to_string(),
|
||||
}),
|
||||
}),
|
||||
location: Span::new((), 68..94),
|
||||
}),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::Var {
|
||||
location: Span::new((), 55..59),
|
||||
name: "msg1".to_string(),
|
||||
}),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 38..46),
|
||||
value: "INLINE".to_string(),
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 0..8),
|
||||
name: "foo".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 129,
|
||||
})],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_keyword_error() {
|
||||
let code = indoc! {r#"
|
||||
fn foo() {
|
||||
error "not implemented"
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
when x is {
|
||||
Something -> Void
|
||||
_ -> error
|
||||
}
|
||||
}
|
||||
"#};
|
||||
assert_definitions(
|
||||
code,
|
||||
vec![
|
||||
ast::Definition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Error,
|
||||
location: Span::new((), 13..36),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 13..36),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 19..36),
|
||||
value: "not implemented".to_string(),
|
||||
}),
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 0..8),
|
||||
name: "foo".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 37,
|
||||
}),
|
||||
ast::Definition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::When {
|
||||
location: Span::new((), 53..109),
|
||||
subjects: vec![expr::UntypedExpr::Var {
|
||||
location: Span::new((), 58..59),
|
||||
name: "x".to_string(),
|
||||
}],
|
||||
clauses: vec![
|
||||
ast::Clause {
|
||||
location: Span::new((), 71..88),
|
||||
pattern: vec![ast::Pattern::Constructor {
|
||||
is_record: false,
|
||||
location: Span::new((), 71..80),
|
||||
name: "Something".to_string(),
|
||||
arguments: vec![],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}],
|
||||
alternative_patterns: vec![],
|
||||
guard: None,
|
||||
then: expr::UntypedExpr::Var {
|
||||
location: Span::new((), 84..88),
|
||||
name: "Void".to_string(),
|
||||
},
|
||||
},
|
||||
ast::Clause {
|
||||
location: Span::new((), 95..105),
|
||||
pattern: vec![ast::Pattern::Discard {
|
||||
name: "_".to_string(),
|
||||
location: Span::new((), 95..96),
|
||||
}],
|
||||
alternative_patterns: vec![],
|
||||
guard: None,
|
||||
then: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Error,
|
||||
location: Span::new((), 100..105),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 100..105),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 100..105),
|
||||
value: "aiken::error".to_string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 40..48),
|
||||
name: "bar".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 110,
|
||||
}),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_keyword_todo() {
|
||||
let code = indoc! {r#"
|
||||
fn foo() {
|
||||
todo "not implemented"
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
when x is {
|
||||
Foo -> todo
|
||||
Bar -> True
|
||||
_ -> False
|
||||
}
|
||||
}
|
||||
"#};
|
||||
assert_definitions(
|
||||
code,
|
||||
vec![
|
||||
ast::Definition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Todo,
|
||||
location: Span::new((), 13..35),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 13..35),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 18..35),
|
||||
value: "not implemented".to_string(),
|
||||
}),
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 0..8),
|
||||
name: "foo".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 36,
|
||||
}),
|
||||
ast::Definition::Fn(Function {
|
||||
arguments: vec![],
|
||||
body: expr::UntypedExpr::When {
|
||||
location: Span::new((), 52..120),
|
||||
subjects: vec![expr::UntypedExpr::Var {
|
||||
location: Span::new((), 57..58),
|
||||
name: "x".to_string(),
|
||||
}],
|
||||
clauses: vec![
|
||||
ast::Clause {
|
||||
location: Span::new((), 70..81),
|
||||
pattern: vec![ast::Pattern::Constructor {
|
||||
is_record: false,
|
||||
location: Span::new((), 70..73),
|
||||
name: "Foo".to_string(),
|
||||
arguments: vec![],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}],
|
||||
alternative_patterns: vec![],
|
||||
guard: None,
|
||||
then: expr::UntypedExpr::Trace {
|
||||
kind: ast::TraceKind::Todo,
|
||||
location: Span::new((), 77..81),
|
||||
then: Box::new(expr::UntypedExpr::ErrorTerm {
|
||||
location: Span::new((), 77..81),
|
||||
}),
|
||||
text: Box::new(expr::UntypedExpr::String {
|
||||
location: Span::new((), 77..81),
|
||||
value: "aiken::todo".to_string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
ast::Clause {
|
||||
location: Span::new((), 88..99),
|
||||
pattern: vec![ast::Pattern::Constructor {
|
||||
is_record: false,
|
||||
location: Span::new((), 88..91),
|
||||
name: "Bar".to_string(),
|
||||
arguments: vec![],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
}],
|
||||
alternative_patterns: vec![],
|
||||
guard: None,
|
||||
then: expr::UntypedExpr::Var {
|
||||
location: Span::new((), 95..99),
|
||||
name: "True".to_string(),
|
||||
},
|
||||
},
|
||||
ast::Clause {
|
||||
location: Span::new((), 106..116),
|
||||
pattern: vec![ast::Pattern::Discard {
|
||||
name: "_".to_string(),
|
||||
location: Span::new((), 106..107),
|
||||
}],
|
||||
alternative_patterns: vec![],
|
||||
guard: None,
|
||||
then: expr::UntypedExpr::Var {
|
||||
location: Span::new((), 111..116),
|
||||
name: "False".to_string(),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
doc: None,
|
||||
location: Span::new((), 39..47),
|
||||
name: "bar".to_string(),
|
||||
public: false,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
end_position: 121,
|
||||
}),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::Type;
|
||||
use crate::{
|
||||
ast::{Annotation, BinOp, CallArg, Span, TodoKind, UntypedPattern},
|
||||
ast::{Annotation, BinOp, CallArg, Span, UntypedPattern},
|
||||
expr::{self, UntypedExpr},
|
||||
format::Formatter,
|
||||
levenshtein,
|
||||
|
@ -1118,7 +1118,6 @@ pub enum Warning {
|
|||
#[diagnostic(help("You probably want to replace that one with real code... eventually."))]
|
||||
#[diagnostic(code("todo"))]
|
||||
Todo {
|
||||
kind: TodoKind,
|
||||
#[label]
|
||||
location: Span,
|
||||
tipo: Arc<Type>,
|
||||
|
|
|
@ -5,7 +5,7 @@ use vec1::Vec1;
|
|||
use crate::{
|
||||
ast::{
|
||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, Clause, ClauseGuard, Constant,
|
||||
RecordUpdateSpread, Span, TodoKind, TypedArg, TypedCallArg, TypedClause, TypedClauseGuard,
|
||||
RecordUpdateSpread, Span, TraceKind, TypedArg, TypedCallArg, TypedClause, TypedClauseGuard,
|
||||
TypedConstant, TypedIfBranch, TypedMultiPattern, TypedRecordUpdateArg, UnOp, UntypedArg,
|
||||
UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedIfBranch, UntypedMultiPattern,
|
||||
UntypedPattern, UntypedRecordUpdateArg,
|
||||
|
@ -221,7 +221,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
| UntypedExpr::RecordUpdate { .. }
|
||||
| UntypedExpr::Sequence { .. }
|
||||
| UntypedExpr::String { .. }
|
||||
| UntypedExpr::Todo { .. }
|
||||
| UntypedExpr::Tuple { .. }
|
||||
| UntypedExpr::TupleIndex { .. }
|
||||
| UntypedExpr::UnOp { .. }
|
||||
|
@ -249,16 +248,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
/// returning an error.
|
||||
pub fn infer(&mut self, expr: UntypedExpr) -> Result<TypedExpr, Error> {
|
||||
match expr {
|
||||
UntypedExpr::Todo {
|
||||
location,
|
||||
label,
|
||||
kind,
|
||||
..
|
||||
} => Ok(self.infer_todo(location, kind, label)),
|
||||
|
||||
UntypedExpr::ErrorTerm { location, label } => {
|
||||
Ok(self.infer_error_term(location, label))
|
||||
}
|
||||
UntypedExpr::ErrorTerm { location } => Ok(self.infer_error_term(location)),
|
||||
|
||||
UntypedExpr::Var { location, name, .. } => self.infer_var(name, location),
|
||||
|
||||
|
@ -309,7 +299,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
location,
|
||||
then,
|
||||
text,
|
||||
} => self.infer_trace(*then, location, text),
|
||||
kind,
|
||||
} => self.infer_trace(kind, *then, location, *text),
|
||||
|
||||
UntypedExpr::When {
|
||||
location,
|
||||
|
@ -1857,47 +1848,37 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
fn infer_todo(&mut self, location: Span, kind: TodoKind, label: Option<String>) -> TypedExpr {
|
||||
fn infer_error_term(&mut self, location: Span) -> TypedExpr {
|
||||
let tipo = self.new_unbound_var();
|
||||
|
||||
self.environment.warnings.push(Warning::Todo {
|
||||
kind,
|
||||
location,
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
|
||||
TypedExpr::Todo {
|
||||
location,
|
||||
label,
|
||||
tipo,
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_error_term(&mut self, location: Span, label: Option<String>) -> TypedExpr {
|
||||
let tipo = self.new_unbound_var();
|
||||
|
||||
TypedExpr::ErrorTerm {
|
||||
location,
|
||||
tipo,
|
||||
label,
|
||||
}
|
||||
TypedExpr::ErrorTerm { location, tipo }
|
||||
}
|
||||
|
||||
fn infer_trace(
|
||||
&mut self,
|
||||
kind: TraceKind,
|
||||
then: UntypedExpr,
|
||||
location: Span,
|
||||
text: Option<String>,
|
||||
text: UntypedExpr,
|
||||
) -> Result<TypedExpr, Error> {
|
||||
let then = self.infer(then)?;
|
||||
let text = self.infer(text)?;
|
||||
self.unify(text.tipo(), string(), text.location(), false)?;
|
||||
|
||||
let then = self.infer(then)?;
|
||||
let tipo = then.tipo();
|
||||
|
||||
if let TraceKind::Todo = kind {
|
||||
self.environment.warnings.push(Warning::Todo {
|
||||
location,
|
||||
tipo: tipo.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(TypedExpr::Trace {
|
||||
location,
|
||||
tipo,
|
||||
then: Box::new(then),
|
||||
text,
|
||||
text: Box::new(text),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -587,13 +587,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
constants_ir(literal, ir_stack, scope);
|
||||
}
|
||||
},
|
||||
TypedExpr::Todo { label, tipo, .. } => {
|
||||
ir_stack.push(Air::Todo {
|
||||
scope,
|
||||
label: label.clone(),
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
}
|
||||
TypedExpr::RecordUpdate {
|
||||
spread, args, tipo, ..
|
||||
} => {
|
||||
|
@ -651,19 +644,21 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
ir_stack.append(&mut elems_air);
|
||||
}
|
||||
|
||||
TypedExpr::Trace {
|
||||
tipo, then, text, ..
|
||||
} => {
|
||||
let mut scope = scope;
|
||||
|
||||
ir_stack.push(Air::Trace {
|
||||
text: text.clone(),
|
||||
tipo: tipo.clone(),
|
||||
scope: scope.clone(),
|
||||
});
|
||||
|
||||
scope.push(self.id_gen.next());
|
||||
self.build_ir(text, ir_stack, scope.clone());
|
||||
|
||||
scope.push(self.id_gen.next());
|
||||
self.build_ir(then, ir_stack, scope);
|
||||
}
|
||||
|
||||
|
@ -677,11 +672,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
self.build_ir(tuple, ir_stack, scope);
|
||||
}
|
||||
|
||||
TypedExpr::ErrorTerm { tipo, label, .. } => {
|
||||
TypedExpr::ErrorTerm { tipo, .. } => {
|
||||
ir_stack.push(Air::ErrorTerm {
|
||||
scope,
|
||||
tipo: tipo.clone(),
|
||||
label: label.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2566,10 +2560,19 @@ impl<'a> CodeGenerator<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
assert_vec.push(Air::Trace {
|
||||
scope: scope.clone(),
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
|
||||
assert_vec.push(Air::String {
|
||||
scope: scope.clone(),
|
||||
value: "Constr index did not match any type variant".to_string(),
|
||||
});
|
||||
|
||||
assert_vec.push(Air::ErrorTerm {
|
||||
scope,
|
||||
tipo: tipo.clone(),
|
||||
label: Some("Constr index did not match any type variant".to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3484,33 +3487,21 @@ impl<'a> CodeGenerator<'a> {
|
|||
tuple_index,
|
||||
};
|
||||
}
|
||||
Air::Todo { tipo, scope, label } => {
|
||||
let mut replaced_type = tipo.clone();
|
||||
replace_opaque_type(&mut replaced_type, self.data_types.clone());
|
||||
|
||||
ir_stack[index] = Air::Todo {
|
||||
scope,
|
||||
label,
|
||||
tipo: replaced_type,
|
||||
};
|
||||
}
|
||||
Air::ErrorTerm { tipo, scope, label } => {
|
||||
Air::ErrorTerm { tipo, scope } => {
|
||||
let mut replaced_type = tipo.clone();
|
||||
replace_opaque_type(&mut replaced_type, self.data_types.clone());
|
||||
|
||||
ir_stack[index] = Air::ErrorTerm {
|
||||
scope,
|
||||
tipo: replaced_type,
|
||||
label,
|
||||
};
|
||||
}
|
||||
Air::Trace { tipo, scope, text } => {
|
||||
Air::Trace { tipo, scope } => {
|
||||
let mut replaced_type = tipo.clone();
|
||||
replace_opaque_type(&mut replaced_type, self.data_types.clone());
|
||||
|
||||
ir_stack[index] = Air::Trace {
|
||||
scope,
|
||||
text,
|
||||
tipo: replaced_type,
|
||||
};
|
||||
}
|
||||
|
@ -5278,23 +5269,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
arg_stack.push(term);
|
||||
}
|
||||
}
|
||||
Air::Todo { label, .. } => {
|
||||
let term = apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
||||
Term::Constant(
|
||||
UplcConstant::String(
|
||||
label.unwrap_or_else(|| "aiken::todo".to_string()),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
Term::Delay(Term::Error.into()),
|
||||
)
|
||||
.force_wrap();
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::RecordUpdate {
|
||||
highest_index,
|
||||
indices,
|
||||
|
@ -5631,41 +5605,20 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::Trace { text, .. } => {
|
||||
Air::Trace { .. } => {
|
||||
let text = arg_stack.pop().unwrap();
|
||||
|
||||
let term = arg_stack.pop().unwrap();
|
||||
|
||||
let term = apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
||||
Term::Constant(
|
||||
UplcConstant::String(
|
||||
text.unwrap_or_else(|| "aiken::trace".to_string()),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
),
|
||||
apply_wrap(Term::Builtin(DefaultFunction::Trace).force_wrap(), text),
|
||||
Term::Delay(term.into()),
|
||||
)
|
||||
.force_wrap();
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::ErrorTerm { label, .. } => {
|
||||
if let Some(label) = label {
|
||||
let term = apply_wrap(
|
||||
apply_wrap(
|
||||
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
||||
Term::Constant(UplcConstant::String(label).into()),
|
||||
),
|
||||
Term::Delay(Term::Error.into()),
|
||||
)
|
||||
.force_wrap();
|
||||
|
||||
arg_stack.push(term);
|
||||
} else {
|
||||
arg_stack.push(Term::Error)
|
||||
}
|
||||
}
|
||||
Air::ErrorTerm { .. } => arg_stack.push(Term::Error),
|
||||
Air::TupleClause {
|
||||
tipo,
|
||||
indices,
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
use aiken/builtin
|
||||
|
||||
fn concat(left: String, right: String) -> String {
|
||||
builtin.append_bytearray(
|
||||
builtin.encode_utf8(left),
|
||||
builtin.encode_utf8(right),
|
||||
)
|
||||
|> builtin.decode_utf8
|
||||
}
|
||||
|
||||
fn is_negative(i: Int) -> Bool {
|
||||
if i < 0 {
|
||||
trace("is negative")
|
||||
trace "is negative"
|
||||
True
|
||||
} else {
|
||||
trace("is non-negative")
|
||||
trace concat("is", concat(" ", "non-negative"))
|
||||
False
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue