mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 10:12:21 +03:00
wip
This commit is contained in:
parent
881ee569d1
commit
9f56b34677
@ -165,8 +165,8 @@ impl<'a> Compiler<'a> {
|
||||
}
|
||||
|
||||
/// Runs the static single assignment pass.
|
||||
pub fn static_single_assignment_pass(&mut self) -> Result<()> {
|
||||
self.ast = StaticSingleAssigner::do_pass((std::mem::take(&mut self.ast), self.handler))?;
|
||||
pub fn static_single_assignment_pass(&mut self, symbol_table: &SymbolTable) -> Result<()> {
|
||||
self.ast = StaticSingleAssigner::do_pass((std::mem::take(&mut self.ast), self.handler, symbol_table))?;
|
||||
|
||||
if self.output_options.ssa_ast {
|
||||
self.write_ast_to_json("ssa_ast.json")?;
|
||||
@ -184,7 +184,7 @@ impl<'a> Compiler<'a> {
|
||||
let st = self.loop_unrolling_pass(st)?;
|
||||
|
||||
// TODO: Make this pass optional.
|
||||
self.static_single_assignment_pass()?;
|
||||
self.static_single_assignment_pass(&st)?;
|
||||
|
||||
Ok(st)
|
||||
}
|
||||
|
@ -193,8 +193,8 @@ fn temp_dir() -> PathBuf {
|
||||
fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>, handler: &Handler) -> Result<String, LeoError> {
|
||||
let st = parsed.symbol_table_pass()?;
|
||||
let st = parsed.type_checker_pass(st)?;
|
||||
let _st = parsed.loop_unrolling_pass(st)?;
|
||||
parsed.static_single_assignment_pass()?;
|
||||
let st = parsed.loop_unrolling_pass(st)?;
|
||||
parsed.static_single_assignment_pass(&st)?;
|
||||
|
||||
// Compile Leo program to bytecode.
|
||||
let bytecode = CodeGenerator::do_pass((&parsed.ast, handler))?;
|
||||
|
@ -57,17 +57,17 @@ pub(crate) use rename_table::*;
|
||||
pub mod static_single_assigner;
|
||||
pub use static_single_assigner::*;
|
||||
|
||||
use crate::Pass;
|
||||
use crate::{Pass, SymbolTable};
|
||||
|
||||
use leo_ast::{Ast, ProgramConsumer};
|
||||
use leo_errors::{emitter::Handler, Result};
|
||||
|
||||
impl<'a> Pass for StaticSingleAssigner<'a> {
|
||||
type Input = (Ast, &'a Handler);
|
||||
type Input = (Ast, &'a Handler, &'a SymbolTable);
|
||||
type Output = Result<Ast>;
|
||||
|
||||
fn do_pass((ast, handler): Self::Input) -> Self::Output {
|
||||
let mut consumer = StaticSingleAssigner::new(handler);
|
||||
fn do_pass((ast, handler, st): Self::Input) -> Self::Output {
|
||||
let mut consumer = StaticSingleAssigner::new(handler, st);
|
||||
let program = consumer.consume_program(ast.into_repr());
|
||||
handler.last_err()?;
|
||||
|
||||
|
@ -15,12 +15,9 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::StaticSingleAssigner;
|
||||
use itertools::Itertools;
|
||||
|
||||
use leo_ast::{
|
||||
AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, CircuitExpression,
|
||||
CircuitVariableInitializer, ErrExpression, Expression, ExpressionConsumer, Identifier, Literal, MemberAccess,
|
||||
Statement, TernaryExpression, TupleAccess, TupleExpression, UnaryExpression,
|
||||
};
|
||||
use leo_ast::{AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, CircuitExpression, CircuitMember, CircuitVariableInitializer, ErrExpression, Expression, ExpressionConsumer, Identifier, Literal, MemberAccess, Statement, TernaryExpression, TupleAccess, TupleExpression, UnaryExpression};
|
||||
|
||||
impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
type Output = (Expression, Vec<Statement>);
|
||||
@ -155,16 +152,23 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Construct and accumulate a new assignment statement for the call expression.
|
||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Circuit(CircuitExpression {
|
||||
name: input.name,
|
||||
span: input.span,
|
||||
members,
|
||||
}));
|
||||
statements.push(statement);
|
||||
|
||||
// Add the variable to the set of circuit variables.
|
||||
match place {
|
||||
Expression::Identifier(identifier) => self.circuits.insert(identifier.name),
|
||||
_ => unreachable!("`place` is always an identifier"),
|
||||
};
|
||||
|
||||
// Note that we do not construct a new assignment statement for the tuple expression.
|
||||
// Expressions that produce compound data types need to be handled separately.
|
||||
(
|
||||
Expression::Circuit(CircuitExpression {
|
||||
name: input.name,
|
||||
span: input.span,
|
||||
members,
|
||||
}),
|
||||
statements,
|
||||
)
|
||||
(place, statements)
|
||||
}
|
||||
|
||||
/// `ErrExpressions` should not exist and thus do not need to be handled.
|
||||
@ -217,16 +221,79 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
statements.append(&mut if_true_statements);
|
||||
statements.append(&mut if_false_statements);
|
||||
|
||||
// Construct and accumulate a unique assignment statement storing the result of the ternary expression.
|
||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(cond_expr),
|
||||
if_true: Box::new(if_true_expr),
|
||||
if_false: Box::new(if_false_expr),
|
||||
span: input.span,
|
||||
}));
|
||||
statements.push(statement);
|
||||
match (if_true_expr, if_false_expr) {
|
||||
(Expression::Tuple(first), Expression::Tuple(second)) => {
|
||||
let tuple = Expression::Tuple(TupleExpression {
|
||||
elements: first
|
||||
.elements
|
||||
.into_iter()
|
||||
.zip_eq(second.elements.into_iter())
|
||||
.map(|(if_true, if_false)| {
|
||||
let (ternary, stmts) = self.consume_ternary(TernaryExpression {
|
||||
condition: Box::new(cond_expr.clone()),
|
||||
if_true: Box::new(if_true),
|
||||
if_false: Box::new(if_false),
|
||||
span: input.span,
|
||||
});
|
||||
statements.extend(stmts);
|
||||
ternary
|
||||
})
|
||||
.collect(),
|
||||
span: Default::default(),
|
||||
});
|
||||
(tuple, statements)
|
||||
}
|
||||
// If the `true` and `false` cases are circuits, handle the appropriately.
|
||||
// Note that type checking guarantees that both expressions have the same same type.
|
||||
(Expression::Identifier(first), Expression::Identifier(second)) if self.circuits.contains(&first.name) && self.circuits.contains(&second.name) => {
|
||||
let first_circuit = self.symbol_table.lookup_circuit(first.name).unwrap();
|
||||
let second_circuit = self.symbol_table.lookup_circuit(second.name).unwrap();
|
||||
assert_eq!(first_circuit, second_circuit);
|
||||
|
||||
(place, statements)
|
||||
// For each circuit member, construct a new ternary expression.
|
||||
let members = first_circuit.members.iter().map(|CircuitMember::CircuitVariable(id, _)| {
|
||||
let (expression, stmts) = self.consume_ternary(TernaryExpression {
|
||||
condition: Box::new(cond_expr.clone()),
|
||||
if_true: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
|
||||
inner: Box::new(Expression::Identifier(first)),
|
||||
name: *id,
|
||||
span: Default::default()
|
||||
}))),
|
||||
if_false: Box::new(Expression::Access(AccessExpression::Member(MemberAccess {
|
||||
inner: Box::new(Expression::Identifier(second)),
|
||||
name: *id,
|
||||
span: Default::default()
|
||||
}))),
|
||||
span: Default::default(),
|
||||
});
|
||||
statements.extend(stmts);
|
||||
|
||||
CircuitVariableInitializer { identifier: *id, expression: Some(expression) }
|
||||
}).collect();
|
||||
|
||||
let (expr, stmts) = self.consume_circuit_init(CircuitExpression {
|
||||
name: first_circuit.identifier,
|
||||
members,
|
||||
span: Default::default(),
|
||||
});
|
||||
|
||||
statements.extend(stmts);
|
||||
|
||||
(expr, statements)
|
||||
}
|
||||
(if_true_expr, if_false_expr) => {
|
||||
// Construct and accumulate a unique assignment statement storing the result of the ternary expression.
|
||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(cond_expr),
|
||||
if_true: Box::new(if_true_expr),
|
||||
if_false: Box::new(if_false_expr),
|
||||
span: input.span,
|
||||
}));
|
||||
statements.push(statement);
|
||||
|
||||
(place, statements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes a tuple expression, accumulating any statements that are generated
|
||||
|
@ -38,10 +38,13 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
// Note that this order is necessary to ensure that the right-hand-side uses the correct name when consuming a complex assignment.
|
||||
// TODO: Can lhs have complex expressions?
|
||||
self.is_lhs = true;
|
||||
let place = self.consume_expression(assign.place).0;
|
||||
let place = match self.consume_expression(assign.place).0 {
|
||||
Expression::Identifier(identifier) => identifier,
|
||||
_ => panic!("Type checking"),
|
||||
};
|
||||
self.is_lhs = false;
|
||||
|
||||
statements.push(Self::simple_assign_statement(place, value));
|
||||
statements.push(self.simple_assign_statement(place, value));
|
||||
|
||||
statements
|
||||
}
|
||||
@ -124,18 +127,22 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
// Create a new name for the variable written to in the `ConditionalStatement`.
|
||||
let new_name = self.unique_symbol(symbol);
|
||||
|
||||
let (value, stmts) = self.consume_ternary(TernaryExpression {
|
||||
condition: Box::new(condition.clone()),
|
||||
if_true: create_phi_argument(&if_table, **symbol),
|
||||
if_false: create_phi_argument(&else_table, **symbol),
|
||||
span: Default::default(),
|
||||
});
|
||||
|
||||
statements.extend(stmts);
|
||||
|
||||
// Create a new `AssignStatement` for the phi function.
|
||||
let assignment = Self::simple_assign_statement(
|
||||
Expression::Identifier(Identifier {
|
||||
let assignment = self.simple_assign_statement(
|
||||
Identifier {
|
||||
name: new_name,
|
||||
span: Default::default(),
|
||||
}),
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(condition.clone()),
|
||||
if_true: create_phi_argument(&if_table, **symbol),
|
||||
if_false: create_phi_argument(&else_table, **symbol),
|
||||
span: Default::default(),
|
||||
}),
|
||||
},
|
||||
value,
|
||||
);
|
||||
|
||||
// Update the `RenameTable` with the new name of the variable.
|
||||
@ -219,7 +226,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
};
|
||||
self.is_lhs = false;
|
||||
|
||||
statements.push(Self::simple_assign_statement(Expression::Identifier(identifier), value));
|
||||
statements.push(self.simple_assign_statement(identifier, value));
|
||||
|
||||
statements
|
||||
}
|
||||
@ -296,7 +303,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
// Consume the expression and add it to `early_returns`.
|
||||
let (expression, statements) = self.consume_expression(input.expression);
|
||||
// Note that this is the only place where `self.early_returns` is appended.
|
||||
// Furthermore, `expression` will always be an identifier or tuple expression.
|
||||
// Furthermore, `expression` will always be an identifier, tuple expression, or circuit expression.
|
||||
self.early_returns.push((guard, expression));
|
||||
|
||||
statements
|
||||
|
@ -14,18 +14,21 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::RenameTable;
|
||||
use itertools::Itertools;
|
||||
use std::fmt::Display;
|
||||
use crate::{RenameTable, SymbolTable};
|
||||
|
||||
use leo_ast::{
|
||||
AssignStatement, CircuitExpression, CircuitVariableInitializer, Expression, Identifier, Statement,
|
||||
TernaryExpression, TupleExpression,
|
||||
AssignStatement, Expression, ExpressionConsumer, Identifier,
|
||||
Statement, TernaryExpression,
|
||||
};
|
||||
use leo_errors::emitter::Handler;
|
||||
use leo_span::Symbol;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use std::fmt::Display;
|
||||
|
||||
pub struct StaticSingleAssigner<'a> {
|
||||
/// The symbol table associated with the program.
|
||||
pub(crate) symbol_table: &'a SymbolTable,
|
||||
/// The `RenameTable` for the current basic block in the AST
|
||||
pub(crate) rename_table: RenameTable,
|
||||
/// An error handler used for any errors found during unrolling.
|
||||
@ -34,6 +37,8 @@ pub struct StaticSingleAssigner<'a> {
|
||||
pub(crate) counter: usize,
|
||||
/// A flag to determine whether or not the traversal is on the left-hand side of a definition or an assignment.
|
||||
pub(crate) is_lhs: bool,
|
||||
/// The set of variables that are circuits.
|
||||
pub(crate) circuits: IndexSet<Symbol>,
|
||||
/// A stack of condition `Expression`s visited up to the current point in the AST.
|
||||
pub(crate) condition_stack: Vec<Expression>,
|
||||
/// A list containing tuples of guards and expressions associated with early `ReturnStatement`s.
|
||||
@ -45,12 +50,14 @@ pub struct StaticSingleAssigner<'a> {
|
||||
}
|
||||
|
||||
impl<'a> StaticSingleAssigner<'a> {
|
||||
pub(crate) fn new(handler: &'a Handler) -> Self {
|
||||
pub(crate) fn new(handler: &'a Handler, symbol_table: &'a SymbolTable) -> Self {
|
||||
Self {
|
||||
symbol_table,
|
||||
rename_table: RenameTable::new(None),
|
||||
_handler: handler,
|
||||
counter: 0,
|
||||
is_lhs: false,
|
||||
circuits: IndexSet::new(),
|
||||
condition_stack: Vec::new(),
|
||||
early_returns: Vec::new(),
|
||||
early_finalizes: Vec::new(),
|
||||
@ -64,9 +71,14 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
}
|
||||
|
||||
/// Constructs the assignment statement `place = expr;`.
|
||||
pub(crate) fn simple_assign_statement(place: Expression, value: Expression) -> Statement {
|
||||
/// This function should be the only place where `AssignStatement`s are constructed.
|
||||
pub(crate) fn simple_assign_statement(&mut self, identifier: Identifier, value: Expression) -> Statement {
|
||||
if matches!(value, Expression::Circuit(_)) {
|
||||
self.circuits.insert(identifier.name);
|
||||
}
|
||||
|
||||
Statement::Assign(Box::new(AssignStatement {
|
||||
place,
|
||||
place: Expression::Identifier(identifier),
|
||||
value,
|
||||
span: Default::default(),
|
||||
}))
|
||||
@ -77,14 +89,16 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
pub(crate) fn unique_simple_assign_statement(&mut self, expr: Expression) -> (Expression, Statement) {
|
||||
// Create a new variable for the expression.
|
||||
let name = self.unique_symbol("$var");
|
||||
let place = Expression::Identifier(Identifier {
|
||||
|
||||
let place = Identifier {
|
||||
name,
|
||||
span: Default::default(),
|
||||
});
|
||||
};
|
||||
|
||||
// Update the rename table.
|
||||
self.rename_table.update(name, name);
|
||||
|
||||
(place.clone(), Self::simple_assign_statement(place, expr))
|
||||
(Expression::Identifier(place), self.simple_assign_statement(place, expr))
|
||||
}
|
||||
|
||||
/// Clears the state associated with `ReturnStatements`, returning the ones that were previously produced.
|
||||
@ -120,24 +134,24 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
let (_, last_expression) = guards.pop().unwrap();
|
||||
|
||||
// Produce a chain of ternary expressions and assignments for the guards.
|
||||
let mut stmts = Vec::with_capacity(guards.len());
|
||||
let mut statements = Vec::with_capacity(guards.len());
|
||||
|
||||
// Helper to construct and store ternary assignments. e.g `$ret$0 = $var$0 ? $var$1 : $var$2`
|
||||
let mut construct_ternary_assignment = |guard: Expression, if_true: Expression, if_false: Expression| {
|
||||
let place = Expression::Identifier(Identifier {
|
||||
let place = Identifier {
|
||||
name: self.unique_symbol(prefix),
|
||||
span: Default::default(),
|
||||
};
|
||||
let (value, stmts) = self.consume_ternary(TernaryExpression {
|
||||
condition: Box::new(guard),
|
||||
if_true: Box::new(if_true),
|
||||
if_false: Box::new(if_false),
|
||||
span: Default::default(),
|
||||
});
|
||||
stmts.push(Self::simple_assign_statement(
|
||||
place.clone(),
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(guard),
|
||||
if_true: Box::new(if_true),
|
||||
if_false: Box::new(if_false),
|
||||
span: Default::default(),
|
||||
}),
|
||||
));
|
||||
place
|
||||
statements.extend(stmts);
|
||||
|
||||
statements.push(self.simple_assign_statement(place, value));
|
||||
Expression::Identifier(place)
|
||||
};
|
||||
|
||||
let expression = guards
|
||||
@ -146,58 +160,9 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
.fold(last_expression, |acc, (guard, expr)| match guard {
|
||||
None => unreachable!("All expression except for the last one must have a guard."),
|
||||
// Note that type checking guarantees that all expressions have the same type.
|
||||
Some(guard) => match (expr, acc) {
|
||||
// If the function returns tuples, fold the expressions into a tuple of ternary expressions.
|
||||
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
|
||||
(Expression::Tuple(expr_tuple), Expression::Tuple(acc_tuple)) => {
|
||||
Expression::Tuple(TupleExpression {
|
||||
elements: expr_tuple
|
||||
.elements
|
||||
.into_iter()
|
||||
.zip_eq(acc_tuple.elements.into_iter())
|
||||
.map(|(if_true, if_false)| {
|
||||
construct_ternary_assignment(guard.clone(), if_true, if_false)
|
||||
})
|
||||
.collect(),
|
||||
span: Default::default(),
|
||||
})
|
||||
}
|
||||
// If the expression is a circuit, fold the expressions into a circuit of ternary expressions.
|
||||
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
|
||||
(Expression::Circuit(expr_circuit), Expression::Circuit(acc_circuit)) => {
|
||||
Expression::Circuit(CircuitExpression {
|
||||
name: acc_circuit.name,
|
||||
span: acc_circuit.span,
|
||||
members: expr_circuit
|
||||
.members
|
||||
.into_iter()
|
||||
.zip_eq(acc_circuit.members.into_iter())
|
||||
.map(|(if_true, if_false)| {
|
||||
let expression = construct_ternary_assignment(
|
||||
guard.clone(),
|
||||
match if_true.expression {
|
||||
None => Expression::Identifier(if_true.identifier),
|
||||
Some(expr) => expr,
|
||||
},
|
||||
match if_false.expression {
|
||||
None => Expression::Identifier(if_false.identifier),
|
||||
Some(expr) => expr,
|
||||
},
|
||||
);
|
||||
CircuitVariableInitializer {
|
||||
identifier: if_true.identifier,
|
||||
expression: Some(expression),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
// Otherwise, fold the return expressions into a single ternary expression.
|
||||
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
|
||||
(expr, acc) => construct_ternary_assignment(guard, expr, acc),
|
||||
},
|
||||
Some(guard) => construct_ternary_assignment(guard, expr, acc),
|
||||
});
|
||||
|
||||
(stmts, expression)
|
||||
(statements, expression)
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -35,6 +34,7 @@ outputs:
|
||||
span:
|
||||
lo: 30
|
||||
hi: 49
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 11
|
||||
hi: 49
|
||||
@ -48,7 +48,6 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -66,6 +65,7 @@ outputs:
|
||||
span:
|
||||
lo: 99
|
||||
hi: 118
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 80
|
||||
hi: 118
|
||||
|
@ -25,12 +25,12 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 38
|
||||
hi: 40
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 17
|
||||
hi: 40
|
||||
@ -44,12 +44,12 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 73
|
||||
hi: 75
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 51
|
||||
hi: 75
|
||||
@ -63,12 +63,12 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 105
|
||||
hi: 107
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 83
|
||||
hi: 107
|
||||
|
@ -20,12 +20,12 @@ outputs:
|
||||
hi: 20
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 32
|
||||
hi: 34
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 34
|
||||
@ -42,12 +42,12 @@ outputs:
|
||||
hi: 57
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 70
|
||||
hi: 72
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 36
|
||||
hi: 72
|
||||
|
@ -27,7 +27,6 @@ outputs:
|
||||
hi: 31
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -45,6 +44,7 @@ outputs:
|
||||
span:
|
||||
lo: 44
|
||||
hi: 63
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 63
|
||||
@ -68,7 +68,6 @@ outputs:
|
||||
hi: 94
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -86,6 +85,7 @@ outputs:
|
||||
span:
|
||||
lo: 107
|
||||
hi: 126
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 65
|
||||
hi: 126
|
||||
|
@ -17,12 +17,12 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 107
|
||||
hi: 109
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 85
|
||||
hi: 109
|
||||
|
@ -13,12 +13,12 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements: []
|
||||
span:
|
||||
lo: 21
|
||||
hi: 23
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 23
|
||||
|
@ -27,7 +27,6 @@ outputs:
|
||||
hi: 22
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -45,6 +44,7 @@ outputs:
|
||||
span:
|
||||
lo: 35
|
||||
hi: 54
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 54
|
||||
|
@ -27,7 +27,6 @@ outputs:
|
||||
hi: 22
|
||||
output:
|
||||
Integer: U32
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -45,6 +44,7 @@ outputs:
|
||||
span:
|
||||
lo: 36
|
||||
hi: 55
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 55
|
||||
|
@ -27,7 +27,6 @@ outputs:
|
||||
hi: 29
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -45,6 +44,7 @@ outputs:
|
||||
span:
|
||||
lo: 42
|
||||
hi: 61
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 61
|
||||
@ -68,7 +68,6 @@ outputs:
|
||||
hi: 90
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -86,6 +85,7 @@ outputs:
|
||||
span:
|
||||
lo: 103
|
||||
hi: 122
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 63
|
||||
hi: 122
|
||||
|
@ -13,7 +13,6 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U32
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -31,6 +30,7 @@ outputs:
|
||||
span:
|
||||
lo: 22
|
||||
hi: 41
|
||||
finalize: ~
|
||||
span:
|
||||
lo: 2
|
||||
hi: 41
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370005]: expected -> -- found '{'\n --> test:3:17\n |\n 3 | function main() {\n | ^"
|
||||
- "Error [EPAR0370005]: expected : -- found '='\n --> test:4:11\n |\n 4 | let x = 1u8;\n | ^"
|
||||
|
@ -13,7 +13,6 @@ outputs:
|
||||
input: []
|
||||
output:
|
||||
Integer: U8
|
||||
core_mapping: ~
|
||||
block:
|
||||
statements:
|
||||
- Return:
|
||||
@ -30,5 +29,6 @@ outputs:
|
||||
- U8
|
||||
- "1"
|
||||
op: Add
|
||||
finalize: ~
|
||||
circuits: {}
|
||||
mappings: {}
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370005]: expected -> -- found '{'\n --> test:3:16\n |\n 3 | function foo() {\n | ^"
|
||||
- "Error [EPAR0370005]: expected : -- found 'x'\n --> test:4:13\n |\n 4 | let mut x = 0;\n | ^"
|
||||
|
Loading…
Reference in New Issue
Block a user