feat: add trace
This commit is contained in:
parent
9068c89c00
commit
429126e38f
|
@ -203,6 +203,12 @@ pub enum Air {
|
|||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
Trace {
|
||||
scope: Vec<u64>,
|
||||
text: Option<String>,
|
||||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
Record {
|
||||
scope: Vec<u64>,
|
||||
},
|
||||
|
@ -261,6 +267,7 @@ impl Air {
|
|||
| Air::Record { scope, .. }
|
||||
| Air::RecordUpdate { scope, .. }
|
||||
| Air::Negate { scope, .. }
|
||||
| Air::Trace { scope, .. }
|
||||
| Air::TupleAccessor { scope, .. } => scope.to_vec(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -344,13 +344,7 @@ pub fn from_default_function(
|
|||
Some((tipo, 3))
|
||||
}
|
||||
DefaultFunction::ChooseUnit => None,
|
||||
DefaultFunction::Trace => {
|
||||
let ret = generic_var(id_gen.next());
|
||||
|
||||
let tipo = function(vec![string(), ret.clone()], ret);
|
||||
|
||||
Some((tipo, 2))
|
||||
}
|
||||
DefaultFunction::Trace => None,
|
||||
DefaultFunction::FstPair => None,
|
||||
DefaultFunction::SndPair => None,
|
||||
DefaultFunction::ChooseList => None,
|
||||
|
|
|
@ -91,6 +91,13 @@ pub enum TypedExpr {
|
|||
kind: AssignmentKind,
|
||||
},
|
||||
|
||||
Trace {
|
||||
location: Span,
|
||||
tipo: Arc<Type>,
|
||||
then: Box<Self>,
|
||||
text: Option<String>,
|
||||
},
|
||||
|
||||
When {
|
||||
location: Span,
|
||||
tipo: Arc<Type>,
|
||||
|
@ -158,6 +165,7 @@ impl TypedExpr {
|
|||
match self {
|
||||
Self::Negate { .. } => bool(),
|
||||
Self::Var { constructor, .. } => constructor.tipo.clone(),
|
||||
Self::Trace {then, ..} => then.tipo(),
|
||||
Self::Fn { tipo, .. }
|
||||
| Self::Int { tipo, .. }
|
||||
| Self::Todo { tipo, .. }
|
||||
|
@ -200,6 +208,7 @@ impl TypedExpr {
|
|||
match self {
|
||||
TypedExpr::Fn { .. }
|
||||
| TypedExpr::Int { .. }
|
||||
| TypedExpr::Trace { .. }
|
||||
| TypedExpr::List { .. }
|
||||
| TypedExpr::Call { .. }
|
||||
| TypedExpr::When { .. }
|
||||
|
@ -240,6 +249,7 @@ impl TypedExpr {
|
|||
Self::Fn { location, .. }
|
||||
| Self::Int { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Trace { location, .. }
|
||||
| Self::Todo { location, .. }
|
||||
| Self::When { location, .. }
|
||||
| Self::Call { location, .. }
|
||||
|
@ -276,6 +286,7 @@ impl TypedExpr {
|
|||
match self {
|
||||
Self::Fn { location, .. }
|
||||
| Self::Int { location, .. }
|
||||
| Self::Trace { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Todo { location, .. }
|
||||
| Self::When { location, .. }
|
||||
|
@ -363,7 +374,11 @@ pub enum UntypedExpr {
|
|||
kind: AssignmentKind,
|
||||
annotation: Option<Annotation>,
|
||||
},
|
||||
|
||||
Trace {
|
||||
location: Span,
|
||||
then: Box<Self>,
|
||||
text: Option<String>,
|
||||
},
|
||||
When {
|
||||
location: Span,
|
||||
subjects: Vec<Self>,
|
||||
|
@ -462,6 +477,7 @@ impl UntypedExpr {
|
|||
pub fn location(&self) -> Span {
|
||||
match self {
|
||||
Self::PipeLine { expressions, .. } => expressions.last().location(),
|
||||
Self::Trace { then, .. } => then.location(),
|
||||
Self::Fn { location, .. }
|
||||
| Self::Var { location, .. }
|
||||
| Self::Int { location, .. }
|
||||
|
@ -498,7 +514,7 @@ impl UntypedExpr {
|
|||
.map(|e| e.start_byte_index())
|
||||
.unwrap_or(location.start),
|
||||
Self::PipeLine { expressions, .. } => expressions.first().start_byte_index(),
|
||||
Self::Assignment { location, .. } => location.start,
|
||||
Self::Trace { location, .. } | Self::Assignment { location, .. } => location.start,
|
||||
_ => self.location().start,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -751,6 +751,29 @@ 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)),
|
||||
|
||||
UntypedExpr::When {
|
||||
subjects, clauses, ..
|
||||
} => self.when(subjects, clauses),
|
||||
|
@ -1319,7 +1342,9 @@ impl<'comments> Formatter<'comments> {
|
|||
|
||||
fn wrap_expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||
match expr {
|
||||
UntypedExpr::Sequence { .. } | UntypedExpr::Assignment { .. } => "{"
|
||||
UntypedExpr::Trace { .. }
|
||||
| UntypedExpr::Sequence { .. }
|
||||
| UntypedExpr::Assignment { .. } => "{"
|
||||
.to_doc()
|
||||
.append(line().append(self.expr(expr)).nest(INDENT))
|
||||
.append(line())
|
||||
|
@ -1356,7 +1381,9 @@ impl<'comments> Formatter<'comments> {
|
|||
|
||||
fn case_clause_value<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||
match expr {
|
||||
UntypedExpr::Sequence { .. } | UntypedExpr::Assignment { .. } => " {"
|
||||
UntypedExpr::Trace { .. }
|
||||
| UntypedExpr::Sequence { .. }
|
||||
| UntypedExpr::Assignment { .. } => " {"
|
||||
.to_doc()
|
||||
.append(line().append(self.expr(expr)).nest(INDENT).group())
|
||||
.append(line())
|
||||
|
|
|
@ -553,9 +553,23 @@ 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> {
|
||||
recursive(|r| {
|
||||
expr_parser(r.clone())
|
||||
.then(r.repeated())
|
||||
.foldl(|current, next| current.append_in_sequence(next))
|
||||
choice((
|
||||
just(Token::Trace)
|
||||
.ignore_then(
|
||||
select! {Token::String {value} => value}
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.or_not(),
|
||||
)
|
||||
.then(r.clone())
|
||||
.map_with_span(|(text, then_), span| expr::UntypedExpr::Trace {
|
||||
location: span,
|
||||
then: Box::new(then_),
|
||||
text,
|
||||
}),
|
||||
expr_parser(r.clone())
|
||||
.then(r.repeated())
|
||||
.foldl(|current, next| current.append_in_sequence(next)),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
|||
.labelled("string");
|
||||
|
||||
let keyword = text::ident().map(|s: String| match s.as_str() {
|
||||
"trace" => Token::Trace,
|
||||
"as" => Token::As,
|
||||
"assert" => Token::Assert,
|
||||
"check" => Token::Assert,
|
||||
|
|
|
@ -73,6 +73,7 @@ pub enum Token {
|
|||
Todo,
|
||||
Type,
|
||||
When,
|
||||
Trace,
|
||||
}
|
||||
|
||||
impl fmt::Display for Token {
|
||||
|
@ -144,6 +145,7 @@ impl fmt::Display for Token {
|
|||
Token::Opaque => "opaque",
|
||||
Token::Pub => "pub",
|
||||
Token::Todo => "todo",
|
||||
Token::Trace => "trace",
|
||||
Token::Type => "type",
|
||||
Token::Test => "test",
|
||||
};
|
||||
|
|
|
@ -279,6 +279,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
..
|
||||
} => self.infer_assignment(pattern, *value, kind, &annotation, location),
|
||||
|
||||
UntypedExpr::Trace {
|
||||
location,
|
||||
then,
|
||||
text,
|
||||
} => self.infer_trace(*then, location, text),
|
||||
|
||||
UntypedExpr::When {
|
||||
location,
|
||||
subjects,
|
||||
|
@ -1711,6 +1717,24 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn infer_trace(
|
||||
&mut self,
|
||||
then: UntypedExpr,
|
||||
location: Span,
|
||||
text: Option<String>,
|
||||
) -> Result<TypedExpr, Error> {
|
||||
let then = self.infer(then)?;
|
||||
|
||||
let tipo = then.tipo();
|
||||
|
||||
Ok(TypedExpr::Trace {
|
||||
location,
|
||||
tipo,
|
||||
then: Box::new(then),
|
||||
text,
|
||||
})
|
||||
}
|
||||
|
||||
fn infer_value_constructor(
|
||||
&mut self,
|
||||
module: &Option<String>,
|
||||
|
|
|
@ -475,6 +475,7 @@ fn str_to_keyword(word: &str) -> Option<Token> {
|
|||
"pub" => Some(Token::Pub),
|
||||
"todo" => Some(Token::Todo),
|
||||
"type" => Some(Token::Type),
|
||||
"trace" => Some(Token::Trace),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -517,6 +517,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(then, ir_stack, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3517,8 +3532,20 @@ impl<'a> CodeGenerator<'a> {
|
|||
arg_stack.push(term);
|
||||
}
|
||||
}
|
||||
Air::Todo { .. } => {
|
||||
arg_stack.push(Term::Error);
|
||||
Air::Todo { label, .. } => {
|
||||
let term = Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::Trace).force_wrap().into(),
|
||||
argument: Term::Constant(uplc::ast::Constant::String(
|
||||
label.unwrap_or_else(|| "aiken::todo".to_string()),
|
||||
))
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Error.into(),
|
||||
};
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::Record { .. } => todo!(),
|
||||
Air::RecordUpdate { .. } => todo!(),
|
||||
|
@ -3677,6 +3704,23 @@ impl<'a> CodeGenerator<'a> {
|
|||
};
|
||||
}
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
Air::Trace { text, .. } => {
|
||||
let term = arg_stack.pop().unwrap();
|
||||
|
||||
let term = Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Builtin(DefaultFunction::Trace).force_wrap().into(),
|
||||
argument: Term::Constant(uplc::ast::Constant::String(
|
||||
text.unwrap_or_else(|| "aike::trace".to_string()),
|
||||
))
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: term.into(),
|
||||
};
|
||||
|
||||
arg_stack.push(term);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
build/
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -0,0 +1,5 @@
|
|||
# This file was generated by Aiken
|
||||
# You typically do not need to edit this file
|
||||
|
||||
requirements = []
|
||||
packages = []
|
|
@ -1,2 +1,2 @@
|
|||
name = "acceptance_test_032"
|
||||
name = "aiken-lang/acceptance_test_032"
|
||||
version = "0.0.0"
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use aiken/builtin
|
||||
|
||||
fn is_negative(i : Int) -> Bool {
|
||||
fn is_negative(i: Int) -> Bool {
|
||||
if i < 0 {
|
||||
builtin.trace("is negative", True)
|
||||
trace("is negative")
|
||||
|
||||
True
|
||||
} else {
|
||||
builtin.trace("is non-negative", False)
|
||||
trace("is non-negative")
|
||||
|
||||
False
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
test trace_1() {
|
||||
is_negative(-14) && !is_negative(42)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue