mirror of
https://github.com/AleoHQ/leo.git
synced 2024-10-05 19:37:58 +03:00
commit
a2e31558c1
488
Cargo.lock
generated
488
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -147,6 +147,12 @@ version = "1.0"
|
||||
[dependencies.serial_test]
|
||||
version = "3.0.0"
|
||||
|
||||
#[dependencies.snarkos-cli]
|
||||
#version = "2.2.4"
|
||||
|
||||
#[dependencies.snarkos-cli]
|
||||
#version = "2.2.4"
|
||||
|
||||
[dependencies.snarkvm]
|
||||
workspace = true
|
||||
features = [ "circuit", "console" ]
|
||||
|
@ -14,7 +14,7 @@
|
||||
// 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::{Expression, Identifier, Node, NodeID, Type};
|
||||
use crate::{Expression, Identifier, Node, NodeID};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -23,8 +23,8 @@ use std::fmt;
|
||||
/// An access expression to an associated function in a struct, e.g.`Pedersen64::hash()`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct AssociatedFunction {
|
||||
/// The inner struct type.
|
||||
pub ty: Type,
|
||||
/// The inner struct variant.
|
||||
pub variant: Identifier,
|
||||
/// The static struct member function that is being accessed.
|
||||
pub name: Identifier,
|
||||
/// The arguments passed to the function `name`.
|
||||
@ -37,7 +37,7 @@ pub struct AssociatedFunction {
|
||||
|
||||
impl fmt::Display for AssociatedFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}::{}", self.ty, self.name)
|
||||
write!(f, "{}::{}", self.variant, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use leo_span::Symbol;
|
||||
|
||||
/// A function call expression, e.g.`foo(args)` or `Foo::bar(args)`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@ -24,8 +25,8 @@ pub struct CallExpression {
|
||||
pub function: Box<Expression>, // todo: make this identifier?
|
||||
/// Expressions for the arguments passed to the functions parameters.
|
||||
pub arguments: Vec<Expression>,
|
||||
/// The name of the external program call, e.g.`bar` in `bar.leo`.
|
||||
pub external: Option<Box<Expression>>,
|
||||
/// The name of the parent program call, e.g.`bar` in `bar.aleo`.
|
||||
pub program: Option<Symbol>,
|
||||
/// Span of the entire call `function(arguments)`.
|
||||
pub span: Span,
|
||||
/// The ID of the node.
|
||||
@ -34,14 +35,7 @@ pub struct CallExpression {
|
||||
|
||||
impl fmt::Display for CallExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self.external {
|
||||
Some(external) => {
|
||||
write!(f, "{external}.leo/{}(", self.function)?;
|
||||
}
|
||||
None => {
|
||||
write!(f, "{}(", self.function)?;
|
||||
}
|
||||
}
|
||||
write!(f, "{}(", self.function)?;
|
||||
|
||||
for (i, param) in self.arguments.iter().enumerate() {
|
||||
write!(f, "{param}")?;
|
||||
|
@ -14,7 +14,7 @@
|
||||
// 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::{Identifier, Node, NodeID, Type};
|
||||
use crate::{CompositeType, Identifier, Node, NodeID, Type};
|
||||
use leo_span::Span;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -37,7 +37,7 @@ pub struct External {
|
||||
|
||||
impl External {
|
||||
pub fn type_(&self) -> Type {
|
||||
Type::Identifier(self.record)
|
||||
Type::Composite(CompositeType { id: self.record, program: Some(self.program_name.name) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{Identifier, Node, NodeID, Type};
|
||||
|
||||
use leo_span::Span;
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snarkvm::prelude::{Mapping as MappingCore, Network};
|
||||
@ -37,12 +37,12 @@ pub struct Mapping {
|
||||
pub id: NodeID,
|
||||
}
|
||||
|
||||
impl<N: Network> From<&MappingCore<N>> for Mapping {
|
||||
fn from(mapping: &MappingCore<N>) -> Self {
|
||||
impl Mapping {
|
||||
pub fn from_snarkvm<N: Network>(mapping: &MappingCore<N>, program: Symbol) -> Self {
|
||||
Self {
|
||||
identifier: Identifier::from(mapping.name()),
|
||||
key_type: Type::from(mapping.key().plaintext_type()),
|
||||
value_type: Type::from(mapping.value().plaintext_type()),
|
||||
key_type: Type::from_snarkvm(mapping.key().plaintext_type(), program),
|
||||
value_type: Type::from_snarkvm(mapping.value().plaintext_type(), program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ pub trait FunctionConsumer {
|
||||
pub trait StructConsumer {
|
||||
type Output;
|
||||
|
||||
fn consume_struct(&mut self, input: Struct) -> Self::Output;
|
||||
fn consume_struct(&mut self, input: Composite) -> Self::Output;
|
||||
}
|
||||
|
||||
/// A Consumer trait for imported programs in the AST.
|
||||
|
@ -79,7 +79,7 @@ pub trait ExpressionReconstructor {
|
||||
fn reconstruct_associated_function(&mut self, input: AssociatedFunction) -> (Expression, Self::AdditionalOutput) {
|
||||
(
|
||||
Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: input.ty,
|
||||
variant: input.variant,
|
||||
name: input.name,
|
||||
arguments: input.arguments.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
|
||||
span: input.span,
|
||||
@ -142,7 +142,7 @@ pub trait ExpressionReconstructor {
|
||||
Expression::Call(CallExpression {
|
||||
function: Box::new(self.reconstruct_expression(*input.function).0),
|
||||
arguments: input.arguments.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
|
||||
external: input.external,
|
||||
program: input.program,
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}),
|
||||
@ -483,7 +483,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
|
||||
input
|
||||
}
|
||||
|
||||
fn reconstruct_struct(&mut self, input: Struct) -> Struct {
|
||||
fn reconstruct_struct(&mut self, input: Composite) -> Composite {
|
||||
input
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
|
||||
self.visit_program(input)
|
||||
}
|
||||
|
||||
fn visit_struct(&mut self, _input: &'a Struct) {}
|
||||
fn visit_struct(&mut self, _input: &'a Composite) {}
|
||||
|
||||
fn visit_mapping(&mut self, _input: &'a Mapping) {}
|
||||
|
||||
@ -255,5 +255,5 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
|
||||
|
||||
fn visit_function_stub(&mut self, _input: &'a FunctionStub) {}
|
||||
|
||||
fn visit_struct_stub(&mut self, _input: &'a Struct) {}
|
||||
fn visit_struct_stub(&mut self, _input: &'a Composite) {}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::Identifier;
|
||||
|
||||
use core::fmt;
|
||||
use leo_span::Symbol;
|
||||
use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use snarkvm::{console::program::ProgramID, prelude::Network};
|
||||
use std::collections::BTreeMap;
|
||||
@ -99,3 +100,12 @@ impl<N: Network> From<&ProgramID<N>> for ProgramId {
|
||||
Self { name: Identifier::from(program.name()), network: Identifier::from(program.network()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Identifier> for ProgramId {
|
||||
fn from(name: Identifier) -> Self {
|
||||
Self {
|
||||
name,
|
||||
network: Identifier { name: Symbol::intern("aleo"), span: Default::default(), id: Default::default() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! A Leo program scope consists of struct, function, and mapping definitions.
|
||||
|
||||
use crate::{ConstDeclaration, Function, Mapping, ProgramId, Struct, Stub};
|
||||
use crate::{Composite, ConstDeclaration, Function, Mapping, ProgramId, Stub};
|
||||
|
||||
use leo_span::{Span, Symbol};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -30,7 +30,7 @@ pub struct ProgramScope {
|
||||
/// A vector of const definitions
|
||||
pub consts: Vec<(Symbol, ConstDeclaration)>,
|
||||
/// A vector of struct definitions.
|
||||
pub structs: Vec<(Symbol, Struct)>,
|
||||
pub structs: Vec<(Symbol, Composite)>,
|
||||
/// A vector of mapping definitions.
|
||||
pub mappings: Vec<(Symbol, Mapping)>,
|
||||
/// A vector of function definitions.
|
||||
|
@ -32,85 +32,44 @@ use snarkvm::{
|
||||
},
|
||||
};
|
||||
|
||||
/// A struct type definition, e.g., `struct Foo { my_field: Bar }`.
|
||||
/// A composite type definition, e.g., `struct Foo { my_field: Bar }` and `record Token { owner: address, amount: u64}`.
|
||||
/// In some languages these are called `struct`s.
|
||||
///
|
||||
/// Type identity is decided by the full path including `struct_name`,
|
||||
/// as the record is nominal, not structural.
|
||||
/// The fields are named so `struct Foo(u8, u16)` is not allowed.
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Struct {
|
||||
pub struct Composite {
|
||||
/// The name of the type in the type system in this module.
|
||||
pub identifier: Identifier,
|
||||
/// The fields, constant variables, and functions of this structure.
|
||||
pub members: Vec<Member>,
|
||||
/// The external program the struct is defined in.
|
||||
pub external: Option<Symbol>,
|
||||
/// Was this a `record Foo { ... }`?
|
||||
/// If so, it wasn't a struct.
|
||||
/// If so, it wasn't a composite.
|
||||
pub is_record: bool,
|
||||
/// The entire span of the struct definition.
|
||||
/// The entire span of the composite definition.
|
||||
pub span: Span,
|
||||
/// The ID of the node.
|
||||
pub id: NodeID,
|
||||
}
|
||||
|
||||
impl PartialEq for Struct {
|
||||
impl PartialEq for Composite {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.identifier == other.identifier
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Struct {}
|
||||
impl Eq for Composite {}
|
||||
|
||||
impl Struct {
|
||||
/// Returns the struct name as a Symbol.
|
||||
impl Composite {
|
||||
/// Returns the composite name as a Symbol.
|
||||
pub fn name(&self) -> Symbol {
|
||||
self.identifier.name
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Struct {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
<Self as fmt::Display>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Struct {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(if self.is_record { "record" } else { "struct" })?;
|
||||
writeln!(f, " {} {{ ", self.identifier)?;
|
||||
for field in self.members.iter() {
|
||||
writeln!(f, " {field}")?;
|
||||
}
|
||||
write!(f, " }}")
|
||||
}
|
||||
}
|
||||
|
||||
crate::simple_node_impl!(Struct);
|
||||
|
||||
impl<N: Network> From<&StructType<N>> for Struct {
|
||||
fn from(input: &StructType<N>) -> Self {
|
||||
Self {
|
||||
identifier: Identifier::from(input.name()),
|
||||
members: input
|
||||
.members()
|
||||
.iter()
|
||||
.map(|(id, type_)| Member {
|
||||
mode: Mode::None,
|
||||
identifier: Identifier::from(id),
|
||||
type_: Type::from(type_),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})
|
||||
.collect(),
|
||||
is_record: false,
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network> From<&RecordType<N>> for Struct {
|
||||
fn from(input: &RecordType<N>) -> Self {
|
||||
pub fn from_external_record<N: Network>(input: &RecordType<N>, external_program: Symbol) -> Self {
|
||||
Self {
|
||||
identifier: Identifier::from(input.name()),
|
||||
members: [
|
||||
@ -128,9 +87,9 @@ impl<N: Network> From<&RecordType<N>> for Struct {
|
||||
mode: if input.owner().is_public() { Mode::Public } else { Mode::Private },
|
||||
identifier: Identifier::from(id),
|
||||
type_: match entry {
|
||||
Public(t) => Type::from(t),
|
||||
Private(t) => Type::from(t),
|
||||
Constant(t) => Type::from(t),
|
||||
Public(t) => Type::from_snarkvm(t, external_program),
|
||||
Private(t) => Type::from_snarkvm(t, external_program),
|
||||
Constant(t) => Type::from_snarkvm(t, external_program),
|
||||
},
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
@ -138,9 +97,50 @@ impl<N: Network> From<&RecordType<N>> for Struct {
|
||||
.collect_vec(),
|
||||
]
|
||||
.concat(),
|
||||
external: Some(external_program),
|
||||
is_record: true,
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_snarkvm<N: Network>(input: &StructType<N>, program: Symbol) -> Self {
|
||||
Self {
|
||||
identifier: Identifier::from(input.name()),
|
||||
members: input
|
||||
.members()
|
||||
.iter()
|
||||
.map(|(id, type_)| Member {
|
||||
mode: Mode::None,
|
||||
identifier: Identifier::from(id),
|
||||
type_: Type::from_snarkvm(type_, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})
|
||||
.collect(),
|
||||
external: Some(program),
|
||||
is_record: false,
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Composite {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
<Self as fmt::Display>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Composite {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(if self.is_record { "record" } else { "struct" })?;
|
||||
writeln!(f, " {} {{ ", self.identifier)?;
|
||||
for field in self.members.iter() {
|
||||
writeln!(f, " {field}")?;
|
||||
}
|
||||
write!(f, " }}")
|
||||
}
|
||||
}
|
||||
|
||||
crate::simple_node_impl!(Composite);
|
||||
|
@ -56,10 +56,11 @@ impl FinalizeStub {
|
||||
|
||||
Self { identifier, input, output, output_type, span, id }
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network, Command: CommandTrait<N>> From<&FinalizeCore<N, Command>> for FinalizeStub {
|
||||
fn from(finalize: &FinalizeCore<N, Command>) -> Self {
|
||||
pub fn from_snarkvm<N: Network, Command: CommandTrait<N>>(
|
||||
finalize: &FinalizeCore<N, Command>,
|
||||
program: Symbol,
|
||||
) -> Self {
|
||||
let mut inputs = Vec::new();
|
||||
|
||||
finalize.inputs().iter().enumerate().for_each(|(index, input)| {
|
||||
@ -68,7 +69,7 @@ impl<N: Network, Command: CommandTrait<N>> From<&FinalizeCore<N, Command>> for F
|
||||
Plaintext(val) => inputs.push(Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::None,
|
||||
type_: Type::from(val),
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})),
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::{
|
||||
finalize_stub::*,
|
||||
Annotation,
|
||||
CompositeType,
|
||||
External,
|
||||
Function,
|
||||
FunctionInput,
|
||||
@ -34,7 +35,7 @@ use crate::{
|
||||
};
|
||||
use leo_span::{sym, Span, Symbol};
|
||||
|
||||
use crate::Type::Identifier as IdentifierType;
|
||||
use crate::Type::Composite;
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snarkvm::{
|
||||
@ -139,33 +140,137 @@ impl FunctionStub {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Function> for FunctionStub {
|
||||
fn from(function: Function) -> Self {
|
||||
/// Converts from snarkvm function type to leo FunctionStub, while also carrying the parent program name.
|
||||
pub fn from_function_core<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
|
||||
function: &FunctionCore<N, Instruction, Command>,
|
||||
program: Symbol,
|
||||
) -> Self {
|
||||
let outputs = function
|
||||
.outputs()
|
||||
.iter()
|
||||
.map(|output| match output.value_type() {
|
||||
ValueType::Constant(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Constant,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Public(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Public,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Private(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Private,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Record(id) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::None,
|
||||
type_: Composite(CompositeType { id: Identifier::from(id), program: Some(program) }),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::ExternalRecord(loc) => {
|
||||
vec![Output::External(External {
|
||||
identifier: Identifier::new(Symbol::intern("dummy"), Default::default()),
|
||||
program_name: ProgramId::from(loc.program_id()).name,
|
||||
record: Identifier::from(loc.resource()),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})]
|
||||
}
|
||||
ValueType::Future(_) => Vec::new(), // Don't include futures in the output signature
|
||||
})
|
||||
.collect_vec()
|
||||
.concat();
|
||||
let output_vec = outputs
|
||||
.iter()
|
||||
.map(|output| match output {
|
||||
Output::Internal(output) => output.type_.clone(),
|
||||
Output::External(output) => {
|
||||
Type::Composite(CompositeType { id: output.record, program: Some(output.program_name.name) })
|
||||
}
|
||||
})
|
||||
.collect_vec();
|
||||
let output_type = match output_vec.len() {
|
||||
0 => Type::Unit,
|
||||
1 => output_vec[0].clone(),
|
||||
_ => Type::Tuple(TupleType::new(output_vec)),
|
||||
};
|
||||
|
||||
Self {
|
||||
annotations: function.annotations,
|
||||
variant: function.variant,
|
||||
identifier: function.identifier,
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
output_type: function.output_type,
|
||||
finalize_stub: function.finalize.map(FinalizeStub::from),
|
||||
span: function.span,
|
||||
id: function.id,
|
||||
annotations: Vec::new(),
|
||||
variant: Variant::Transition,
|
||||
identifier: Identifier::from(function.name()),
|
||||
input: function
|
||||
.inputs()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, input)| {
|
||||
let arg_name = Identifier::new(Symbol::intern(&format!("a{}", index + 1)), Default::default());
|
||||
match input.value_type() {
|
||||
ValueType::Constant(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Constant,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Public(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Public,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Private(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Private,
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Record(id) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::None,
|
||||
type_: Composite(CompositeType { id: Identifier::from(id), program: Some(program) }),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::ExternalRecord(loc) => Input::External(External {
|
||||
identifier: Identifier::new(Symbol::intern("dummy"), Default::default()),
|
||||
program_name: ProgramId::from(loc.program_id()).name,
|
||||
record: Identifier::from(loc.resource()),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Future(_) => panic!("Functions do not contain futures as inputs"),
|
||||
}
|
||||
})
|
||||
.collect_vec(),
|
||||
output: outputs,
|
||||
output_type,
|
||||
finalize_stub: function.finalize_logic().map(|f| FinalizeStub::from_snarkvm(f, program)),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network, Instruction: InstructionTrait<N>> From<&ClosureCore<N, Instruction>> for FunctionStub {
|
||||
fn from(closure: &ClosureCore<N, Instruction>) -> Self {
|
||||
pub fn from_closure<N: Network, Instruction: InstructionTrait<N>>(
|
||||
closure: &ClosureCore<N, Instruction>,
|
||||
program: Symbol,
|
||||
) -> Self {
|
||||
let outputs = closure
|
||||
.outputs()
|
||||
.iter()
|
||||
.map(|output| match output.register_type() {
|
||||
Plaintext(val) => Output::Internal(FunctionOutput {
|
||||
mode: Mode::None,
|
||||
type_: Type::from(val),
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
@ -200,7 +305,7 @@ impl<N: Network, Instruction: InstructionTrait<N>> From<&ClosureCore<N, Instruct
|
||||
Plaintext(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::None,
|
||||
type_: Type::from(val),
|
||||
type_: Type::from_snarkvm(val, program),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
@ -219,117 +324,18 @@ impl<N: Network, Instruction: InstructionTrait<N>> From<&ClosureCore<N, Instruct
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>
|
||||
From<&FunctionCore<N, Instruction, Command>> for FunctionStub
|
||||
{
|
||||
fn from(function: &FunctionCore<N, Instruction, Command>) -> Self {
|
||||
let outputs = function
|
||||
.outputs()
|
||||
.iter()
|
||||
.map(|output| match output.value_type() {
|
||||
ValueType::Constant(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Constant,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Public(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Public,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Private(val) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::Private,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Record(id) => vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::None,
|
||||
type_: IdentifierType(Identifier::from(id)),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::ExternalRecord(loc) => vec![Output::External(External {
|
||||
identifier: Identifier::new(Symbol::intern("dummy"), Default::default()),
|
||||
program_name: ProgramId::from(loc.program_id()).name,
|
||||
record: Identifier::from(loc.resource()),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})],
|
||||
ValueType::Future(_) => Vec::new(), // Don't include futures in the output signature
|
||||
})
|
||||
.collect_vec()
|
||||
.concat();
|
||||
let output_vec = outputs
|
||||
.iter()
|
||||
.map(|output| match output {
|
||||
Output::Internal(output) => output.type_.clone(),
|
||||
Output::External(output) => Type::Identifier(output.record),
|
||||
})
|
||||
.collect_vec();
|
||||
let output_type = match output_vec.len() {
|
||||
0 => Type::Unit,
|
||||
1 => output_vec[0].clone(),
|
||||
_ => Type::Tuple(TupleType::new(output_vec)),
|
||||
};
|
||||
|
||||
impl From<Function> for FunctionStub {
|
||||
fn from(function: Function) -> Self {
|
||||
Self {
|
||||
annotations: Vec::new(),
|
||||
variant: Variant::Transition,
|
||||
identifier: Identifier::from(function.name()),
|
||||
input: function
|
||||
.inputs()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, input)| {
|
||||
let arg_name = Identifier::new(Symbol::intern(&format!("a{}", index + 1)), Default::default());
|
||||
match input.value_type() {
|
||||
ValueType::Constant(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Constant,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Public(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Public,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Private(val) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::Private,
|
||||
type_: Type::from(val),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Record(id) => Input::Internal(FunctionInput {
|
||||
identifier: arg_name,
|
||||
mode: Mode::None,
|
||||
type_: IdentifierType(Identifier::from(id)),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::ExternalRecord(loc) => Input::External(External {
|
||||
identifier: arg_name,
|
||||
program_name: ProgramId::from(loc.program_id()).name,
|
||||
record: Identifier::from(loc.resource()),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
ValueType::Future(_) => panic!("Functions do not contain futures as inputs"),
|
||||
}
|
||||
})
|
||||
.collect_vec(),
|
||||
output: outputs,
|
||||
output_type,
|
||||
finalize_stub: function.finalize_logic().map(FinalizeStub::from),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
annotations: function.annotations,
|
||||
variant: function.variant,
|
||||
identifier: function.identifier,
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
output_type: function.output_type,
|
||||
finalize_stub: function.finalize.map(FinalizeStub::from),
|
||||
span: function.span,
|
||||
id: function.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub use finalize_stub::*;
|
||||
pub mod function_stub;
|
||||
pub use function_stub::*;
|
||||
|
||||
use crate::{ConstDeclaration, Identifier, Mapping, NodeID, ProgramId, Struct};
|
||||
use crate::{Composite, ConstDeclaration, Identifier, Mapping, NodeID, ProgramId};
|
||||
use leo_span::{Span, Symbol};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -36,7 +36,7 @@ pub struct Stub {
|
||||
/// A vector of const definitions.
|
||||
pub consts: Vec<(Symbol, ConstDeclaration)>,
|
||||
/// A vector of struct definitions.
|
||||
pub structs: Vec<(Symbol, Struct)>,
|
||||
pub structs: Vec<(Symbol, Composite)>,
|
||||
/// A vector of mapping definitions.
|
||||
pub mappings: Vec<(Symbol, Mapping)>,
|
||||
/// A vector of function stub definitions.
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::{NonNegativeNumber, Type};
|
||||
use snarkvm::console::program::ArrayType as ConsoleArrayType;
|
||||
|
||||
use leo_span::Symbol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snarkvm::prelude::Network;
|
||||
use std::fmt;
|
||||
@ -51,12 +52,10 @@ impl ArrayType {
|
||||
type_ => type_,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network> From<&ConsoleArrayType<N>> for ArrayType {
|
||||
fn from(array_type: &ConsoleArrayType<N>) -> Self {
|
||||
pub fn from_snarkvm<N: Network>(array_type: &ConsoleArrayType<N>, program: Symbol) -> Self {
|
||||
Self {
|
||||
element_type: Box::new(Type::from(array_type.next_element_type())),
|
||||
element_type: Box::new(Type::from_snarkvm(array_type.next_element_type(), program)),
|
||||
length: NonNegativeNumber::from(array_type.length().to_string().replace("u32", "")),
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ pub use integer_type::*;
|
||||
pub mod mapping;
|
||||
pub use mapping::*;
|
||||
|
||||
pub mod struct_type;
|
||||
pub use struct_type::*;
|
||||
|
||||
pub mod tuple;
|
||||
pub use tuple::*;
|
||||
|
||||
|
36
compiler/ast/src/types/struct_type.rs
Normal file
36
compiler/ast/src/types/struct_type.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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::Identifier;
|
||||
|
||||
use leo_span::Symbol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
/// A composite type of a identifier and external program name.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Copy)]
|
||||
pub struct CompositeType {
|
||||
// The identifier of the composite definition.
|
||||
pub id: Identifier,
|
||||
// The external program that this composite is defined in.
|
||||
pub program: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompositeType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{id}", id = self.id)
|
||||
}
|
||||
}
|
@ -14,9 +14,10 @@
|
||||
// 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::{common, ArrayType, Identifier, IntegerType, MappingType, TupleType};
|
||||
use crate::{common, ArrayType, CompositeType, Identifier, IntegerType, MappingType, TupleType};
|
||||
|
||||
use itertools::Itertools;
|
||||
use leo_span::Symbol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snarkvm::prelude::{
|
||||
Network,
|
||||
@ -34,6 +35,8 @@ pub enum Type {
|
||||
Array(ArrayType),
|
||||
/// The `bool` type.
|
||||
Boolean,
|
||||
/// The `struct` type.
|
||||
Composite(CompositeType),
|
||||
/// The `field` type.
|
||||
Field,
|
||||
/// The `group` type.
|
||||
@ -88,34 +91,14 @@ impl Type {
|
||||
.iter()
|
||||
.zip_eq(right.elements().iter())
|
||||
.all(|(left_type, right_type)| left_type.eq_flat(right_type)),
|
||||
(Type::Composite(left), Type::Composite(right)) => {
|
||||
left.id.name == right.id.name && left.program == right.program
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Type::Address => write!(f, "address"),
|
||||
Type::Array(ref array_type) => write!(f, "{array_type}"),
|
||||
Type::Boolean => write!(f, "boolean"),
|
||||
Type::Field => write!(f, "field"),
|
||||
Type::Group => write!(f, "group"),
|
||||
Type::Identifier(ref variable) => write!(f, "{variable}"),
|
||||
Type::Integer(ref integer_type) => write!(f, "{integer_type}"),
|
||||
Type::Mapping(ref mapping_type) => write!(f, "{mapping_type}"),
|
||||
Type::Scalar => write!(f, "scalar"),
|
||||
Type::Signature => write!(f, "signature"),
|
||||
Type::String => write!(f, "string"),
|
||||
Type::Tuple(ref tuple) => write!(f, "{tuple}"),
|
||||
Type::Unit => write!(f, "()"),
|
||||
Type::Err => write!(f, "error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network> From<&PlaintextType<N>> for Type {
|
||||
fn from(t: &PlaintextType<N>) -> Self {
|
||||
pub fn from_snarkvm<N: Network>(t: &PlaintextType<N>, program: Symbol) -> Self {
|
||||
match t {
|
||||
Literal(lit) => match lit {
|
||||
snarkvm::prelude::LiteralType::Address => Type::Address,
|
||||
@ -136,8 +119,30 @@ impl<N: Network> From<&PlaintextType<N>> for Type {
|
||||
snarkvm::prelude::LiteralType::Signature => Type::Signature,
|
||||
snarkvm::prelude::LiteralType::String => Type::String,
|
||||
},
|
||||
Struct(s) => Type::Identifier(common::Identifier::from(s)),
|
||||
Array(array) => Type::Array(ArrayType::from(array)),
|
||||
Struct(s) => Type::Composite(CompositeType { id: common::Identifier::from(s), program: Some(program) }),
|
||||
Array(array) => Type::Array(ArrayType::from_snarkvm(array, program)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Type::Address => write!(f, "address"),
|
||||
Type::Array(ref array_type) => write!(f, "{array_type}"),
|
||||
Type::Boolean => write!(f, "boolean"),
|
||||
Type::Field => write!(f, "field"),
|
||||
Type::Group => write!(f, "group"),
|
||||
Type::Identifier(ref variable) => write!(f, "{variable}"),
|
||||
Type::Integer(ref integer_type) => write!(f, "{integer_type}"),
|
||||
Type::Mapping(ref mapping_type) => write!(f, "{mapping_type}"),
|
||||
Type::Scalar => write!(f, "scalar"),
|
||||
Type::Signature => write!(f, "signature"),
|
||||
Type::String => write!(f, "string"),
|
||||
Type::Composite(ref struct_type) => write!(f, "{}", struct_type.id.name),
|
||||
Type::Tuple(ref tuple) => write!(f, "{tuple}"),
|
||||
Type::Unit => write!(f, "()"),
|
||||
Type::Err => write!(f, "error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +72,9 @@ impl<'a> ExpressionVisitor<'a> for CheckUniqueNodeIds<'a> {
|
||||
self.visit_identifier(name, &Default::default());
|
||||
self.check(*id);
|
||||
}
|
||||
AccessExpression::AssociatedFunction(AssociatedFunction { ty, name, arguments, id, .. }) => {
|
||||
self.check_ty(ty);
|
||||
AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
variant: _variant, name, arguments, id, ..
|
||||
}) => {
|
||||
self.visit_identifier(name, &Default::default());
|
||||
for argument in arguments {
|
||||
self.visit_expression(argument, &Default::default());
|
||||
@ -100,14 +101,11 @@ impl<'a> ExpressionVisitor<'a> for CheckUniqueNodeIds<'a> {
|
||||
}
|
||||
|
||||
fn visit_call(&mut self, input: &'a CallExpression, _: &Self::AdditionalInput) -> Self::Output {
|
||||
let CallExpression { function, arguments, external, id, .. } = input;
|
||||
let CallExpression { function, arguments, program: _external, id, .. } = input;
|
||||
self.visit_expression(function, &Default::default());
|
||||
for argument in arguments {
|
||||
self.visit_expression(argument, &Default::default());
|
||||
}
|
||||
if let Some(external) = external {
|
||||
self.visit_expression(external, &Default::default());
|
||||
}
|
||||
self.check(*id);
|
||||
}
|
||||
|
||||
@ -252,8 +250,8 @@ impl<'a> StatementVisitor<'a> for CheckUniqueNodeIds<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ProgramVisitor<'a> for CheckUniqueNodeIds<'a> {
|
||||
fn visit_struct(&mut self, input: &'a Struct) {
|
||||
let Struct { identifier, members, id, .. } = input;
|
||||
fn visit_struct(&mut self, input: &'a Composite) {
|
||||
let Composite { identifier, members, id, .. } = input;
|
||||
self.visit_identifier(identifier, &Default::default());
|
||||
for Member { identifier, type_, id, .. } in members {
|
||||
self.visit_identifier(identifier, &Default::default());
|
||||
|
@ -39,6 +39,8 @@ pub(crate) struct ParserContext<'a> {
|
||||
pub(crate) prev_token: SpannedToken,
|
||||
/// true if parsing an expression for if and loop statements -- means struct inits are not legal
|
||||
pub(crate) disallow_struct_construction: bool,
|
||||
/// The name of the program being parsed.
|
||||
pub(crate) program_name: Option<Symbol>,
|
||||
}
|
||||
|
||||
/// Dummy span used to appease borrow checker.
|
||||
@ -60,6 +62,7 @@ impl<'a> ParserContext<'a> {
|
||||
prev_token: token.clone(),
|
||||
token,
|
||||
tokens,
|
||||
program_name: None,
|
||||
};
|
||||
p.bump();
|
||||
p
|
||||
|
@ -17,7 +17,7 @@
|
||||
use super::*;
|
||||
use leo_errors::{ParserError, Result};
|
||||
|
||||
use leo_span::sym;
|
||||
use leo_span::{sym, Symbol};
|
||||
use snarkvm::console::{account::Address, network::Testnet3};
|
||||
|
||||
const INT_TYPES: &[Token] = &[
|
||||
@ -347,7 +347,7 @@ impl ParserContext<'_> {
|
||||
(args.len(), CoreFunction::from_symbols(sym::signature, method.name))
|
||||
{
|
||||
Ok(Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: Type::Identifier(Identifier::new(sym::signature, self.node_builder.next_id())),
|
||||
variant: Identifier::new(sym::signature, self.node_builder.next_id()),
|
||||
name: method,
|
||||
arguments: {
|
||||
let mut arguments = vec![receiver];
|
||||
@ -367,7 +367,7 @@ impl ParserContext<'_> {
|
||||
| (1, Some(CoreFunction::MappingContains)) => {
|
||||
// Found an instance of `<mapping>.get`, `<mapping>.get_or_use`, `<mapping>.set`, `<mapping>.remove`, or `<mapping>.contains`.
|
||||
Ok(Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: Type::Identifier(Identifier::new(sym::Mapping, self.node_builder.next_id())),
|
||||
variant: Identifier::new(sym::Mapping, self.node_builder.next_id()),
|
||||
name: method,
|
||||
arguments: {
|
||||
let mut arguments = vec![receiver];
|
||||
@ -391,8 +391,8 @@ impl ParserContext<'_> {
|
||||
/// static access expression.
|
||||
fn parse_associated_access_expression(&mut self, module_name: Expression) -> Result<Expression> {
|
||||
// Parse struct name expression into struct type.
|
||||
let type_ = if let Expression::Identifier(ident) = module_name {
|
||||
Type::Identifier(ident)
|
||||
let variant = if let Expression::Identifier(ident) = module_name {
|
||||
ident
|
||||
} else {
|
||||
return Err(ParserError::invalid_associated_access(&module_name, module_name.span()).into());
|
||||
};
|
||||
@ -408,7 +408,7 @@ impl ParserContext<'_> {
|
||||
// Return the struct function.
|
||||
AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
span: module_name.span() + end,
|
||||
ty: type_,
|
||||
variant,
|
||||
name: member_name,
|
||||
arguments: args,
|
||||
id: self.node_builder.next_id(),
|
||||
@ -417,7 +417,7 @@ impl ParserContext<'_> {
|
||||
// Return the struct constant.
|
||||
AccessExpression::AssociatedConstant(AssociatedConstant {
|
||||
span: module_name.span() + member_name.span(),
|
||||
ty: type_,
|
||||
ty: Type::Identifier(variant),
|
||||
name: member_name,
|
||||
id: self.node_builder.next_id(),
|
||||
})
|
||||
@ -429,7 +429,7 @@ impl ParserContext<'_> {
|
||||
self.parse_paren_comma_list(|p| p.parse_expression().map(Some))
|
||||
}
|
||||
|
||||
// Parses an externa function call `credits.aleo/transfer()` or `board.leo/make_move()`
|
||||
// Parses an external function call `credits.aleo/transfer()` or `board.leo/make_move()`
|
||||
fn parse_external_call(&mut self, expr: Expression) -> Result<Expression> {
|
||||
// Eat an external function call.
|
||||
self.eat(&Token::Div); // todo: Make `/` a more general token.
|
||||
@ -437,12 +437,24 @@ impl ParserContext<'_> {
|
||||
// Parse function name.
|
||||
let name = self.expect_identifier()?;
|
||||
|
||||
// Parsing a '{' means that user is trying to illegally define an external record.
|
||||
if self.token.token == Token::LeftCurly {
|
||||
return Err(ParserError::cannot_define_external_record(expr.span() + name.span()).into());
|
||||
}
|
||||
|
||||
// Parse the function call.
|
||||
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
||||
|
||||
// Parse the parent program identifier.
|
||||
let program: Symbol = match expr {
|
||||
Expression::Identifier(identifier) => identifier.name,
|
||||
_ => unreachable!("Function called must be preceded by a program identifier."),
|
||||
};
|
||||
|
||||
Ok(Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(Expression::Identifier(name)),
|
||||
external: Some(Box::new(expr)),
|
||||
program: Some(program),
|
||||
arguments,
|
||||
id: self.node_builder.next_id(),
|
||||
}))
|
||||
@ -513,7 +525,7 @@ impl ParserContext<'_> {
|
||||
expr = Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(expr),
|
||||
external: None,
|
||||
program: self.program_name,
|
||||
arguments,
|
||||
id: self.node_builder.next_id(),
|
||||
});
|
||||
|
@ -95,6 +95,9 @@ impl ParserContext<'_> {
|
||||
// Parse the program name.
|
||||
let name = self.expect_identifier()?;
|
||||
|
||||
// Set the program name in the context.
|
||||
self.program_name = Some(name.name);
|
||||
|
||||
// Parse the program network.
|
||||
self.expect(&Token::Dot)?;
|
||||
|
||||
@ -111,7 +114,7 @@ impl ParserContext<'_> {
|
||||
// Parse the body of the program scope.
|
||||
let mut consts: Vec<(Symbol, ConstDeclaration)> = Vec::new();
|
||||
let mut functions: Vec<(Symbol, Function)> = Vec::new();
|
||||
let mut structs: Vec<(Symbol, Struct)> = Vec::new();
|
||||
let mut structs: Vec<(Symbol, Composite)> = Vec::new();
|
||||
let mut mappings: Vec<(Symbol, Mapping)> = Vec::new();
|
||||
|
||||
while self.has_next() {
|
||||
@ -203,7 +206,7 @@ impl ParserContext<'_> {
|
||||
}
|
||||
|
||||
/// Parses a struct or record definition, e.g., `struct Foo { ... }` or `record Foo { ... }`.
|
||||
pub(super) fn parse_struct(&mut self) -> Result<(Symbol, Struct)> {
|
||||
pub(super) fn parse_struct(&mut self) -> Result<(Symbol, Composite)> {
|
||||
let is_record = matches!(&self.token.token, Token::Record);
|
||||
let start = self.expect_any(&[Token::Struct, Token::Record])?;
|
||||
|
||||
@ -218,9 +221,10 @@ impl ParserContext<'_> {
|
||||
self.expect(&Token::LeftCurly)?;
|
||||
let (members, end) = self.parse_struct_members()?;
|
||||
|
||||
Ok((struct_name.name, Struct {
|
||||
Ok((struct_name.name, Composite {
|
||||
identifier: struct_name,
|
||||
members,
|
||||
external: self.program_name,
|
||||
is_record,
|
||||
span: start + end,
|
||||
id: self.node_builder.next_id(),
|
||||
|
@ -95,13 +95,16 @@ impl ParserContext<'_> {
|
||||
// Parse the record name
|
||||
if let Some(record_name) = self.eat_identifier() {
|
||||
// Return the external type
|
||||
return Ok((Type::Identifier(record_name), ident.span + record_name.span));
|
||||
return Ok((
|
||||
Type::Composite(CompositeType { id: record_name, program: Some(ident.name) }),
|
||||
ident.span + record_name.span,
|
||||
));
|
||||
} else {
|
||||
return Err(ParserError::invalid_external_type(self.token.span).into());
|
||||
}
|
||||
}
|
||||
|
||||
Ok((Type::Identifier(ident), ident.span))
|
||||
Ok((Type::Composite(CompositeType { id: ident, program: self.program_name }), ident.span))
|
||||
} else if self.token.token == Token::LeftSquare {
|
||||
// Parse the left bracket.
|
||||
self.expect(&Token::LeftSquare)?;
|
||||
|
@ -51,8 +51,8 @@ version = "0.2.18"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = [ "derive", "rc" ]
|
||||
features = ["derive", "rc"]
|
||||
|
||||
[dependencies.serde_json]
|
||||
version = "1.0"
|
||||
features = [ "preserve_order" ]
|
||||
features = ["preserve_order"]
|
||||
|
@ -349,53 +349,23 @@ impl<'a> CodeGenerator<'a> {
|
||||
};
|
||||
|
||||
// Construct the instruction.
|
||||
let (destination, instruction) = match &input.ty {
|
||||
Type::Identifier(Identifier { name: sym::BHP256, .. }) => {
|
||||
construct_simple_function_call(&input.name, "bhp256", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::BHP512, .. }) => {
|
||||
construct_simple_function_call(&input.name, "bhp512", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::BHP768, .. }) => {
|
||||
construct_simple_function_call(&input.name, "bhp768", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::BHP1024, .. }) => {
|
||||
construct_simple_function_call(&input.name, "bhp1024", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Keccak256, .. }) => {
|
||||
construct_simple_function_call(&input.name, "keccak256", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Keccak384, .. }) => {
|
||||
construct_simple_function_call(&input.name, "keccak384", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Keccak512, .. }) => {
|
||||
construct_simple_function_call(&input.name, "keccak512", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Pedersen64, .. }) => {
|
||||
construct_simple_function_call(&input.name, "ped64", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Pedersen128, .. }) => {
|
||||
construct_simple_function_call(&input.name, "ped128", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Poseidon2, .. }) => {
|
||||
construct_simple_function_call(&input.name, "psd2", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Poseidon4, .. }) => {
|
||||
construct_simple_function_call(&input.name, "psd4", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Poseidon8, .. }) => {
|
||||
construct_simple_function_call(&input.name, "psd8", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::SHA3_256, .. }) => {
|
||||
construct_simple_function_call(&input.name, "sha3_256", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::SHA3_384, .. }) => {
|
||||
construct_simple_function_call(&input.name, "sha3_384", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::SHA3_512, .. }) => {
|
||||
construct_simple_function_call(&input.name, "sha3_512", arguments)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::Mapping, .. }) => match input.name.name {
|
||||
let (destination, instruction) = match input.variant.name {
|
||||
sym::BHP256 => construct_simple_function_call(&input.name, "bhp256", arguments),
|
||||
sym::BHP512 => construct_simple_function_call(&input.name, "bhp512", arguments),
|
||||
sym::BHP768 => construct_simple_function_call(&input.name, "bhp768", arguments),
|
||||
sym::BHP1024 => construct_simple_function_call(&input.name, "bhp1024", arguments),
|
||||
sym::Keccak256 => construct_simple_function_call(&input.name, "keccak256", arguments),
|
||||
sym::Keccak384 => construct_simple_function_call(&input.name, "keccak384", arguments),
|
||||
sym::Keccak512 => construct_simple_function_call(&input.name, "keccak512", arguments),
|
||||
sym::Pedersen64 => construct_simple_function_call(&input.name, "ped64", arguments),
|
||||
sym::Pedersen128 => construct_simple_function_call(&input.name, "ped128", arguments),
|
||||
sym::Poseidon2 => construct_simple_function_call(&input.name, "psd2", arguments),
|
||||
sym::Poseidon4 => construct_simple_function_call(&input.name, "psd4", arguments),
|
||||
sym::Poseidon8 => construct_simple_function_call(&input.name, "psd8", arguments),
|
||||
sym::SHA3_256 => construct_simple_function_call(&input.name, "sha3_256", arguments),
|
||||
sym::SHA3_384 => construct_simple_function_call(&input.name, "sha3_384", arguments),
|
||||
sym::SHA3_512 => construct_simple_function_call(&input.name, "sha3_512", arguments),
|
||||
sym::Mapping => match input.name.name {
|
||||
sym::get => {
|
||||
let mut instruction = " get".to_string();
|
||||
let destination_register = get_destination_register();
|
||||
@ -439,7 +409,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
}
|
||||
_ => unreachable!("The only variants of Mapping are get, get_or, and set"),
|
||||
},
|
||||
Type::Identifier(Identifier { name: sym::group, .. }) => {
|
||||
sym::group => {
|
||||
match input.name {
|
||||
Identifier { name: sym::to_x_coordinate, .. } => {
|
||||
let mut instruction = " cast".to_string();
|
||||
@ -460,7 +430,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
_ => unreachable!("The only associated methods of group are to_x_coordinate and to_y_coordinate"),
|
||||
}
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::ChaCha, .. }) => {
|
||||
sym::ChaCha => {
|
||||
// Get the destination register.
|
||||
let destination_register = get_destination_register();
|
||||
// Construct the instruction template.
|
||||
@ -487,7 +457,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
.expect("failed to write to string");
|
||||
(destination_register, instruction)
|
||||
}
|
||||
Type::Identifier(Identifier { name: sym::signature, .. }) => {
|
||||
sym::signature => {
|
||||
let mut instruction = " sign.verify".to_string();
|
||||
let destination_register = get_destination_register();
|
||||
// Write the arguments and the destination register.
|
||||
@ -520,47 +490,32 @@ impl<'a> CodeGenerator<'a> {
|
||||
}
|
||||
|
||||
fn visit_call(&mut self, input: &'a CallExpression) -> (String, String) {
|
||||
let (mut call_instruction, has_finalize) = match &input.external {
|
||||
Some(external) => {
|
||||
// If the function is an external call, then check whether or not it has an associated finalize block.
|
||||
// Extract the program name from the external call.
|
||||
let program_name = match **external {
|
||||
Expression::Identifier(identifier) => identifier.name,
|
||||
_ => unreachable!("Parsing guarantees that a program name is always an identifier."),
|
||||
};
|
||||
let stub_scope: ProgramScope;
|
||||
// Lookup the imported program scope.
|
||||
// TODO: Needs refactor. All imports are stubs now.
|
||||
let imported_program_scope = match self
|
||||
.program
|
||||
.imports
|
||||
.get(&program_name)
|
||||
.and_then(|(program, _)| program.program_scopes.get(&program_name))
|
||||
{
|
||||
Some(program) => program,
|
||||
None => {
|
||||
if let Some(stub_program) = self.program.stubs.get(&program_name) {
|
||||
stub_scope = ProgramScope::from(stub_program.clone());
|
||||
&stub_scope
|
||||
} else {
|
||||
unreachable!("Type checking guarantees that imported and stub programs are well defined.")
|
||||
}
|
||||
}
|
||||
};
|
||||
// Check if the external function has a finalize block.
|
||||
// Need to determine the program the function originated from as well as if the function has a finalize block.
|
||||
let (mut call_instruction, has_finalize);
|
||||
|
||||
// Check if function is external.
|
||||
let main_program = input.program.unwrap();
|
||||
if main_program != self.program_id.unwrap().name.name {
|
||||
// All external functions must be defined as stubs.
|
||||
if let Some(stub_program) = self.program.stubs.get(&main_program) {
|
||||
let stub_scope = ProgramScope::from(stub_program.clone());
|
||||
let function_name = match *input.function {
|
||||
Expression::Identifier(identifier) => identifier.name,
|
||||
_ => unreachable!("Parsing guarantees that a function name is always an identifier."),
|
||||
};
|
||||
let has_finalize = match imported_program_scope.functions.iter().find(|(sym, _)| *sym == function_name)
|
||||
{
|
||||
|
||||
// Check if the external function has a finalize block.
|
||||
has_finalize = match stub_scope.functions.iter().find(|(sym, _)| *sym == function_name) {
|
||||
Some((_, function)) => function.finalize.is_some(),
|
||||
None => unreachable!("Type checking guarantees that imported functions are well defined."),
|
||||
};
|
||||
(format!(" call {external}.aleo/{}", input.function), has_finalize)
|
||||
call_instruction = format!(" call {}.aleo/{}", main_program, input.function);
|
||||
} else {
|
||||
unreachable!("Type checking guarantees that imported and stub programs are well defined.")
|
||||
}
|
||||
None => (format!(" call {}", input.function), false),
|
||||
};
|
||||
} else {
|
||||
(call_instruction, has_finalize) = (format!(" call {}", input.function), false);
|
||||
}
|
||||
let mut instructions = String::new();
|
||||
|
||||
for argument in input.arguments.iter() {
|
||||
@ -578,7 +533,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Initialize storage for the destination registers.
|
||||
let mut destinations = Vec::new();
|
||||
|
||||
let return_type = &self.symbol_table.lookup_fn_symbol(function_name).unwrap().output_type;
|
||||
let return_type = &self.symbol_table.lookup_fn_symbol(main_program, function_name).unwrap().output_type;
|
||||
match return_type {
|
||||
Type::Unit => {} // Do nothing
|
||||
Type::Tuple(tuple) => match tuple.length() {
|
||||
@ -607,14 +562,8 @@ impl<'a> CodeGenerator<'a> {
|
||||
let future_register = format!("r{}", self.next_register);
|
||||
self.next_register += 1;
|
||||
|
||||
// Construct the future type.
|
||||
let program_id = match input.external.as_deref() {
|
||||
Some(Expression::Identifier(identifier)) => identifier,
|
||||
_ => unreachable!("If `has_finalize` is true, then the external call must be an identifier."),
|
||||
};
|
||||
|
||||
// Add the futures register to the list of futures.
|
||||
self.futures.push((future_register.clone(), format!("{program_id}.aleo/{function_name}")));
|
||||
self.futures.push((future_register.clone(), format!("{}.aleo/{function_name}", main_program)));
|
||||
|
||||
// Add the future register to the list of destinations.
|
||||
destinations.push(future_register);
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::CodeGenerator;
|
||||
|
||||
use leo_ast::{functions, Function, Mapping, Mode, Program, ProgramScope, Struct, Type, Variant};
|
||||
use leo_ast::{functions, Composite, Function, Mapping, Mode, Program, ProgramScope, Type, Variant};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
@ -51,7 +51,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
let order = self.struct_graph.post_order().unwrap();
|
||||
|
||||
// Create a mapping of symbols to references of structs so can perform constant-time lookups.
|
||||
let structs_map: IndexMap<Symbol, &Struct> =
|
||||
let structs_map: IndexMap<Symbol, &Composite> =
|
||||
program_scope.structs.iter().map(|(name, struct_)| (*name, struct_)).collect();
|
||||
|
||||
// Visit each `Struct` or `Record` in the post-ordering and produce an Aleo struct or record.
|
||||
@ -100,11 +100,11 @@ impl<'a> CodeGenerator<'a> {
|
||||
program_string
|
||||
}
|
||||
|
||||
fn visit_struct_or_record(&mut self, struct_: &'a Struct) -> String {
|
||||
fn visit_struct_or_record(&mut self, struct_: &'a Composite) -> String {
|
||||
if struct_.is_record { self.visit_record(struct_) } else { self.visit_struct(struct_) }
|
||||
}
|
||||
|
||||
fn visit_struct(&mut self, struct_: &'a Struct) -> String {
|
||||
fn visit_struct(&mut self, struct_: &'a Composite) -> String {
|
||||
// Add private symbol to composite types.
|
||||
self.composite_mapping.insert(&struct_.identifier.name, (false, String::from("private"))); // todo: private by default here.
|
||||
|
||||
@ -119,7 +119,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
output_string
|
||||
}
|
||||
|
||||
fn visit_record(&mut self, record: &'a Struct) -> String {
|
||||
fn visit_record(&mut self, record: &'a Composite) -> String {
|
||||
// Add record symbol to composite types.
|
||||
let mut output_string = String::from("record");
|
||||
self.composite_mapping.insert(&record.identifier.name, (true, output_string.clone()));
|
||||
|
@ -28,6 +28,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
| Type::Scalar
|
||||
| Type::Signature
|
||||
| Type::String
|
||||
| Type::Composite(..)
|
||||
| Type::Identifier(..)
|
||||
| Type::Integer(..) => format!("{input}"),
|
||||
Type::Array(array_type) => {
|
||||
@ -36,6 +37,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
Type::Mapping(_) => {
|
||||
unreachable!("Mapping types are not supported at this phase of compilation")
|
||||
}
|
||||
//Type::Struct(_) => unreachable!("Struct types should not be visited at this phase of compilation"),
|
||||
Type::Tuple(_) => {
|
||||
unreachable!("Tuple types should not be visited at this phase of compilation")
|
||||
}
|
||||
@ -48,8 +50,8 @@ impl<'a> CodeGenerator<'a> {
|
||||
match type_ {
|
||||
// When the type is a record.
|
||||
// Note that this unwrap is safe because all composite types have been added to the mapping.
|
||||
Type::Identifier(identifier) if self.composite_mapping.get(&identifier.name).unwrap().0 => {
|
||||
format!("{identifier}.record")
|
||||
Type::Composite(struct_) if self.composite_mapping.get(&struct_.id.name).unwrap().0 => {
|
||||
format!("{}.record", struct_.id.name)
|
||||
}
|
||||
_ => match visibility {
|
||||
Mode::None => Self::visit_type(type_),
|
||||
|
@ -58,13 +58,6 @@ impl ConstantPropagationTable {
|
||||
self.scope_index()
|
||||
}
|
||||
|
||||
/// Inserts a function into the symbol table.
|
||||
pub fn insert_fn_scope(&mut self) -> Result<()> {
|
||||
self.scope_index();
|
||||
self.scopes.push(Default::default());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempts to lookup a constant in the constant propagation table.
|
||||
pub fn lookup_constant(&self, symbol: Symbol) -> Option<&Expression> {
|
||||
if let Some(constant) = self.constants.get(&symbol) {
|
||||
|
54
compiler/passes/src/common/symbol_table/location.rs
Normal file
54
compiler/passes/src/common/symbol_table/location.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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 leo_span::Symbol;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
// Create custom struct to wrap (Symbol, Symbol) so that it can be serialized and deserialized.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Location {
|
||||
pub program: Symbol,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
// Create new Location instance.
|
||||
pub fn new(program: Symbol, name: Symbol) -> Location {
|
||||
Location { program, name }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Location {
|
||||
fn serialize<S>(&self, serializer: S) -> leo_errors::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&format!("{}/{}", self.program, self.name))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Location {
|
||||
fn deserialize<D>(deserializer: D) -> leo_errors::Result<Location, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
let mut parts = s.split('/');
|
||||
let program = Symbol::intern(parts.next().unwrap());
|
||||
let name = Symbol::intern(parts.next().unwrap());
|
||||
Ok(Location::new(program, name))
|
||||
}
|
||||
}
|
@ -17,13 +17,17 @@
|
||||
pub mod function_symbol;
|
||||
pub use function_symbol::*;
|
||||
|
||||
pub mod location;
|
||||
pub use location::*;
|
||||
|
||||
pub mod variable_symbol;
|
||||
|
||||
pub use variable_symbol::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use leo_ast::{normalize_json_value, remove_key_from_json, Function, Struct};
|
||||
use leo_errors::{AstError, LeoMessageCode, Result};
|
||||
use leo_ast::{normalize_json_value, remove_key_from_json, Composite, Function};
|
||||
use leo_errors::{AstError, Result};
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
@ -37,12 +41,12 @@ pub struct SymbolTable {
|
||||
/// The parent scope if it exists.
|
||||
/// For example, the parent scope of a then-block is the scope containing the associated ConditionalStatement.
|
||||
pub(crate) parent: Option<Box<SymbolTable>>,
|
||||
/// Functions represents the name of each function mapped to the AST's function definition.
|
||||
/// Maps parent program name and function name to the AST's function definition.
|
||||
/// This field is populated at a first pass.
|
||||
pub functions: IndexMap<Symbol, FunctionSymbol>,
|
||||
/// Maps struct names to struct definitions.
|
||||
pub functions: IndexMap<Location, FunctionSymbol>,
|
||||
/// Maps parent program name and composite name to composite definitions.
|
||||
/// This field is populated at a first pass.
|
||||
pub structs: IndexMap<Symbol, Struct>,
|
||||
pub structs: IndexMap<Location, Composite>,
|
||||
/// The variables defined in a scope.
|
||||
/// This field is populated as necessary.
|
||||
pub(crate) variables: IndexMap<Symbol, VariableSymbol>,
|
||||
@ -55,18 +59,21 @@ pub struct SymbolTable {
|
||||
impl SymbolTable {
|
||||
/// Recursively checks if the symbol table contains an entry for the given symbol.
|
||||
/// Leo does not allow any variable shadowing or overlap between different symbols.
|
||||
pub fn check_shadowing(&self, symbol: Symbol, span: Span) -> Result<()> {
|
||||
pub fn check_shadowing(&self, program: Option<Symbol>, symbol: Symbol, span: Span) -> Result<()> {
|
||||
if let Some(program) = program {
|
||||
if self.functions.contains_key(&Location::new(program, symbol)) {
|
||||
return Err(AstError::shadowed_function(symbol, span).into());
|
||||
} else if let Some(existing) = self.structs.get(&Location::new(program, symbol)) {
|
||||
return match existing.is_record {
|
||||
true => Err(AstError::shadowed_record(symbol, span).into()),
|
||||
false => Err(AstError::shadowed_struct(symbol, span).into()),
|
||||
};
|
||||
}
|
||||
}
|
||||
if self.variables.contains_key(&symbol) {
|
||||
Err(AstError::shadowed_variable(symbol, span).into())
|
||||
} else if self.functions.contains_key(&symbol) {
|
||||
Err(AstError::shadowed_function(symbol, span).into())
|
||||
} else if let Some(existing) = self.structs.get(&symbol) {
|
||||
match existing.is_record {
|
||||
true => Err(AstError::shadowed_record(symbol, span).into()),
|
||||
false => Err(AstError::shadowed_struct(symbol, span).into()),
|
||||
}
|
||||
} else if let Some(parent) = self.parent.as_ref() {
|
||||
parent.check_shadowing(symbol, span)
|
||||
parent.check_shadowing(program, symbol, span)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -81,59 +88,28 @@ impl SymbolTable {
|
||||
}
|
||||
|
||||
/// Inserts a function into the symbol table.
|
||||
pub fn insert_fn(&mut self, symbol: Symbol, insert: &Function) -> Result<()> {
|
||||
self.check_shadowing(symbol, insert.span)?;
|
||||
pub fn insert_fn(&mut self, program: Symbol, symbol: Symbol, insert: &Function) -> Result<()> {
|
||||
let id = self.scope_index();
|
||||
self.functions.insert(symbol, Self::new_function_symbol(id, insert));
|
||||
self.check_shadowing(Some(program), symbol, insert.span)?;
|
||||
self.functions.insert(Location::new(program, symbol), Self::new_function_symbol(id, insert));
|
||||
self.scopes.push(Default::default());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if the struct is a duplicate of the existing struct.
|
||||
/// This is used to allow redefinitions of external structs.
|
||||
pub fn check_duplicate_struct(&self, old: &Struct, new: &Struct) -> bool {
|
||||
if old.members.len() != new.members.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (old_member, new_member) in old.members.iter().zip(new.members.iter()) {
|
||||
if old_member.identifier.name != new_member.identifier.name {
|
||||
return false;
|
||||
}
|
||||
if old_member.type_ != new_member.type_ {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Inserts a struct into the symbol table.
|
||||
pub fn insert_struct(&mut self, symbol: Symbol, insert: &Struct) -> Result<()> {
|
||||
match self.check_shadowing(symbol, insert.span) {
|
||||
pub fn insert_struct(&mut self, program: Symbol, symbol: Symbol, insert: &Composite) -> Result<()> {
|
||||
match self.check_shadowing(Some(program), symbol, insert.span) {
|
||||
Ok(_) => {
|
||||
self.structs.insert(symbol, insert.clone());
|
||||
self.structs.insert(Location::new(program, symbol), insert.clone());
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
if e.error_code() == AstError::shadowed_struct(symbol, insert.span).error_code() {
|
||||
if self.check_duplicate_struct(
|
||||
self.structs.get(&symbol).expect("Must be in symbol table since struct already referenced"),
|
||||
insert,
|
||||
) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AstError::redefining_external_struct(symbol).into())
|
||||
}
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts a variable into the symbol table.
|
||||
pub fn insert_variable(&mut self, symbol: Symbol, insert: VariableSymbol) -> Result<()> {
|
||||
self.check_shadowing(symbol, insert.span)?;
|
||||
self.check_shadowing(None, symbol, insert.span)?;
|
||||
self.variables.insert(symbol, insert);
|
||||
Ok(())
|
||||
}
|
||||
@ -150,22 +126,22 @@ impl SymbolTable {
|
||||
}
|
||||
|
||||
/// Attempts to lookup a function in the symbol table.
|
||||
pub fn lookup_fn_symbol(&self, symbol: Symbol) -> Option<&FunctionSymbol> {
|
||||
if let Some(func) = self.functions.get(&symbol) {
|
||||
pub fn lookup_fn_symbol(&self, program: Symbol, symbol: Symbol) -> Option<&FunctionSymbol> {
|
||||
if let Some(func) = self.functions.get(&Location::new(program, symbol)) {
|
||||
Some(func)
|
||||
} else if let Some(parent) = self.parent.as_ref() {
|
||||
parent.lookup_fn_symbol(symbol)
|
||||
parent.lookup_fn_symbol(program, symbol)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to lookup a struct in the symbol table.
|
||||
pub fn lookup_struct(&self, symbol: Symbol) -> Option<&Struct> {
|
||||
if let Some(struct_) = self.structs.get(&symbol) {
|
||||
pub fn lookup_struct(&self, program: Symbol, symbol: Symbol) -> Option<&Composite> {
|
||||
if let Some(struct_) = self.structs.get(&Location::new(program, symbol)) {
|
||||
Some(struct_)
|
||||
} else if let Some(parent) = self.parent.as_ref() {
|
||||
parent.lookup_struct(symbol)
|
||||
parent.lookup_struct(program, symbol)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -207,11 +183,6 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the scope associated with the function symbol, if it exists in the symbol table.
|
||||
pub fn lookup_fn_scope(&self, symbol: Symbol) -> Option<&RefCell<Self>> {
|
||||
self.lookup_fn_symbol(symbol).and_then(|func| self.scopes.get(func.id))
|
||||
}
|
||||
|
||||
/// Returns the scope associated with `index`, if it exists in the symbol table.
|
||||
pub fn lookup_scope_by_index(&self, index: usize) -> Option<&RefCell<Self>> {
|
||||
self.scopes.get(index)
|
||||
@ -273,3 +244,36 @@ impl SymbolTable {
|
||||
Self::from_json_string(&data)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use leo_ast::{Identifier, Type, Variant};
|
||||
use leo_span::symbol::create_session_if_not_set_then;
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn serialization_test() {
|
||||
create_session_if_not_set_then(|_| {
|
||||
let mut symbol_table = SymbolTable::default();
|
||||
let program = Symbol::intern("credits");
|
||||
let function = Symbol::intern("transfer_public");
|
||||
let insert = Function {
|
||||
annotations: Vec::new(),
|
||||
id: 0,
|
||||
output_type: Type::Address,
|
||||
variant: Variant::Inline,
|
||||
span: Default::default(),
|
||||
input: Vec::new(),
|
||||
finalize: None,
|
||||
identifier: Identifier::new(Symbol::intern("transfer_public"), Default::default()),
|
||||
output: vec![],
|
||||
block: Default::default(),
|
||||
};
|
||||
symbol_table.insert_fn(program, function, &insert).unwrap();
|
||||
let json = symbol_table.to_json_string().unwrap();
|
||||
dbg!(json.clone());
|
||||
let deserialized = SymbolTable::from_json_string(&json).unwrap();
|
||||
dbg!(deserialized);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ use leo_ast::{
|
||||
Identifier,
|
||||
StructExpression,
|
||||
StructVariableInitializer,
|
||||
Type,
|
||||
};
|
||||
use leo_span::sym;
|
||||
|
||||
@ -34,9 +33,8 @@ impl ExpressionReconstructor for DeadCodeEliminator<'_> {
|
||||
/// Reconstructs the associated function access expression.
|
||||
fn reconstruct_associated_function(&mut self, input: AssociatedFunction) -> (Expression, Self::AdditionalOutput) {
|
||||
// If the associated function manipulates a mapping, mark the statement as necessary.
|
||||
match (&input.ty, input.name.name) {
|
||||
(Type::Identifier(Identifier { name: sym::Mapping, .. }), sym::remove)
|
||||
| (Type::Identifier(Identifier { name: sym::Mapping, .. }), sym::set) => {
|
||||
match (&input.variant.name, input.name.name) {
|
||||
(&sym::Mapping, sym::remove) | (&sym::Mapping, sym::set) => {
|
||||
self.is_necessary = true;
|
||||
}
|
||||
_ => {}
|
||||
@ -44,7 +42,7 @@ impl ExpressionReconstructor for DeadCodeEliminator<'_> {
|
||||
// Reconstruct the access expression.
|
||||
let result = (
|
||||
Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: input.ty,
|
||||
variant: input.variant,
|
||||
name: input.name,
|
||||
arguments: input.arguments.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
|
||||
span: input.span,
|
||||
|
@ -87,9 +87,10 @@ impl ExpressionReconstructor for Flattener<'_> {
|
||||
|
||||
match &first_type {
|
||||
Type::Array(first_type) => self.ternary_array(first_type, &input.condition, &first, &second),
|
||||
Type::Identifier(first_type) => {
|
||||
Type::Composite(first_type) => {
|
||||
// Get the struct definitions.
|
||||
let first_type = self.symbol_table.lookup_struct(first_type.name).unwrap();
|
||||
let first_type =
|
||||
self.symbol_table.lookup_struct(first_type.program.unwrap(), first_type.id.name).unwrap();
|
||||
self.ternary_struct(first_type, &input.condition, &first, &second)
|
||||
}
|
||||
Type::Tuple(first_type) => self.ternary_tuple(first_type, &input.condition, &first, &second),
|
||||
|
@ -24,6 +24,8 @@ use leo_ast::{
|
||||
BinaryExpression,
|
||||
BinaryOperation,
|
||||
Block,
|
||||
Composite,
|
||||
CompositeType,
|
||||
Expression,
|
||||
ExpressionReconstructor,
|
||||
Identifier,
|
||||
@ -36,7 +38,6 @@ use leo_ast::{
|
||||
NonNegativeNumber,
|
||||
ReturnStatement,
|
||||
Statement,
|
||||
Struct,
|
||||
StructExpression,
|
||||
StructVariableInitializer,
|
||||
TernaryExpression,
|
||||
@ -384,7 +385,7 @@ impl<'a> Flattener<'a> {
|
||||
|
||||
pub(crate) fn ternary_struct(
|
||||
&mut self,
|
||||
struct_: &Struct,
|
||||
struct_: &Composite,
|
||||
condition: &Expression,
|
||||
first: &Identifier,
|
||||
second: &Identifier,
|
||||
@ -463,7 +464,8 @@ impl<'a> Flattener<'a> {
|
||||
// Create a new node ID for the struct expression.
|
||||
let id = self.node_builder.next_id();
|
||||
// Set the type of the node ID.
|
||||
self.type_table.insert(id, Type::Identifier(struct_.identifier));
|
||||
self.type_table
|
||||
.insert(id, Type::Composite(CompositeType { id: struct_.identifier, program: struct_.external }));
|
||||
id
|
||||
},
|
||||
});
|
||||
|
@ -30,6 +30,8 @@ pub struct FunctionInliner<'a> {
|
||||
pub(crate) type_table: &'a TypeTable,
|
||||
/// A map of reconstructed functions in the current program scope.
|
||||
pub(crate) reconstructed_functions: Vec<(Symbol, Function)>,
|
||||
/// The main program.
|
||||
pub(crate) program: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> FunctionInliner<'a> {
|
||||
@ -46,6 +48,7 @@ impl<'a> FunctionInliner<'a> {
|
||||
assignment_renamer: AssignmentRenamer::new(assigner),
|
||||
reconstructed_functions: Default::default(),
|
||||
type_table,
|
||||
program: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl ExpressionReconstructor for FunctionInliner<'_> {
|
||||
|
||||
fn reconstruct_call(&mut self, input: CallExpression) -> (Expression, Self::AdditionalOutput) {
|
||||
// Type checking guarantees that only functions local to the program scope can be inlined.
|
||||
if input.external.is_some() {
|
||||
if input.program.unwrap() != self.program.unwrap() {
|
||||
return (Expression::Call(input), Default::default());
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,9 @@ use indexmap::IndexMap;
|
||||
|
||||
impl ProgramReconstructor for FunctionInliner<'_> {
|
||||
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
|
||||
// Set the program name.
|
||||
self.program = Some(input.program_id.name.name);
|
||||
|
||||
// Get the post-order ordering of the call graph.
|
||||
// Note that the post-order always contains all nodes in the call graph.
|
||||
// Note that the unwrap is safe since type checking guarantees that the call graph is acyclic.
|
||||
|
@ -21,13 +21,10 @@ pub mod unroller;
|
||||
pub use unroller::*;
|
||||
|
||||
pub mod unroll_expression;
|
||||
pub use unroll_expression::*;
|
||||
|
||||
pub mod unroll_program;
|
||||
pub use unroll_program::*;
|
||||
|
||||
pub mod unroll_statement;
|
||||
pub use unroll_statement::*;
|
||||
|
||||
use crate::{Pass, SymbolTable, TypeTable};
|
||||
|
||||
|
@ -19,11 +19,28 @@ use leo_ast::*;
|
||||
use crate::Unroller;
|
||||
|
||||
impl ProgramReconstructor for Unroller<'_> {
|
||||
fn reconstruct_stub(&mut self, input: Stub) -> Stub {
|
||||
// Set the current program
|
||||
self.current_program = Some(input.stub_id.name.name);
|
||||
Stub {
|
||||
imports: input.imports,
|
||||
stub_id: input.stub_id,
|
||||
consts: input.consts,
|
||||
structs: input.structs,
|
||||
mappings: input.mappings,
|
||||
span: input.span,
|
||||
functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function_stub(f))).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
|
||||
// Don't need to reconstructed consts, just need to add them to constant propagation table
|
||||
input.consts.into_iter().for_each(|(_, c)| {
|
||||
self.reconstruct_const(c);
|
||||
});
|
||||
// Set the current program
|
||||
self.current_program = Some(input.program_id.name.name);
|
||||
// Reconstruct the program scope
|
||||
ProgramScope {
|
||||
program_id: input.program_id,
|
||||
structs: input.structs,
|
||||
@ -38,7 +55,12 @@ impl ProgramReconstructor for Unroller<'_> {
|
||||
fn reconstruct_function_stub(&mut self, input: FunctionStub) -> FunctionStub {
|
||||
// Lookup function metadata in the symbol table.
|
||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||
let function_index = self.symbol_table.borrow().lookup_fn_symbol(input.identifier.name).unwrap().id;
|
||||
let function_index = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_fn_symbol(self.current_program.unwrap(), input.identifier.name)
|
||||
.unwrap()
|
||||
.id;
|
||||
|
||||
// Enter the function's scope.
|
||||
let previous_function_index = self.enter_scope(function_index);
|
||||
@ -52,7 +74,12 @@ impl ProgramReconstructor for Unroller<'_> {
|
||||
fn reconstruct_function(&mut self, function: Function) -> Function {
|
||||
// Lookup function metadata in the symbol table.
|
||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||
let function_index = self.symbol_table.borrow().lookup_fn_symbol(function.identifier.name).unwrap().id;
|
||||
let function_index = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_fn_symbol(self.current_program.unwrap(), function.identifier.name)
|
||||
.unwrap()
|
||||
.id;
|
||||
|
||||
// Enter the function's scope.
|
||||
let previous_function_index = self.enter_scope(function_index);
|
||||
|
@ -29,6 +29,7 @@ use leo_ast::{
|
||||
use std::cell::RefCell;
|
||||
|
||||
use leo_errors::{emitter::Handler, loop_unroller::LoopUnrollerError};
|
||||
use leo_span::Symbol;
|
||||
|
||||
use crate::{
|
||||
constant_propagation_table::ConstantPropagationTable,
|
||||
@ -54,6 +55,8 @@ pub struct Unroller<'a> {
|
||||
pub(crate) node_builder: &'a NodeBuilder,
|
||||
/// Are we in the midst of unrolling a loop?
|
||||
pub(crate) is_unrolling: bool,
|
||||
/// The current program name.
|
||||
pub(crate) current_program: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> Unroller<'a> {
|
||||
@ -71,6 +74,7 @@ impl<'a> Unroller<'a> {
|
||||
handler,
|
||||
node_builder,
|
||||
is_unrolling: false,
|
||||
current_program: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,13 +24,13 @@ use leo_ast::{
|
||||
BinaryExpression,
|
||||
CallExpression,
|
||||
CastExpression,
|
||||
Composite,
|
||||
Expression,
|
||||
ExpressionConsumer,
|
||||
Identifier,
|
||||
Literal,
|
||||
MemberAccess,
|
||||
Statement,
|
||||
Struct,
|
||||
StructExpression,
|
||||
StructVariableInitializer,
|
||||
TernaryExpression,
|
||||
@ -53,7 +53,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
let mut statements = Vec::new();
|
||||
(
|
||||
AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: function.ty,
|
||||
variant: function.variant,
|
||||
name: function.name,
|
||||
arguments: function
|
||||
.arguments
|
||||
@ -192,7 +192,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
function: input.function,
|
||||
// Consume the arguments.
|
||||
arguments,
|
||||
external: input.external,
|
||||
program: input.program,
|
||||
span: input.span,
|
||||
id: input.id,
|
||||
}));
|
||||
@ -252,7 +252,8 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
|
||||
// Lookup the struct definition.
|
||||
// Note that type checking guarantees that the correct struct definition exists.
|
||||
let struct_definition: &Struct = self.symbol_table.lookup_struct(input.name.name).unwrap();
|
||||
let struct_definition: &Composite =
|
||||
self.symbol_table.lookup_struct(self.program.unwrap(), input.name.name).unwrap();
|
||||
|
||||
// Initialize the list of reordered members.
|
||||
let mut reordered_members = Vec::with_capacity(members.len());
|
||||
|
@ -18,6 +18,7 @@ use crate::StaticSingleAssigner;
|
||||
|
||||
use leo_ast::{
|
||||
Block,
|
||||
Composite,
|
||||
Finalize,
|
||||
Function,
|
||||
FunctionConsumer,
|
||||
@ -27,7 +28,6 @@ use leo_ast::{
|
||||
ProgramScope,
|
||||
ProgramScopeConsumer,
|
||||
StatementConsumer,
|
||||
Struct,
|
||||
StructConsumer,
|
||||
};
|
||||
use leo_span::{sym, Symbol};
|
||||
@ -35,10 +35,10 @@ use leo_span::{sym, Symbol};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
impl StructConsumer for StaticSingleAssigner<'_> {
|
||||
type Output = Struct;
|
||||
type Output = Composite;
|
||||
|
||||
/// Reconstructs records in the program, ordering its fields such that `owner` and is the first field.
|
||||
fn consume_struct(&mut self, struct_: Struct) -> Self::Output {
|
||||
fn consume_struct(&mut self, struct_: Composite) -> Self::Output {
|
||||
match struct_.is_record {
|
||||
false => struct_,
|
||||
true => {
|
||||
@ -53,7 +53,7 @@ impl StructConsumer for StaticSingleAssigner<'_> {
|
||||
// Add the remaining fields to the members list.
|
||||
members.extend(member_map.into_iter().map(|(_, member)| member));
|
||||
|
||||
Struct { members, ..struct_ }
|
||||
Composite { members, ..struct_ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,6 +130,7 @@ impl ProgramScopeConsumer for StaticSingleAssigner<'_> {
|
||||
type Output = ProgramScope;
|
||||
|
||||
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
|
||||
self.program = Some(input.program_id.name.name);
|
||||
ProgramScope {
|
||||
program_id: input.program_id,
|
||||
structs: input.structs.into_iter().map(|(i, s)| (i, self.consume_struct(s))).collect(),
|
||||
|
@ -344,7 +344,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
expression: Expression::Call(CallExpression {
|
||||
function: call.function,
|
||||
arguments,
|
||||
external: call.external,
|
||||
program: call.program,
|
||||
span: call.span,
|
||||
id: call.id,
|
||||
}),
|
||||
@ -359,7 +359,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
|
||||
// Note that we do not create a new assignment for the associated function; this is necessary for correct code generation.
|
||||
statements.push(Statement::Expression(ExpressionStatement {
|
||||
expression: Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
|
||||
ty: associated_function.ty,
|
||||
variant: associated_function.variant,
|
||||
name: associated_function.name,
|
||||
arguments,
|
||||
span: associated_function.span,
|
||||
|
@ -17,6 +17,7 @@
|
||||
use crate::{Assigner, RenameTable, SymbolTable, TypeTable};
|
||||
|
||||
use leo_ast::{Expression, Identifier, Node, NodeBuilder, Statement};
|
||||
use leo_span::Symbol;
|
||||
|
||||
pub struct StaticSingleAssigner<'a> {
|
||||
/// A counter used to generate unique node IDs.
|
||||
@ -31,6 +32,8 @@ pub struct StaticSingleAssigner<'a> {
|
||||
pub(crate) is_lhs: bool,
|
||||
/// A struct used to construct (unique) assignment statements.
|
||||
pub(crate) assigner: &'a Assigner,
|
||||
/// The main program name.
|
||||
pub(crate) program: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> StaticSingleAssigner<'a> {
|
||||
@ -41,7 +44,15 @@ impl<'a> StaticSingleAssigner<'a> {
|
||||
type_table: &'a TypeTable,
|
||||
assigner: &'a Assigner,
|
||||
) -> Self {
|
||||
Self { node_builder, symbol_table, type_table, rename_table: RenameTable::new(None), is_lhs: false, assigner }
|
||||
Self {
|
||||
node_builder,
|
||||
symbol_table,
|
||||
type_table,
|
||||
rename_table: RenameTable::new(None),
|
||||
is_lhs: false,
|
||||
assigner,
|
||||
program: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes a new scope, setting the current scope as the new scope's parent.
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use leo_ast::*;
|
||||
use leo_errors::emitter::Handler;
|
||||
use leo_span::Symbol;
|
||||
|
||||
use crate::{SymbolTable, VariableSymbol, VariableType};
|
||||
|
||||
@ -27,11 +28,13 @@ pub struct SymbolTableCreator<'a> {
|
||||
pub(crate) symbol_table: SymbolTable,
|
||||
/// The error handler.
|
||||
handler: &'a Handler,
|
||||
/// The current program name.
|
||||
program_name: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> SymbolTableCreator<'a> {
|
||||
pub fn new(handler: &'a Handler) -> Self {
|
||||
Self { symbol_table: Default::default(), handler }
|
||||
Self { symbol_table: Default::default(), handler, program_name: None }
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,12 +46,23 @@ impl<'a> ExpressionVisitor<'a> for SymbolTableCreator<'a> {
|
||||
impl<'a> StatementVisitor<'a> for SymbolTableCreator<'a> {}
|
||||
|
||||
impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> {
|
||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||
// Set current program name
|
||||
self.program_name = Some(input.program_id.name.name);
|
||||
|
||||
// Visit the program scope
|
||||
input.structs.iter().for_each(|(_, c)| (self.visit_struct(c)));
|
||||
input.mappings.iter().for_each(|(_, c)| (self.visit_mapping(c)));
|
||||
input.functions.iter().for_each(|(_, c)| (self.visit_function(c)));
|
||||
input.consts.iter().for_each(|(_, c)| (self.visit_const(c)));
|
||||
}
|
||||
|
||||
fn visit_import(&mut self, input: &'a Program) {
|
||||
self.visit_program(input)
|
||||
}
|
||||
|
||||
fn visit_struct(&mut self, input: &'a Struct) {
|
||||
if let Err(err) = self.symbol_table.insert_struct(input.name(), input) {
|
||||
fn visit_struct(&mut self, input: &'a Composite) {
|
||||
if let Err(err) = self.symbol_table.insert_struct(self.program_name.unwrap(), input.name(), input) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
@ -68,19 +82,27 @@ impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> {
|
||||
}
|
||||
|
||||
fn visit_function(&mut self, input: &'a Function) {
|
||||
if let Err(err) = self.symbol_table.insert_fn(input.name(), input) {
|
||||
if let Err(err) = self.symbol_table.insert_fn(self.program_name.unwrap(), input.name(), input) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_stub(&mut self, input: &'a Stub) {
|
||||
self.program_name = Some(input.stub_id.name.name);
|
||||
input.functions.iter().for_each(|(_, c)| (self.visit_function_stub(c)));
|
||||
|
||||
input.structs.iter().for_each(|(_, c)| (self.visit_struct(c)));
|
||||
input.structs.iter().for_each(|(_, c)| (self.visit_struct_stub(c)));
|
||||
}
|
||||
|
||||
fn visit_function_stub(&mut self, input: &'a FunctionStub) {
|
||||
if let Err(err) = self.symbol_table.insert_fn(input.name(), &Function::from(input.clone())) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.insert_fn(self.program_name.unwrap(), input.name(), &Function::from(input.clone()))
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct_stub(&mut self, input: &'a Composite) {
|
||||
if let Err(err) = self.symbol_table.insert_struct(self.program_name.unwrap(), input.name(), input) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
AccessExpression::AssociatedFunction(access) => {
|
||||
// Check core struct name and function.
|
||||
if let Some(core_instruction) = self.get_core_function_call(&access.ty, &access.name) {
|
||||
if let Some(core_instruction) = self.get_core_function_call(&access.variant, &access.name) {
|
||||
// Check that operation is not restricted to finalize blocks.
|
||||
if !self.is_finalize && core_instruction.is_finalize_command() {
|
||||
self.emit_err(TypeCheckerError::operation_must_be_in_finalize_block(input.span()));
|
||||
@ -203,9 +203,13 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
_ => {
|
||||
// Check that the type of `inner` in `inner.name` is a struct.
|
||||
match self.visit_expression(&access.inner, &None) {
|
||||
Some(Type::Identifier(identifier)) => {
|
||||
Some(Type::Composite(struct_)) => {
|
||||
// Retrieve the struct definition associated with `identifier`.
|
||||
let struct_ = self.symbol_table.borrow().lookup_struct(identifier.name).cloned();
|
||||
let struct_ = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(struct_.program.unwrap(), struct_.id.name)
|
||||
.cloned();
|
||||
if let Some(struct_) = struct_ {
|
||||
// Check that `access.name` is a member of the struct.
|
||||
match struct_.members.iter().find(|member| member.name() == access.name.name) {
|
||||
@ -566,8 +570,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
Expression::Identifier(ident) => {
|
||||
// Note: The function symbol lookup is performed outside of the `if let Some(func) ...` block to avoid a RefCell lifetime bug in Rust.
|
||||
// Do not move it into the `if let Some(func) ...` block or it will keep `self.symbol_table_creation` alive for the entire block and will be very memory inefficient!
|
||||
let func = self.symbol_table.borrow().lookup_fn_symbol(ident.name).cloned();
|
||||
|
||||
let func = self.symbol_table.borrow().lookup_fn_symbol(input.program.unwrap(), ident.name).cloned();
|
||||
if let Some(func) = func {
|
||||
// Check that the call is valid.
|
||||
// Note that this unwrap is safe since we always set the variant before traversing the body of the function.
|
||||
@ -580,7 +583,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
// If the function is a transition function, then check that the call is not to another local transition function.
|
||||
Variant::Transition => {
|
||||
if matches!(func.variant, Variant::Transition) && input.external.is_none() {
|
||||
if matches!(func.variant, Variant::Transition)
|
||||
&& input.program.unwrap() == self.program_name.unwrap()
|
||||
{
|
||||
self.emit_err(TypeCheckerError::cannot_invoke_call_to_local_transition_function(
|
||||
input.span,
|
||||
));
|
||||
@ -589,7 +594,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
|
||||
// Check that the call is not to an external `inline` function.
|
||||
if func.variant == Variant::Inline && input.external.is_some() {
|
||||
if func.variant == Variant::Inline && input.program.unwrap() != self.program_name.unwrap() {
|
||||
self.emit_err(TypeCheckerError::cannot_call_external_inline_function(input.span));
|
||||
}
|
||||
|
||||
@ -614,7 +619,12 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
None => unreachable!("`self.function` is set every time a function is visited."),
|
||||
Some(func) => func,
|
||||
};
|
||||
self.call_graph.add_edge(caller_name, ident.name);
|
||||
|
||||
// Don't add external functions to call graph.
|
||||
// We check that there is no dependency cycle of imports, so we know that external functions can never lead to a call graph cycle
|
||||
if input.program.unwrap() == self.program_name.unwrap() {
|
||||
self.call_graph.add_edge(caller_name, ident.name);
|
||||
}
|
||||
|
||||
Some(ret)
|
||||
} else {
|
||||
@ -639,10 +649,10 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
|
||||
fn visit_struct_init(&mut self, input: &'a StructExpression, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
let struct_ = self.symbol_table.borrow().lookup_struct(input.name.name).cloned();
|
||||
let struct_ = self.symbol_table.borrow().lookup_struct(self.program_name.unwrap(), input.name.name).cloned();
|
||||
if let Some(struct_) = struct_ {
|
||||
// Check struct type name.
|
||||
let ret = self.check_expected_struct(struct_.identifier, additional, input.name.span());
|
||||
let ret = self.check_expected_struct(&struct_, additional, input.name.span());
|
||||
|
||||
// Check number of struct members.
|
||||
if struct_.members.len() != input.members.len() {
|
||||
|
@ -46,9 +46,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
|
||||
fn visit_stub(&mut self, input: &'a Stub) {
|
||||
// Set the current program name.
|
||||
self.program_name = Some(input.stub_id.name.name);
|
||||
|
||||
// Cannot have constant declarations in stubs.
|
||||
if !input.consts.is_empty() {
|
||||
self.emit_err(TypeCheckerError::stubs_cannot_have_const_declarations(input.consts.get(0).unwrap().1.span));
|
||||
self.emit_err(TypeCheckerError::stubs_cannot_have_const_declarations(input.consts.first().unwrap().1.span));
|
||||
}
|
||||
|
||||
// Typecheck the program's structs.
|
||||
@ -66,7 +69,8 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
// Lookup function metadata in the symbol table.
|
||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||
let function_index = self.symbol_table.borrow().lookup_fn_symbol(input.identifier.name).unwrap().id;
|
||||
let function_index =
|
||||
self.symbol_table.borrow().lookup_fn_symbol(self.program_name.unwrap(), input.identifier.name).unwrap().id;
|
||||
|
||||
// Enter the function's scope.
|
||||
self.enter_scope(function_index);
|
||||
@ -97,11 +101,14 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
self.exit_scope(function_index);
|
||||
}
|
||||
|
||||
fn visit_struct_stub(&mut self, input: &'a Struct) {
|
||||
fn visit_struct_stub(&mut self, input: &'a Composite) {
|
||||
self.visit_struct(input);
|
||||
}
|
||||
|
||||
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
|
||||
// Set the current program name.
|
||||
self.program_name = Some(input.program_id.name.name);
|
||||
|
||||
// Typecheck each const definition, and append to symbol table.
|
||||
input.consts.iter().for_each(|(_, c)| self.visit_const(c));
|
||||
|
||||
@ -157,7 +164,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct(&mut self, input: &'a Struct) {
|
||||
fn visit_struct(&mut self, input: &'a Composite) {
|
||||
// Check for conflicting struct/record member names.
|
||||
let mut used = HashSet::new();
|
||||
// TODO: Better span to target duplicate member.
|
||||
@ -203,8 +210,9 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
// If the member is a struct, add it to the struct dependency graph.
|
||||
// Note that we have already checked that each member is defined and valid.
|
||||
if let Type::Identifier(member_type) = type_ {
|
||||
self.struct_graph.add_edge(input.identifier.name, member_type.name);
|
||||
if let Type::Composite(struct_member_type) = type_ {
|
||||
// Note that since there are no cycles in the program dependency graph, there are no cycles in the struct dependency graph caused by external structs.
|
||||
self.struct_graph.add_edge(input.identifier.name, struct_member_type.id.name);
|
||||
} else if let Type::Array(array_type) = type_ {
|
||||
// Get the base element type.
|
||||
let base_element_type = array_type.base_element_type();
|
||||
@ -225,10 +233,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
// Check that a mapping's key type is valid.
|
||||
self.assert_type_is_valid(&input.key_type, input.span);
|
||||
// Check that a mapping's key type is not a tuple, record, or mapping.
|
||||
match input.key_type {
|
||||
match input.key_type.clone() {
|
||||
Type::Tuple(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("key", "tuple", input.span)),
|
||||
Type::Identifier(identifier) => {
|
||||
if let Some(struct_) = self.symbol_table.borrow().lookup_struct(identifier.name) {
|
||||
Type::Composite(struct_type) => {
|
||||
if let Some(struct_) =
|
||||
self.symbol_table.borrow().lookup_struct(struct_type.program.unwrap(), struct_type.id.name)
|
||||
{
|
||||
if struct_.is_record {
|
||||
self.emit_err(TypeCheckerError::invalid_mapping_type("key", "record", input.span));
|
||||
}
|
||||
@ -242,10 +252,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
// Check that a mapping's value type is valid.
|
||||
self.assert_type_is_valid(&input.value_type, input.span);
|
||||
// Check that a mapping's value type is not a tuple, record or mapping.
|
||||
match input.value_type {
|
||||
match input.value_type.clone() {
|
||||
Type::Tuple(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("value", "tuple", input.span)),
|
||||
Type::Identifier(identifier) => {
|
||||
if let Some(struct_) = self.symbol_table.borrow().lookup_struct(identifier.name) {
|
||||
Type::Composite(struct_type) => {
|
||||
if let Some(struct_) =
|
||||
self.symbol_table.borrow().lookup_struct(struct_type.program.unwrap(), struct_type.id.name)
|
||||
{
|
||||
if struct_.is_record {
|
||||
self.emit_err(TypeCheckerError::invalid_mapping_type("value", "record", input.span));
|
||||
}
|
||||
@ -269,7 +281,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
// Lookup function metadata in the symbol table.
|
||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||
let function_index = self.symbol_table.borrow().lookup_fn_symbol(function.identifier.name).unwrap().id;
|
||||
let function_index = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_fn_symbol(self.program_name.unwrap(), function.identifier.name)
|
||||
.unwrap()
|
||||
.id;
|
||||
|
||||
// Enter the function's scope.
|
||||
self.enter_scope(function_index);
|
||||
|
@ -205,7 +205,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// Check that the type of the definition is defined.
|
||||
self.assert_type_is_valid(&input.type_, input.span);
|
||||
|
||||
// Check that the type of the definition is not a unit type, singleton tuple type, or nested tuple type.
|
||||
// Check that the type of the definition is not a unit type, singleton tuple type, nested tuple type, or external struct type.
|
||||
match &input.type_ {
|
||||
// If the type is an empty tuple, return an error.
|
||||
Type::Unit => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.span)),
|
||||
@ -213,14 +213,23 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
Type::Tuple(tuple) => match tuple.length() {
|
||||
0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."),
|
||||
_ => {
|
||||
if tuple.elements().iter().any(|type_| matches!(type_, Type::Tuple(_))) {
|
||||
self.emit_err(TypeCheckerError::nested_tuple_type(input.span))
|
||||
for type_ in tuple.elements() {
|
||||
if matches!(type_, Type::Tuple(_)) {
|
||||
self.emit_err(TypeCheckerError::nested_tuple_type(input.span))
|
||||
}
|
||||
if let Type::Composite(composite) = type_ {
|
||||
self.assert_internal_struct(composite, input.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Type::Mapping(_) | Type::Err => unreachable!(
|
||||
"Parsing guarantees that `mapping` and `err` types are not present at this location in the AST."
|
||||
),
|
||||
// Make sure there are no instances of external structs created.
|
||||
Type::Composite(composite) => {
|
||||
self.assert_internal_struct(composite, input.span);
|
||||
}
|
||||
// Otherwise, the type is valid.
|
||||
_ => (), // Do nothing
|
||||
}
|
||||
@ -372,11 +381,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// We can safely unwrap all self.parent instances because
|
||||
// statements should always have some parent block
|
||||
let parent = self.function.unwrap();
|
||||
let return_type = &self.symbol_table.borrow().lookup_fn_symbol(parent).map(|f| match self.is_finalize {
|
||||
// TODO: Check this.
|
||||
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
|
||||
true => f.finalize.as_ref().unwrap().output_type.clone(),
|
||||
false => f.output_type.clone(),
|
||||
let return_type = &self.symbol_table.borrow().lookup_fn_symbol(self.program_name.unwrap(), parent).map(|f| {
|
||||
match self.is_finalize {
|
||||
// TODO: Check this.
|
||||
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
|
||||
true => f.finalize.as_ref().unwrap().output_type.clone(),
|
||||
false => f.output_type.clone(),
|
||||
}
|
||||
});
|
||||
|
||||
// Set the `has_return` flag.
|
||||
@ -409,8 +420,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// Check that the function has a finalize block.
|
||||
// Note that `self.function.unwrap()` is safe since every `self.function` is set for every function.
|
||||
// Note that `(self.function.unwrap()).unwrap()` is safe since all functions have been checked to exist.
|
||||
let finalize =
|
||||
self.symbol_table.borrow().lookup_fn_symbol(self.function.unwrap()).unwrap().finalize.clone();
|
||||
let finalize = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_fn_symbol(self.program_name.unwrap(), self.function.unwrap())
|
||||
.unwrap()
|
||||
.finalize
|
||||
.clone();
|
||||
match finalize {
|
||||
None => self.emit_err(TypeCheckerError::finalize_without_finalize_block(input.span())),
|
||||
Some(finalize) => {
|
||||
|
@ -17,6 +17,8 @@
|
||||
use crate::{CallGraph, StructGraph, SymbolTable, TypeTable, VariableSymbol, VariableType};
|
||||
|
||||
use leo_ast::{
|
||||
Composite,
|
||||
CompositeType,
|
||||
CoreConstant,
|
||||
CoreFunction,
|
||||
Finalize,
|
||||
@ -61,6 +63,8 @@ pub struct TypeChecker<'a> {
|
||||
pub(crate) is_finalize: bool,
|
||||
/// Whether or not we are currently traversing a return statement.
|
||||
pub(crate) is_return: bool,
|
||||
/// Current program name.
|
||||
pub(crate) program_name: Option<Symbol>,
|
||||
/// Whether or not we are currently traversing a stub.
|
||||
pub(crate) is_stub: bool,
|
||||
}
|
||||
@ -112,9 +116,8 @@ const MAGNITUDE_TYPES: [Type; 3] =
|
||||
impl<'a> TypeChecker<'a> {
|
||||
/// Returns a new type checker given a symbol table and error handler.
|
||||
pub fn new(symbol_table: SymbolTable, type_table: &'a TypeTable, handler: &'a Handler) -> Self {
|
||||
let struct_names = symbol_table.structs.keys().cloned().collect();
|
||||
|
||||
let function_names = symbol_table.functions.keys().cloned().collect();
|
||||
let struct_names = symbol_table.structs.keys().map(|loc| loc.name).collect();
|
||||
let function_names = symbol_table.functions.keys().map(|loc| loc.name).collect();
|
||||
|
||||
// Note that the `struct_graph` and `call_graph` are initialized with their full node sets.
|
||||
Self {
|
||||
@ -129,6 +132,7 @@ impl<'a> TypeChecker<'a> {
|
||||
has_finalize: false,
|
||||
is_finalize: false,
|
||||
is_return: false,
|
||||
program_name: None,
|
||||
is_stub: true,
|
||||
}
|
||||
}
|
||||
@ -175,6 +179,17 @@ impl<'a> TypeChecker<'a> {
|
||||
pub(crate) fn check_eq_types(&self, t1: &Option<Type>, t2: &Option<Type>, span: Span) {
|
||||
match (t1, t2) {
|
||||
(Some(t1), Some(t2)) if !Type::eq_flat(t1, t2) => {
|
||||
if let (Type::Composite(left), Type::Composite(right)) = (t1, t2) {
|
||||
if !self.check_duplicate_struct(left.id.name, left.program.unwrap(), right.program.unwrap()) {
|
||||
self.emit_err(TypeCheckerError::struct_definitions_dont_match(
|
||||
left.id.name.to_string(),
|
||||
left.program.unwrap().to_string(),
|
||||
right.program.unwrap().to_string(),
|
||||
span,
|
||||
));
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.emit_err(TypeCheckerError::type_should_be(t1, t2, span))
|
||||
}
|
||||
(Some(type_), None) | (None, Some(type_)) => {
|
||||
@ -187,10 +202,8 @@ impl<'a> TypeChecker<'a> {
|
||||
/// Use this method when you know the actual type.
|
||||
/// Emits an error to the handler if the `actual` type is not equal to the `expected` type.
|
||||
pub(crate) fn assert_and_return_type(&self, actual: Type, expected: &Option<Type>, span: Span) -> Type {
|
||||
if let Some(expected) = expected {
|
||||
if !actual.eq_flat(expected) {
|
||||
self.emit_err(TypeCheckerError::type_should_be(actual.clone(), expected, span));
|
||||
}
|
||||
if expected.is_some() {
|
||||
self.check_eq_types(&Some(actual.clone()), expected, span);
|
||||
}
|
||||
actual
|
||||
}
|
||||
@ -374,18 +387,16 @@ impl<'a> TypeChecker<'a> {
|
||||
|
||||
/// Emits an error if the `struct` is not a core library struct.
|
||||
/// Emits an error if the `function` is not supported by the struct.
|
||||
pub(crate) fn get_core_function_call(&self, struct_: &Type, function: &Identifier) -> Option<CoreFunction> {
|
||||
if let Type::Identifier(ident) = struct_ {
|
||||
// Lookup core struct
|
||||
match CoreFunction::from_symbols(ident.name, function.name) {
|
||||
None => {
|
||||
// Not a core library struct.
|
||||
self.emit_err(TypeCheckerError::invalid_core_function(ident.name, function.name, ident.span()));
|
||||
}
|
||||
Some(core_instruction) => return Some(core_instruction),
|
||||
pub(crate) fn get_core_function_call(&self, struct_: &Identifier, function: &Identifier) -> Option<CoreFunction> {
|
||||
// Lookup core struct
|
||||
match CoreFunction::from_symbols(struct_.name, function.name) {
|
||||
None => {
|
||||
// Not a core library struct.
|
||||
self.emit_err(TypeCheckerError::invalid_core_function(struct_.name, function.name, struct_.span()));
|
||||
None
|
||||
}
|
||||
Some(core_instruction) => Some(core_instruction),
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Type checks the inputs to a core function call and returns the expected output type.
|
||||
@ -1041,26 +1052,67 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
|
||||
/// Returns the `struct` type and emits an error if the `expected` type does not match.
|
||||
pub(crate) fn check_expected_struct(&mut self, struct_: Identifier, expected: &Option<Type>, span: Span) -> Type {
|
||||
if let Some(expected) = expected {
|
||||
if !Type::Identifier(struct_).eq_flat(expected) {
|
||||
self.emit_err(TypeCheckerError::type_should_be(struct_.name, expected, span));
|
||||
}
|
||||
pub(crate) fn check_expected_struct(&mut self, struct_: &Composite, expected: &Option<Type>, span: Span) -> Type {
|
||||
let current_struct = CompositeType { id: struct_.identifier, program: struct_.external };
|
||||
if expected.is_some() {
|
||||
self.check_eq_types(&Some(Type::Composite(current_struct)), expected, span);
|
||||
}
|
||||
Type::Identifier(struct_)
|
||||
Type::Composite(current_struct)
|
||||
}
|
||||
|
||||
/// Determines if two struct definitions from different programs match or not.
|
||||
pub(crate) fn check_duplicate_struct(&self, name: Symbol, program_1: Symbol, program_2: Symbol) -> bool {
|
||||
// Make sure that both structs have been defined already.
|
||||
let st = self.symbol_table.borrow();
|
||||
let (struct_1, struct_2) = match (st.lookup_struct(program_1, name), st.lookup_struct(program_2, name)) {
|
||||
(Some(struct_1), Some(struct_2)) => (struct_1, struct_2),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
// Make sure both structs have the same number of members
|
||||
if struct_1.members.len() != struct_2.members.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that all members of the structs match.
|
||||
for (member_1, member_2) in struct_1.members.iter().zip(struct_2.members.iter()) {
|
||||
// Make sure that the member names match.
|
||||
if member_1.identifier.name != member_2.identifier.name {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that the member types match.
|
||||
if member_1.type_.eq_flat(&member_2.type_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Recursively check that the member types match in the case that the type is struct.
|
||||
return if let (Type::Composite(internal_struct_1), Type::Composite(internal_struct_2)) =
|
||||
(&member_1.type_, &member_2.type_)
|
||||
{
|
||||
self.check_duplicate_struct(
|
||||
internal_struct_1.id.name,
|
||||
internal_struct_1.program.unwrap(),
|
||||
internal_struct_2.program.unwrap(),
|
||||
)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Emits an error if the struct member is a record type.
|
||||
pub(crate) fn assert_member_is_not_record(&self, span: Span, parent: Symbol, type_: &Type) {
|
||||
match type_ {
|
||||
Type::Identifier(identifier)
|
||||
Type::Composite(struct_)
|
||||
if self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(identifier.name)
|
||||
.lookup_struct(struct_.program.unwrap(), struct_.id.name)
|
||||
.map_or(false, |struct_| struct_.is_record) =>
|
||||
{
|
||||
self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(parent, identifier.name, span))
|
||||
self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(parent, struct_.id.name, span))
|
||||
}
|
||||
Type::Tuple(tuple_type) => {
|
||||
for type_ in tuple_type.elements().iter() {
|
||||
@ -1081,9 +1133,11 @@ impl<'a> TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::strings_are_not_supported(span));
|
||||
}
|
||||
// Check that the named composite type has been defined.
|
||||
Type::Identifier(identifier) if self.symbol_table.borrow().lookup_struct(identifier.name).is_none() => {
|
||||
Type::Composite(struct_)
|
||||
if self.symbol_table.borrow().lookup_struct(struct_.program.unwrap(), struct_.id.name).is_none() =>
|
||||
{
|
||||
is_valid = false;
|
||||
self.emit_err(TypeCheckerError::undefined_type(identifier.name, span));
|
||||
self.emit_err(TypeCheckerError::undefined_type(struct_.id.name, span));
|
||||
}
|
||||
// Check that the constituent types of the tuple are valid.
|
||||
Type::Tuple(tuple_type) => {
|
||||
@ -1111,9 +1165,11 @@ impl<'a> TypeChecker<'a> {
|
||||
// Array elements cannot be tuples.
|
||||
Type::Tuple(_) => self.emit_err(TypeCheckerError::array_element_cannot_be_tuple(span)),
|
||||
// Array elements cannot be records.
|
||||
Type::Identifier(identifier) => {
|
||||
Type::Composite(struct_type) => {
|
||||
// Look up the type.
|
||||
if let Some(struct_) = self.symbol_table.borrow().lookup_struct(identifier.name) {
|
||||
if let Some(struct_) =
|
||||
self.symbol_table.borrow().lookup_struct(struct_type.program.unwrap(), struct_type.id.name)
|
||||
{
|
||||
// Check that the type is not a record.
|
||||
if struct_.is_record {
|
||||
self.emit_err(TypeCheckerError::array_element_cannot_be_record(span));
|
||||
@ -1170,8 +1226,8 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
|
||||
// If the function is not a transition function, then it cannot have a record as input
|
||||
if let Type::Identifier(identifier) = input_var.type_() {
|
||||
if let Some(val) = self.symbol_table.borrow().lookup_struct(identifier.name) {
|
||||
if let Type::Composite(struct_) = input_var.type_() {
|
||||
if let Some(val) = self.symbol_table.borrow().lookup_struct(struct_.program.unwrap(), struct_.id.name) {
|
||||
if val.is_record && !matches!(function.variant, Variant::Transition) {
|
||||
self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(input_var.span()));
|
||||
}
|
||||
@ -1209,9 +1265,14 @@ impl<'a> TypeChecker<'a> {
|
||||
// Check that the type of output is defined.
|
||||
if self.assert_type_is_valid(&function_output.type_, function_output.span) {
|
||||
// If the function is not a transition function, then it cannot output a record.
|
||||
if let Type::Identifier(identifier) = function_output.type_ {
|
||||
if let Type::Composite(struct_) = function_output.type_.clone() {
|
||||
if !matches!(function.variant, Variant::Transition)
|
||||
&& self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record
|
||||
&& self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(struct_.program.unwrap(), struct_.id.name)
|
||||
.unwrap()
|
||||
.is_record
|
||||
{
|
||||
self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(
|
||||
function_output.span,
|
||||
@ -1256,9 +1317,15 @@ impl<'a> TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::finalize_cannot_take_tuple_as_input(input_var.span()))
|
||||
}
|
||||
// Check that the input parameter is not a record.
|
||||
if let Type::Identifier(identifier) = input_var.type_() {
|
||||
if let Type::Composite(struct_) = input_var.type_() {
|
||||
// Note that this unwrap is safe, as the type is defined.
|
||||
if self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record {
|
||||
if self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(struct_.program.unwrap(), struct_.id.name)
|
||||
.unwrap()
|
||||
.is_record
|
||||
{
|
||||
self.emit_err(TypeCheckerError::finalize_cannot_take_record_as_input(input_var.span()))
|
||||
}
|
||||
}
|
||||
@ -1299,9 +1366,15 @@ impl<'a> TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::nested_tuple_type(output_type.span()))
|
||||
}
|
||||
// Check that the output is not a record.
|
||||
if let Type::Identifier(identifier) = output_type.type_() {
|
||||
if let Type::Composite(struct_) = output_type.type_() {
|
||||
// Note that this unwrap is safe, as the type is defined.
|
||||
if self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record {
|
||||
if self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(struct_.program.unwrap(), struct_.id.name)
|
||||
.unwrap()
|
||||
.is_record
|
||||
{
|
||||
self.emit_err(TypeCheckerError::finalize_cannot_output_record(output_type.span()))
|
||||
}
|
||||
}
|
||||
@ -1316,6 +1389,19 @@ impl<'a> TypeChecker<'a> {
|
||||
// Check that the return type is defined. Note that the component types are already checked.
|
||||
self.assert_type_is_valid(&finalize.output_type, finalize.span);
|
||||
}
|
||||
|
||||
/// Emits an error if the type corresponds to an external struct.
|
||||
pub(crate) fn assert_internal_struct(&self, composite: &CompositeType, span: Span) {
|
||||
let st = self.symbol_table.borrow();
|
||||
match st.lookup_struct(composite.program.unwrap(), composite.id.name) {
|
||||
None => self.emit_err(TypeCheckerError::undefined_type(composite.id, span)),
|
||||
Some(composite_def) => {
|
||||
if !composite_def.is_record && composite_def.external.unwrap() != self.program_name.unwrap() {
|
||||
self.emit_err(TypeCheckerError::cannot_define_external_struct(composite.id, span))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn types_to_string(types: &[Type]) -> String {
|
||||
|
@ -16,13 +16,9 @@
|
||||
|
||||
pub mod check_expressions;
|
||||
|
||||
pub use check_expressions::*;
|
||||
|
||||
pub mod check_program;
|
||||
pub use check_program::*;
|
||||
|
||||
pub mod check_statements;
|
||||
pub use check_statements::*;
|
||||
|
||||
pub mod checker;
|
||||
pub use checker::*;
|
||||
|
@ -25,7 +25,6 @@ pub use self::formatted::*;
|
||||
/// This module contains the macros for making errors easily.
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub use self::macros::*;
|
||||
|
||||
/// This module contains traits for making errors easily.
|
||||
pub mod traits;
|
||||
|
@ -194,4 +194,11 @@ create_messages!(
|
||||
msg: format!("Failed to write file.\nIO Error: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_read_environment_private_key {
|
||||
args: (error: impl Display),
|
||||
msg: format!("Failed to read private key from environment.\nIO Error: {error}"),
|
||||
help: Some("Pass in private key using `--private-key <PRIVATE-KEY>` or create a .env file with your private key information. See examples for formatting information.".to_string()),
|
||||
}
|
||||
);
|
||||
|
@ -74,7 +74,7 @@ create_messages!(
|
||||
@formatted
|
||||
imported_program_not_found {
|
||||
args: (main_program_name: impl Display, dependency_name: impl Display),
|
||||
msg: format!("`{main_program_name}` imports `{dependency_name}.aleo`, but `{dependency_name}.aleo` is not found in `program.json`."),
|
||||
msg: format!("`{main_program_name}` imports `{dependency_name}.aleo`, but `{dependency_name}.aleo` is not found in program manifest. Use `leo add --help` for more information on how to add a dependency."),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -348,4 +348,26 @@ create_messages!(
|
||||
msg: format!("Failed to update `program.json` from the provided file path {path} - {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
failed_to_deserialize_lock_file {
|
||||
args: (error: impl ErrorArg),
|
||||
msg: format!("Failed to deserialize `leo.lock` - {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_lock_file_formatting {
|
||||
args: (),
|
||||
msg: "Invalid `leo.lock` formatting.".to_string(),
|
||||
help: Some("Delete the lock file and rebuild the project".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
unimplemented_command {
|
||||
args: (command: impl Display),
|
||||
msg: format!("The `{command}` command is not implemented."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
);
|
||||
|
@ -335,4 +335,11 @@ create_messages!(
|
||||
msg: format!("Only external calls to `.aleo` programs are supported."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
cannot_define_external_record {
|
||||
args: (),
|
||||
msg: format!("Cannot create an external record. Records can only be created in the program that they are defined in."),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -200,7 +200,7 @@ create_messages!(
|
||||
msg: format!(
|
||||
"The type `{type_}` is not found in the current scope."
|
||||
),
|
||||
help: None,
|
||||
help: Some("If you are using an external type, make sure to preface with the program name. Ex: `credits.aleo/credits` instead of `credits`".to_string()),
|
||||
}
|
||||
|
||||
/// Attempted to access an invalid struct variable.
|
||||
@ -754,4 +754,18 @@ create_messages!(
|
||||
msg: format!("A program must have at least one transition function."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
cannot_define_external_struct {
|
||||
args: (struct_: impl Display),
|
||||
msg: format!("Cannot define external struct `{struct_}`"),
|
||||
help: Some("Copy the external definition of the struct into the current program, and then define without the `.aleo` extension.".to_string()),
|
||||
}
|
||||
|
||||
@formatted
|
||||
struct_definitions_dont_match {
|
||||
args: (struct_: impl Display, program_1: impl Display, program_2: impl Display),
|
||||
msg: format!("The definition for `{struct_}` in program `{program_1}.aleo` does not match the definition in program `{program_2}.aleo`"),
|
||||
help: Some("Check that the struct definition in the current program matches the definition in the imported program.".to_string()),
|
||||
}
|
||||
);
|
||||
|
@ -134,7 +134,7 @@ create_messages!(
|
||||
@formatted
|
||||
snarkvm_error_building_program_id {
|
||||
args: (),
|
||||
msg: format!("Snarkvm error building program id"),
|
||||
msg: "Snarkvm error building program id".to_string(),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -144,4 +144,11 @@ create_messages!(
|
||||
msg: format!("Failed to retrieve from endpoint `{endpoint}`. Error: {error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
build_file_does_not_exist {
|
||||
args: (path: impl Display),
|
||||
msg: format!("Compiled file at `{path}` does not exist, cannot compile parent."),
|
||||
help: Some("If you were using the `--non-recursive` flag, remove it and try again.".to_string()),
|
||||
}
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ program battleship.aleo {
|
||||
let board: u64 = verify.aleo/create_board(carrier, battleship, cruiser, destroyer);
|
||||
|
||||
// Initialize the board state record.
|
||||
let state: board_state = board.aleo/new_board_state(board, player);
|
||||
let state: board.aleo/board_state = board.aleo/new_board_state(board, player);
|
||||
|
||||
return state;
|
||||
}
|
||||
@ -46,8 +46,8 @@ program battleship.aleo {
|
||||
// The board record to start a game with.
|
||||
board: board.aleo/board_state.record,
|
||||
) -> (board.aleo/board_state.record, move.aleo/move.record) {
|
||||
let state: board_state = board.aleo/start_board(board);
|
||||
let dummy: move = move.aleo/start_game(board.player_2);
|
||||
let state: board.aleo/board_state = board.aleo/start_board(board);
|
||||
let dummy: move.aleo/move = move.aleo/start_game(board.player_2);
|
||||
|
||||
return (state, dummy);
|
||||
}
|
||||
@ -64,8 +64,8 @@ program battleship.aleo {
|
||||
assert_eq(board.player_1, move_start.player_2);
|
||||
assert_eq(board.player_2, move_start.player_1);
|
||||
|
||||
let state: board_state = board.aleo/start_board(board);
|
||||
let dummy: move = move.aleo/start_game(board.player_2);
|
||||
let state: board.aleo/board_state = board.aleo/start_board(board);
|
||||
let dummy: move.aleo/move = move.aleo/start_game(board.player_2);
|
||||
|
||||
return (state, dummy);
|
||||
}
|
||||
@ -89,15 +89,15 @@ program battleship.aleo {
|
||||
assert_eq(board.player_2, move_incoming.player_1);
|
||||
|
||||
// Play coordinate on own board. Will fail if not a valid move.
|
||||
let hit_or_miss: board_state = board.aleo/update_played_tiles(board, shoot);
|
||||
let hit_or_miss: board.aleo/board_state = board.aleo/update_played_tiles(board, shoot);
|
||||
|
||||
// Update own board with result of last shot.
|
||||
let next_board: board_state = board.aleo/update_hits_and_misses(hit_or_miss, move_incoming.prev_hit_or_miss);
|
||||
let next_board: board.aleo/board_state = board.aleo/update_hits_and_misses(hit_or_miss, move_incoming.prev_hit_or_miss);
|
||||
|
||||
// Assess whether incoming fire coordinate is a hit.
|
||||
let is_hit: u64 = move_incoming.incoming_fire_coordinate & board.ships;
|
||||
|
||||
let next_move: move = move.aleo/create_move(move_incoming, shoot, is_hit);
|
||||
let next_move: move.aleo/move = move.aleo/create_move(move_incoming, shoot, is_hit);
|
||||
|
||||
return (next_board, next_move);
|
||||
}
|
||||
|
414
leo/cli/cli.rs
414
leo/cli/cli.rs
@ -43,16 +43,16 @@ pub struct CLI {
|
||||
///Leo compiler and package manager
|
||||
#[derive(Parser, Debug)]
|
||||
enum Commands {
|
||||
#[clap(about = "Add a new dependency to the current package. Defaults to testnet3 network")]
|
||||
Add {
|
||||
#[clap(flatten)]
|
||||
command: Add,
|
||||
},
|
||||
#[clap(about = "Create a new Aleo account, sign and verify messages")]
|
||||
Account {
|
||||
#[clap(subcommand)]
|
||||
command: Account,
|
||||
},
|
||||
#[clap(about = "Add a new on-chain or local dependency to the current package.")]
|
||||
Add {
|
||||
#[clap(flatten)]
|
||||
command: Add,
|
||||
},
|
||||
#[clap(about = "Create a new Leo package in a new directory")]
|
||||
New {
|
||||
#[clap(flatten)]
|
||||
@ -63,16 +63,6 @@ enum Commands {
|
||||
#[clap(subcommand)]
|
||||
command: Example,
|
||||
},
|
||||
#[clap(about = "Compile the current package as a program")]
|
||||
Build {
|
||||
#[clap(flatten)]
|
||||
command: Build,
|
||||
},
|
||||
#[clap(about = "Clean the output directory")]
|
||||
Clean {
|
||||
#[clap(flatten)]
|
||||
command: Clean,
|
||||
},
|
||||
#[clap(about = "Run a program with input variables")]
|
||||
Run {
|
||||
#[clap(flatten)]
|
||||
@ -83,6 +73,22 @@ enum Commands {
|
||||
#[clap(flatten)]
|
||||
command: Execute,
|
||||
},
|
||||
#[clap(about = "Deploy a program")]
|
||||
Deploy {
|
||||
#[clap(flatten)]
|
||||
command: Deploy,
|
||||
},
|
||||
|
||||
#[clap(about = "Compile the current package as a program")]
|
||||
Build {
|
||||
#[clap(flatten)]
|
||||
command: Build,
|
||||
},
|
||||
#[clap(about = "Clean the output directory")]
|
||||
Clean {
|
||||
#[clap(flatten)]
|
||||
command: Clean,
|
||||
},
|
||||
#[clap(about = "Update the Leo CLI")]
|
||||
Update {
|
||||
#[clap(flatten)]
|
||||
@ -135,6 +141,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
|
||||
command.try_execute(context)
|
||||
}
|
||||
Commands::Clean { command } => command.try_execute(context),
|
||||
Commands::Deploy { command } => command.try_execute(context),
|
||||
Commands::Example { command } => command.try_execute(context),
|
||||
Commands::Run { command } => command.try_execute(context),
|
||||
Commands::Execute { command } => command.try_execute(context),
|
||||
@ -230,6 +237,80 @@ mod tests {
|
||||
// TODO: Clear tmp directory
|
||||
// std::fs::remove_dir_all(project_directory).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn relaxed_shadowing_run_test() {
|
||||
// Set current directory to temporary directory
|
||||
let temp_dir = temp_dir();
|
||||
let project_name = "outer";
|
||||
let project_directory = temp_dir.join(project_name);
|
||||
|
||||
// Remove it if it already exists
|
||||
if project_directory.exists() {
|
||||
std::fs::remove_dir_all(project_directory.clone()).unwrap();
|
||||
}
|
||||
|
||||
// Create file structure
|
||||
test_helpers::sample_shadowing_package(&temp_dir);
|
||||
|
||||
// Run program
|
||||
let run = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Run {
|
||||
command: crate::cli::commands::Run {
|
||||
name: "inner_1_main".to_string(),
|
||||
inputs: vec!["1u32".to_string(), "2u32".to_string()],
|
||||
compiler_options: Default::default(),
|
||||
file: None,
|
||||
},
|
||||
},
|
||||
path: Some(project_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
create_session_if_not_set_then(|_| {
|
||||
run_with_args(run).expect("Failed to execute `leo run`");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn relaxed_struct_shadowing_run_test() {
|
||||
// Set current directory to temporary directory
|
||||
let temp_dir = temp_dir();
|
||||
let project_name = "outer";
|
||||
let project_directory = temp_dir.join(project_name);
|
||||
|
||||
// Remove it if it already exists
|
||||
if project_directory.exists() {
|
||||
std::fs::remove_dir_all(project_directory.clone()).unwrap();
|
||||
}
|
||||
|
||||
// Create file structure
|
||||
test_helpers::sample_struct_shadowing_package(&temp_dir);
|
||||
|
||||
// Run program
|
||||
let run = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Run {
|
||||
command: crate::cli::commands::Run {
|
||||
name: "main".to_string(),
|
||||
inputs: vec!["1u32".to_string(), "2u32".to_string()],
|
||||
compiler_options: Default::default(),
|
||||
file: None,
|
||||
},
|
||||
},
|
||||
path: Some(project_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
create_session_if_not_set_then(|_| {
|
||||
run_with_args(run).expect("Failed to execute `leo run`");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -465,4 +546,307 @@ program child.aleo {
|
||||
run_with_args(add_parent_dependency).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn sample_shadowing_package(temp_dir: &Path) {
|
||||
let outer_directory = temp_dir.join("outer");
|
||||
let inner_1_directory = outer_directory.join("inner_1");
|
||||
let inner_2_directory = outer_directory.join("inner_2");
|
||||
|
||||
if outer_directory.exists() {
|
||||
std::fs::remove_dir_all(outer_directory.clone()).unwrap();
|
||||
}
|
||||
|
||||
// Create project file structure `outer/inner_1` and `outer/inner_2`
|
||||
let create_outer_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "outer".to_string() } },
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let create_inner_1_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_1".to_string() } },
|
||||
path: Some(inner_1_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let create_inner_2_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_2".to_string() } },
|
||||
path: Some(inner_2_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
// Add source files `outer/src/main.leo` and `outer/inner/src/main.leo`
|
||||
let outer_program = "import inner_1.aleo;
|
||||
import inner_2.aleo;
|
||||
program outer.aleo {
|
||||
|
||||
struct ex_struct {
|
||||
arg1: u32,
|
||||
arg2: u32,
|
||||
}
|
||||
|
||||
record inner_1_record {
|
||||
owner: address,
|
||||
arg1: u32,
|
||||
arg2: u32,
|
||||
arg3: u32,
|
||||
}
|
||||
|
||||
transition inner_1_main(public a: u32, b: u32) -> (inner_1.aleo/inner_1_record, inner_2.aleo/inner_1_record, inner_1_record) {
|
||||
let c: ex_struct = ex_struct {arg1: 1u32, arg2: 1u32};
|
||||
let rec_1:inner_1.aleo/inner_1_record = inner_1.aleo/inner_1_main(1u32,1u32, c);
|
||||
let rec_2:inner_2.aleo/inner_1_record = inner_2.aleo/inner_1_main(1u32,1u32);
|
||||
return (rec_1, rec_2, inner_1_record {owner: aleo14tnetva3xfvemqyg5ujzvr0qfcaxdanmgjx2wsuh2xrpvc03uc9s623ps7, arg1: 1u32, arg2: 1u32, arg3: 1u32});
|
||||
}
|
||||
}";
|
||||
let inner_1_program = "program inner_1.aleo {
|
||||
mapping inner_1_mapping: u32 => u32;
|
||||
record inner_1_record {
|
||||
owner: address,
|
||||
val: u32,
|
||||
}
|
||||
struct ex_struct {
|
||||
arg1: u32,
|
||||
arg2: u32,
|
||||
}
|
||||
transition inner_1_main(public a: u32, b: u32, c: ex_struct) -> inner_1_record {
|
||||
return inner_1_record {
|
||||
owner: self.caller,
|
||||
val: c.arg1,
|
||||
};
|
||||
}
|
||||
}";
|
||||
let inner_2_program = "program inner_2.aleo {
|
||||
mapping inner_2_mapping: u32 => u32;
|
||||
record inner_1_record {
|
||||
owner: address,
|
||||
val: u32,
|
||||
}
|
||||
transition inner_1_main(public a: u32, b: u32) -> inner_1_record {
|
||||
let c: u32 = a + b;
|
||||
return inner_1_record {
|
||||
owner: self.caller,
|
||||
val: a,
|
||||
};
|
||||
}
|
||||
}";
|
||||
// Add dependencies `outer/program.json`
|
||||
let add_outer_dependency_1 = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Add {
|
||||
command: Add {
|
||||
name: "inner_1".to_string(),
|
||||
local: Some(inner_1_directory.clone()),
|
||||
network: "testnet3".to_string(),
|
||||
},
|
||||
},
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let add_outer_dependency_2 = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Add {
|
||||
command: Add {
|
||||
name: "inner_2".to_string(),
|
||||
local: Some(inner_2_directory.clone()),
|
||||
network: "testnet3".to_string(),
|
||||
},
|
||||
},
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
// Execute all commands
|
||||
create_session_if_not_set_then(|_| {
|
||||
// Create projects
|
||||
run_with_args(create_outer_project).unwrap();
|
||||
run_with_args(create_inner_1_project).unwrap();
|
||||
run_with_args(create_inner_2_project).unwrap();
|
||||
|
||||
// Write files
|
||||
std::fs::write(outer_directory.join("src").join("main.leo"), outer_program).unwrap();
|
||||
std::fs::write(inner_1_directory.join("src").join("main.leo"), inner_1_program).unwrap();
|
||||
std::fs::write(inner_2_directory.join("src").join("main.leo"), inner_2_program).unwrap();
|
||||
|
||||
// Add dependencies
|
||||
run_with_args(add_outer_dependency_1).unwrap();
|
||||
run_with_args(add_outer_dependency_2).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn sample_struct_shadowing_package(temp_dir: &Path) {
|
||||
let outer_directory = temp_dir.join("outer");
|
||||
let inner_1_directory = outer_directory.join("inner_1");
|
||||
let inner_2_directory = outer_directory.join("inner_2");
|
||||
|
||||
if outer_directory.exists() {
|
||||
std::fs::remove_dir_all(outer_directory.clone()).unwrap();
|
||||
}
|
||||
|
||||
// Create project file structure `outer/inner_1` and `outer/inner_2`
|
||||
let create_outer_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "outer".to_string() } },
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let create_inner_1_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_1".to_string() } },
|
||||
path: Some(inner_1_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let create_inner_2_project = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::New { command: New { name: "inner_2".to_string() } },
|
||||
path: Some(inner_2_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
// Add source files `outer/src/main.leo` and `outer/inner/src/main.leo`
|
||||
let outer_program = "
|
||||
import inner_1.aleo;
|
||||
import inner_2.aleo;
|
||||
program outer.aleo {
|
||||
struct Foo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: Boo,
|
||||
}
|
||||
struct Boo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
struct Goo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
}
|
||||
record Hello {
|
||||
owner: address,
|
||||
a: u32,
|
||||
}
|
||||
transition main(public a: u32, b: u32) -> (inner_2.aleo/Yoo, Hello) {
|
||||
let d: Foo = inner_1.aleo/main(1u32,1u32);
|
||||
let e: u32 = inner_1.aleo/main_2(Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}});
|
||||
let f: Boo = Boo {a:1u32, b:1u32};
|
||||
let g: Foo = inner_2.aleo/main(1u32, 1u32);
|
||||
inner_2.aleo/Yo_Consumer(inner_2.aleo/Yo());
|
||||
let h: inner_2.aleo/Yoo = inner_2.aleo/Yo();
|
||||
let i: Goo = inner_2.aleo/Goo_creator();
|
||||
let j: Hello = Hello {owner: self.signer, a:1u32};
|
||||
|
||||
return (h, j);
|
||||
}
|
||||
}
|
||||
";
|
||||
let inner_1_program = "program inner_1.aleo {
|
||||
struct Foo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: Boo,
|
||||
}
|
||||
struct Boo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
transition main(public a: u32, b: u32) -> Foo {
|
||||
return Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}};
|
||||
}
|
||||
transition main_2(a:Foo)->u32{
|
||||
return a.a;
|
||||
}
|
||||
}";
|
||||
let inner_2_program = "program inner_2.aleo {
|
||||
struct Foo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: Boo,
|
||||
}
|
||||
struct Boo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
record Yoo {
|
||||
owner: address,
|
||||
a: u32,
|
||||
}
|
||||
struct Goo {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
}
|
||||
transition main(public a: u32, b: u32) -> Foo {
|
||||
return Foo {a: a, b: b, c: Boo {a:1u32, b:1u32}};
|
||||
}
|
||||
transition Yo()-> Yoo {
|
||||
return Yoo {owner: self.signer, a:1u32};
|
||||
}
|
||||
transition Yo_Consumer(a: Yoo)->u32 {
|
||||
return a.a;
|
||||
}
|
||||
transition Goo_creator() -> Goo {
|
||||
return Goo {a:100u32, b:1u32, c:1u32};
|
||||
}
|
||||
}";
|
||||
// Add dependencies `outer/program.json`
|
||||
let add_outer_dependency_1 = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Add {
|
||||
command: Add {
|
||||
name: "inner_1".to_string(),
|
||||
local: Some(inner_1_directory.clone()),
|
||||
network: "testnet3".to_string(),
|
||||
},
|
||||
},
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
let add_outer_dependency_2 = CLI {
|
||||
debug: false,
|
||||
quiet: false,
|
||||
command: Commands::Add {
|
||||
command: Add {
|
||||
name: "inner_2".to_string(),
|
||||
local: Some(inner_2_directory.clone()),
|
||||
network: "testnet3".to_string(),
|
||||
},
|
||||
},
|
||||
path: Some(outer_directory.clone()),
|
||||
home: None,
|
||||
};
|
||||
|
||||
// Execute all commands
|
||||
create_session_if_not_set_then(|_| {
|
||||
// Create projects
|
||||
run_with_args(create_outer_project).unwrap();
|
||||
run_with_args(create_inner_1_project).unwrap();
|
||||
run_with_args(create_inner_2_project).unwrap();
|
||||
|
||||
// Write files
|
||||
std::fs::write(outer_directory.join("src").join("main.leo"), outer_program).unwrap();
|
||||
std::fs::write(inner_1_directory.join("src").join("main.leo"), inner_1_program).unwrap();
|
||||
std::fs::write(inner_2_directory.join("src").join("main.leo"), inner_2_program).unwrap();
|
||||
|
||||
// Add dependencies
|
||||
run_with_args(add_outer_dependency_1).unwrap();
|
||||
run_with_args(add_outer_dependency_2).unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ impl Command for Build {
|
||||
|
||||
// Retrieve all local dependencies in post order
|
||||
let main_sym = Symbol::intern(&program_id.name().to_string());
|
||||
let mut retriever = Retriever::new(main_sym, &package_path, &home_path)
|
||||
let mut retriever = Retriever::new(main_sym, &package_path, &home_path, self.options.endpoint.clone())
|
||||
.map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
let mut local_dependencies =
|
||||
retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?;
|
||||
@ -113,39 +113,44 @@ impl Command for Build {
|
||||
// Push the main program at the end of the list to be compiled after all of its dependencies have been processed
|
||||
local_dependencies.push(main_sym);
|
||||
|
||||
// Recursive build will recursively compile all local dependencies. Can disable to save compile time.
|
||||
let recursive_build = !self.options.non_recursive;
|
||||
|
||||
// Loop through all local dependencies and compile them in order
|
||||
for dependency in local_dependencies.into_iter() {
|
||||
// Get path to the local project
|
||||
let (local_path, stubs) = retriever.prepare_local(dependency)?;
|
||||
if recursive_build || dependency == main_sym {
|
||||
// Get path to the local project
|
||||
let (local_path, stubs) = retriever.prepare_local(dependency)?;
|
||||
|
||||
// Create the outputs directory.
|
||||
let local_outputs_directory = OutputsDirectory::create(&local_path)?;
|
||||
// Create the outputs directory.
|
||||
let local_outputs_directory = OutputsDirectory::create(&local_path)?;
|
||||
|
||||
// Open the build directory.
|
||||
let local_build_directory = BuildDirectory::create(&local_path)?;
|
||||
// Open the build directory.
|
||||
let local_build_directory = BuildDirectory::create(&local_path)?;
|
||||
|
||||
// Fetch paths to all .leo files in the source directory.
|
||||
let local_source_files = SourceDirectory::files(&local_path)?;
|
||||
// Fetch paths to all .leo files in the source directory.
|
||||
let local_source_files = SourceDirectory::files(&local_path)?;
|
||||
|
||||
// Check the source files.
|
||||
SourceDirectory::check_files(&local_source_files)?;
|
||||
// Check the source files.
|
||||
SourceDirectory::check_files(&local_source_files)?;
|
||||
|
||||
// Compile all .leo files into .aleo files.
|
||||
for file_path in local_source_files {
|
||||
compile_leo_file(
|
||||
file_path,
|
||||
&ProgramID::<Testnet3>::try_from(format!("{}.aleo", dependency))
|
||||
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
||||
&local_outputs_directory,
|
||||
&local_build_directory,
|
||||
&handler,
|
||||
self.options.clone(),
|
||||
stubs.clone(),
|
||||
)?;
|
||||
// Compile all .leo files into .aleo files.
|
||||
for file_path in local_source_files {
|
||||
compile_leo_file(
|
||||
file_path,
|
||||
&ProgramID::<Testnet3>::try_from(format!("{}.aleo", dependency))
|
||||
.map_err(|_| UtilError::snarkvm_error_building_program_id(Default::default()))?,
|
||||
&local_outputs_directory,
|
||||
&local_build_directory,
|
||||
&handler,
|
||||
self.options.clone(),
|
||||
stubs.clone(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Writes `leo.lock` as well as caches objects (when target is an intermediate dependency)
|
||||
retriever.process_local(dependency)?;
|
||||
retriever.process_local(dependency, recursive_build)?;
|
||||
}
|
||||
|
||||
// `Package::open` checks that the build directory and that `main.aleo` and all imported files are well-formed.
|
||||
|
@ -15,10 +15,26 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
//use snarkos_cli::commands::{Deploy as SnarkOSDeploy, Developer};
|
||||
|
||||
/// Deploys an Aleo program.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Deploy;
|
||||
pub struct Deploy {
|
||||
#[clap(long, help = "Custom priority fee in microcredits", default_value = "1000000")]
|
||||
pub(crate) priority_fee: String,
|
||||
#[clap(long, help = "Custom query endpoint", default_value = "http://api.explorer.aleo.org/v1")]
|
||||
pub(crate) endpoint: String,
|
||||
#[clap(long, help = "Custom network", default_value = "testnet3")]
|
||||
pub(crate) network: String,
|
||||
#[clap(long, help = "Custom private key")]
|
||||
pub(crate) private_key: Option<String>,
|
||||
#[clap(long, help = "Disables building of the project before deployment", default_value = "false")]
|
||||
pub(crate) no_build: bool,
|
||||
#[clap(long, help = "Disables recursive deployment of dependencies", default_value = "false")]
|
||||
pub(crate) non_recursive: bool,
|
||||
#[clap(long, help = "Custom wait gap between consecutive deployments", default_value = "12")]
|
||||
pub(crate) wait_gap: u64,
|
||||
}
|
||||
|
||||
impl Command for Deploy {
|
||||
type Input = ();
|
||||
@ -28,30 +44,62 @@ impl Command for Deploy {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _: Context) -> Result<Self::Input> {
|
||||
fn prelude(&self, context: Context) -> Result<Self::Input> {
|
||||
if !self.no_build {
|
||||
(Build { options: BuildOptions::default() }).execute(context)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Open the Leo build/ directory
|
||||
let path = context.dir()?;
|
||||
let build_directory = BuildDirectory::open(&path).map_err(|_| CliError::needs_leo_build())?;
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// // Get the program name
|
||||
// let project_name = context.open_manifest()?.program_id().to_string();
|
||||
//
|
||||
// // Get the private key
|
||||
// let mut private_key = self.private_key;
|
||||
// if private_key.is_none() {
|
||||
// private_key =
|
||||
// Some(dotenv_private_key().map_err(CliError::failed_to_read_environment_private_key)?.to_string());
|
||||
// }
|
||||
//
|
||||
// let mut all_paths: Vec<(String, PathBuf)> = Vec::new();
|
||||
//
|
||||
// // Extract post-ordered list of local dependencies' paths from `leo.lock`
|
||||
// if !self.non_recursive {
|
||||
// all_paths = context.local_dependency_paths()?;
|
||||
// }
|
||||
//
|
||||
// // Add the parent program to be deployed last
|
||||
// all_paths.push((project_name, context.dir()?.join("build")));
|
||||
//
|
||||
// for (index, (name, path)) in all_paths.iter().enumerate() {
|
||||
// // Set deploy arguments
|
||||
// let deploy = SnarkOSDeploy::try_parse_from([
|
||||
// "snarkos",
|
||||
// "--private-key",
|
||||
// private_key.as_ref().unwrap(),
|
||||
// "--query",
|
||||
// self.endpoint.as_str(),
|
||||
// "--priority-fee",
|
||||
// self.priority_fee.as_str(),
|
||||
// "--path",
|
||||
// path.to_str().unwrap(),
|
||||
// "--broadcast",
|
||||
// format!("{}/{}/transaction/broadcast", self.endpoint, self.network).as_str(),
|
||||
// &name,
|
||||
// ])
|
||||
// .unwrap();
|
||||
//
|
||||
// // Deploy program
|
||||
// Developer::Deploy(deploy).parse().map_err(CliError::failed_to_execute_deploy)?;
|
||||
//
|
||||
// // Sleep for `wait_gap` seconds.
|
||||
// // This helps avoid parents from being serialized before children.
|
||||
// if index < all_paths.len() - 1 {
|
||||
// std::thread::sleep(std::time::Duration::from_secs(self.wait_gap));
|
||||
// }
|
||||
// }
|
||||
|
||||
// Change the cwd to the Leo build/ directory to deploy aleo files.
|
||||
std::env::set_current_dir(&build_directory)
|
||||
.map_err(|err| PackageError::failed_to_set_cwd(build_directory.display(), err))?;
|
||||
|
||||
// Unset the Leo panic hook.
|
||||
let _ = std::panic::take_hook();
|
||||
|
||||
// Call the `node` command.
|
||||
println!();
|
||||
let command = SnarkVMDeploy::try_parse_from([ALEO_CLI_COMMAND]).map_err(CliError::failed_to_parse_aleo_node)?;
|
||||
let res = command.parse().map_err(CliError::failed_to_execute_aleo_node)?;
|
||||
|
||||
// Log the output of the `node` command.
|
||||
tracing::info!("{}", res);
|
||||
|
||||
Ok(())
|
||||
Err(PackageError::unimplemented_command("leo deploy").into())
|
||||
}
|
||||
}
|
||||
|
@ -15,31 +15,29 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use clap::Parser;
|
||||
// use snarkos_cli::commands::{Developer, Execute as SnarkOSExecute};
|
||||
use snarkvm::{cli::Execute as SnarkVMExecute, prelude::Parser as SnarkVMParser};
|
||||
|
||||
/// Build, Prove and Run Leo program with inputs
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Execute {
|
||||
#[clap(name = "NAME", help = "The name of the program to execute.", default_value = "main")]
|
||||
#[clap(name = "NAME", help = "The name of the function to execute.", default_value = "main")]
|
||||
name: String,
|
||||
|
||||
#[clap(name = "INPUTS", help = "The inputs to the program.")]
|
||||
#[clap(name = "INPUTS", help = "The inputs to the program. If none are provided, the input file is used.")]
|
||||
inputs: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
name = "ENDPOINT",
|
||||
help = "The specified network endpoint.",
|
||||
default_value = "https://api.explorer.aleo.org/v1",
|
||||
long
|
||||
)]
|
||||
endpoint: String,
|
||||
|
||||
#[clap(long, help = "Execute the transition on chain", default_value = "false")]
|
||||
broadcast: bool,
|
||||
#[clap(long, help = "Custom priority fee in microcredits", default_value = "1000000")]
|
||||
priority_fee: String,
|
||||
#[clap(long, help = "Custom network", default_value = "testnet3")]
|
||||
network: String,
|
||||
#[clap(long, help = "Custom private key")]
|
||||
private_key: Option<String>,
|
||||
#[arg(short, long, help = "The inputs to the program, from a file. Overrides the INPUTS argument.")]
|
||||
file: Option<String>,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub(crate) compiler_options: BuildOptions,
|
||||
compiler_options: BuildOptions,
|
||||
}
|
||||
|
||||
impl Command for Execute {
|
||||
@ -54,7 +52,51 @@ impl Command for Execute {
|
||||
(Build { options: self.compiler_options.clone() }).execute(context)
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
fn apply(self, context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||
// If the `broadcast` flag is set, then broadcast the transaction.
|
||||
if self.broadcast {
|
||||
// // Get the program name
|
||||
// let project_name = context.open_manifest()?.program_id().to_string();
|
||||
//
|
||||
// // Get the private key
|
||||
// let mut private_key = self.private_key;
|
||||
// if private_key.is_none() {
|
||||
// private_key =
|
||||
// Some(dotenv_private_key().map_err(CliError::failed_to_read_environment_private_key)?.to_string());
|
||||
// }
|
||||
//
|
||||
// // Execute program
|
||||
// Developer::Execute(
|
||||
// SnarkOSExecute::try_parse_from(
|
||||
// [
|
||||
// vec![
|
||||
// "snarkos",
|
||||
// "--private-key",
|
||||
// private_key.as_ref().unwrap(),
|
||||
// "--query",
|
||||
// self.compiler_options.endpoint.as_str(),
|
||||
// "--priority-fee",
|
||||
// self.priority_fee.as_str(),
|
||||
// "--broadcast",
|
||||
// format!("{}/{}/transaction/broadcast", self.compiler_options.endpoint, self.network)
|
||||
// .as_str(),
|
||||
// project_name.as_str(),
|
||||
// &self.name,
|
||||
// ],
|
||||
// self.inputs.iter().map(|input| input.as_str()).collect(),
|
||||
// ]
|
||||
// .concat(),
|
||||
// )
|
||||
// .unwrap(),
|
||||
// )
|
||||
// .parse()
|
||||
// .map_err(CliError::failed_to_execute_deploy)?;
|
||||
|
||||
return Err(PackageError::unimplemented_command("leo execute --broadcast").into());
|
||||
}
|
||||
|
||||
// If input values are provided, then run the program with those inputs.
|
||||
// Otherwise, use the input file.
|
||||
let mut inputs = self.inputs;
|
||||
|
||||
// Compose the `execute` command.
|
||||
@ -93,7 +135,7 @@ impl Command for Execute {
|
||||
|
||||
// Add the endpoint to the arguments.
|
||||
arguments.push(String::from("--endpoint"));
|
||||
arguments.push(self.endpoint);
|
||||
arguments.push(self.compiler_options.endpoint.clone());
|
||||
|
||||
// Open the Leo build/ directory
|
||||
let path = context.dir()?;
|
||||
|
@ -26,15 +26,15 @@ pub use build::Build;
|
||||
pub mod clean;
|
||||
pub use clean::Clean;
|
||||
|
||||
pub mod deploy;
|
||||
pub use deploy::Deploy;
|
||||
|
||||
pub mod example;
|
||||
pub use example::Example;
|
||||
|
||||
pub mod execute;
|
||||
pub use execute::Execute;
|
||||
|
||||
// pub mod deploy;
|
||||
// pub use deploy::Deploy;
|
||||
|
||||
pub mod new;
|
||||
pub use new::New;
|
||||
|
||||
@ -122,6 +122,14 @@ pub trait Command {
|
||||
/// require Build command output as their input.
|
||||
#[derive(Parser, Clone, Debug, Default)]
|
||||
pub struct BuildOptions {
|
||||
#[clap(
|
||||
long,
|
||||
help = "Endpoint to retrieve on-chain dependencies from.",
|
||||
default_value = "http://api.explorer.aleo.org/v1"
|
||||
)]
|
||||
pub endpoint: String,
|
||||
#[clap(long, help = "Does not recursively compile dependencies.")]
|
||||
pub non_recursive: bool,
|
||||
#[clap(long, help = "Enables offline mode.")]
|
||||
pub offline: bool,
|
||||
#[clap(long, help = "Enable spans in AST snapshots.")]
|
||||
|
@ -22,6 +22,8 @@ use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};
|
||||
use snarkvm::file::Manifest;
|
||||
|
||||
use aleo_std::aleo_dir;
|
||||
use indexmap::IndexMap;
|
||||
use retriever::LockFileEntry;
|
||||
use std::{
|
||||
env::current_dir,
|
||||
fs::File,
|
||||
@ -106,4 +108,33 @@ impl Context {
|
||||
// Get package name from program id.
|
||||
Ok(manifest)
|
||||
}
|
||||
|
||||
/// Returns a post ordering of the local dependencies.
|
||||
/// Found by reading the lock file `leo.lock`.
|
||||
pub fn local_dependency_paths(&self) -> Result<Vec<(String, PathBuf)>> {
|
||||
let path = self.dir()?;
|
||||
let lock_path = path.join("leo.lock");
|
||||
|
||||
// If there is no lock file can assume no local dependencies
|
||||
if !lock_path.exists() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let contents = std::fs::read_to_string(&lock_path)
|
||||
.map_err(|err| PackageError::failed_to_read_file(lock_path.to_str().unwrap(), err))?;
|
||||
|
||||
let entry_map: IndexMap<String, Vec<LockFileEntry>> =
|
||||
toml::from_str(&contents).map_err(PackageError::failed_to_deserialize_lock_file)?;
|
||||
|
||||
let lock_entries = entry_map.get("package").ok_or_else(PackageError::invalid_lock_file_formatting)?;
|
||||
|
||||
let list: Vec<(String, PathBuf)> = lock_entries
|
||||
.iter()
|
||||
.filter_map(|entry| {
|
||||
entry.path().map(|local_path| (entry.name().to_string(), local_path.clone().join("build")))
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ default-features = false
|
||||
[dependencies.snarkvm]
|
||||
workspace = true
|
||||
|
||||
#[dependencies.snarkos-cli]
|
||||
#version = "2.2.4"
|
||||
|
||||
[dependencies.leo-errors]
|
||||
path = "../../errors"
|
||||
version = "=1.10.0"
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: ced2082a8e348b1aa0808f4c72fa4fb4ab5fc664e573e33a203f2683879dfeca
|
||||
type_checked_symbol_table: a0dfc2822cd2ba34228b9388c5f8f05f5ff5add4283a622c3615093172118f8f
|
||||
unrolled_symbol_table: a0dfc2822cd2ba34228b9388c5f8f05f5ff5add4283a622c3615093172118f8f
|
||||
- - initial_symbol_table: 2ee2a99efeb3473ccec80415106122bfa9a87565247ed9b8032896ec756e33aa
|
||||
type_checked_symbol_table: c1619490816ec0d56d77600e667acdb7b4577b32084cf542fcdc1a802d7a972b
|
||||
unrolled_symbol_table: c1619490816ec0d56d77600e667acdb7b4577b32084cf542fcdc1a802d7a972b
|
||||
initial_ast: 94d3242e748619d667e5896f7ad3988dda45250b368ce2486c33cf6f1c55b638
|
||||
unrolled_ast: 94d3242e748619d667e5896f7ad3988dda45250b368ce2486c33cf6f1c55b638
|
||||
ssa_ast: db3e09758f82feca118021d2bee6d59052d672d49f417c27e3b0c05d88002a15
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: af38ae3d646149a4d9313a419619ad336e2483d6e11877216ab2076dfff872ac
|
||||
type_checked_symbol_table: 489037ec216d778e85678b6c9ddd7c3ed22e40d5481c7eda82b732dcff1f27cf
|
||||
unrolled_symbol_table: 489037ec216d778e85678b6c9ddd7c3ed22e40d5481c7eda82b732dcff1f27cf
|
||||
- - initial_symbol_table: 7f932b8d44e0a087c6da5750a6d6caebe3701863c0d179297cfb44fc68113163
|
||||
type_checked_symbol_table: 2bc79159a5bee87aecb4b652b908988bfc8922ea41269afe0dffd7fe55ffccda
|
||||
unrolled_symbol_table: 2bc79159a5bee87aecb4b652b908988bfc8922ea41269afe0dffd7fe55ffccda
|
||||
initial_ast: 8cb5c760709498b96a56ea62b25d3c28b22bf0484298831b23cd89a3570c63c3
|
||||
unrolled_ast: 8cb5c760709498b96a56ea62b25d3c28b22bf0484298831b23cd89a3570c63c3
|
||||
ssa_ast: 54a1e0dc85a8262b757539c8e65704ebe4666f121081732d9a8ed3381c5bef34
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: b665474dcaa4c7a4b2eb7a513f4cff8ba3b673a65465db206b134799acd0bd93
|
||||
type_checked_symbol_table: f385833c35da9d545935068b126557a8bfe7a03da8278004ad0c60286ed7ec46
|
||||
unrolled_symbol_table: f385833c35da9d545935068b126557a8bfe7a03da8278004ad0c60286ed7ec46
|
||||
- - initial_symbol_table: e0182bdd45dcbb1862e12e209da9b2fb8227c78b37bf915e37f00208557c9b18
|
||||
type_checked_symbol_table: 9031de27b62db9f0c3f3ed4fb03211263039a5bb88fa67e6bd6ee55396d946f9
|
||||
unrolled_symbol_table: 9031de27b62db9f0c3f3ed4fb03211263039a5bb88fa67e6bd6ee55396d946f9
|
||||
initial_ast: 10650ea9835265f168c13b09658eadd2b33b4eca35826b56bdca6be930c5ef53
|
||||
unrolled_ast: 10650ea9835265f168c13b09658eadd2b33b4eca35826b56bdca6be930c5ef53
|
||||
ssa_ast: b103df8661413a11492f1bf0d7e0e322e652f38055875bdb51026bda792ec8b3
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: b665474dcaa4c7a4b2eb7a513f4cff8ba3b673a65465db206b134799acd0bd93
|
||||
type_checked_symbol_table: f5626319ada04af53a186ac6d1bfef2fd7cd3a16890ea8cc4000e4abd4be2335
|
||||
unrolled_symbol_table: f5626319ada04af53a186ac6d1bfef2fd7cd3a16890ea8cc4000e4abd4be2335
|
||||
- - initial_symbol_table: e0182bdd45dcbb1862e12e209da9b2fb8227c78b37bf915e37f00208557c9b18
|
||||
type_checked_symbol_table: 6cb5b5abdfc48c9e6f755f97947504a8bdc2837ffbf708b0c12f5c38e52ca55b
|
||||
unrolled_symbol_table: 6cb5b5abdfc48c9e6f755f97947504a8bdc2837ffbf708b0c12f5c38e52ca55b
|
||||
initial_ast: 4b616fbbbf52577b25e69eb1b95915dd9b9ae0da10520f3edd913b9aeeae93fd
|
||||
unrolled_ast: 4b616fbbbf52577b25e69eb1b95915dd9b9ae0da10520f3edd913b9aeeae93fd
|
||||
ssa_ast: 94c32c4de57d425b18ec80921bacbbe66ae2eb8a813ade87b9e1852e01ce38d3
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: e4ceb61c69bd6ea4bc6189b0e05d050b6ce9ab15b321561f9a0d9bc3f4b076d6
|
||||
type_checked_symbol_table: 39b6a4995fc09260e0d1ecd5c8f6a7855a4f97a899bfd3498f7c611e16fbd952
|
||||
unrolled_symbol_table: dc9b52633c15f99daa99e8764fe57e898cb25a34e9a17c800eefcd6d5e0bab0a
|
||||
- - initial_symbol_table: 3742aee96e76bb3d7d05a2f040bb4e84fa92268b522f537f91b6b74e1bf8754b
|
||||
type_checked_symbol_table: e4097f4f784b48ea876a7d7278c96bc81f51a90c70f81d215fa490eca8ca5311
|
||||
unrolled_symbol_table: 60258c0c9cc5cd4935f5b8418ddbe251a9ece726e47dc6adb386747569b3c2fc
|
||||
initial_ast: 3d649cf2f604480c50b5ff669bf54750f77e81f889a3998555cc71689390485c
|
||||
unrolled_ast: 7ede4b449bb5d6f8017baae359e49a939f98fc956351a73c72049d8a6cfb9f96
|
||||
ssa_ast: 17ae84d03fb6b02573a98d6fe13a5237a50bd48a107d947c29dfd5025003ab96
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 5ac639a39bc707c8427d221252a15a00d76ef155a5a2f7770287dfffc5045cc3
|
||||
type_checked_symbol_table: 10d6e256f34841581c8a9ea58dd3536aed5870e2c12364106aaa51697966426e
|
||||
unrolled_symbol_table: 10d6e256f34841581c8a9ea58dd3536aed5870e2c12364106aaa51697966426e
|
||||
- - initial_symbol_table: f0c558fe33905e4a538c4b8c1778c51ccda937535c4fa06ffc7d83ae08f7b2cb
|
||||
type_checked_symbol_table: d34d710ad8077f01ff2d8f4bdcc1328f2aa579651f2ebd3f00280f351024ebd2
|
||||
unrolled_symbol_table: d34d710ad8077f01ff2d8f4bdcc1328f2aa579651f2ebd3f00280f351024ebd2
|
||||
initial_ast: 32276ab6a1dc1aab9f7c473112e6672410ee24cc6161566deb1e4602658b4277
|
||||
unrolled_ast: 32276ab6a1dc1aab9f7c473112e6672410ee24cc6161566deb1e4602658b4277
|
||||
ssa_ast: 4e948dd99feb72930b8ec3a14c0dba9fe02af16ed798b858ca5247cdf7fa4527
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 3eb83061a2a79055bbc0123f4f779f50c6ad3c6336ad697057e3cfbe2fef6bd6
|
||||
type_checked_symbol_table: ada5f23ac25bb1d9459045c27095fce0e36e746d84ca57cd7499c322773aa334
|
||||
unrolled_symbol_table: ada5f23ac25bb1d9459045c27095fce0e36e746d84ca57cd7499c322773aa334
|
||||
initial_ast: fb686c9a0b088dbf94c5b9acb172d03020054d3e04ddae20c18712058c904871
|
||||
unrolled_ast: fb686c9a0b088dbf94c5b9acb172d03020054d3e04ddae20c18712058c904871
|
||||
ssa_ast: ddbaafa6458cbdb1aef181b82f983b14bdeb6d7fa897c802c6014dbd2ffb7677
|
||||
flattened_ast: f0d3ed7e4fe70d7dd546aea9f68d2384fc06ad0d926357da8e317209b60c79f9
|
||||
destructured_ast: 8365e9db0d3aa9d9d42d47606a4dd6b519e358ebaceef0cf609345bf7676e26f
|
||||
inlined_ast: 8365e9db0d3aa9d9d42d47606a4dd6b519e358ebaceef0cf609345bf7676e26f
|
||||
dce_ast: 8365e9db0d3aa9d9d42d47606a4dd6b519e358ebaceef0cf609345bf7676e26f
|
||||
- - initial_symbol_table: 0a9e39c80f4a7f4cac48e8fa673aec1a25fb39998ad02d690a0922bdbf7c91a5
|
||||
type_checked_symbol_table: fcace63f105343adf3ce1f8d99a70762e83a99e81d6d9a366ec7e9a7bfcbbb96
|
||||
unrolled_symbol_table: fcace63f105343adf3ce1f8d99a70762e83a99e81d6d9a366ec7e9a7bfcbbb96
|
||||
initial_ast: ed44f2e8674bc083238a3e55c224e862583cc2118f7032194dd9f866937f6e11
|
||||
unrolled_ast: ed44f2e8674bc083238a3e55c224e862583cc2118f7032194dd9f866937f6e11
|
||||
ssa_ast: cace7d8d010a0387e087f70d50dda22dd9219f10e7e93f4c5b8de4afd2b7abfe
|
||||
flattened_ast: 00d9a1361c7f00b01be1856f385ccb2ce2864a33d17f01cde91b83ba527cf663
|
||||
destructured_ast: 190079c0017bf93950821145acf9f999dd7e8f9cb1a5267b22aefa3c08dd002d
|
||||
inlined_ast: 190079c0017bf93950821145acf9f999dd7e8f9cb1a5267b22aefa3c08dd002d
|
||||
dce_ast: 190079c0017bf93950821145acf9f999dd7e8f9cb1a5267b22aefa3c08dd002d
|
||||
bytecode: a3539a0515c22f4ec653aa601063d7a414db833dc25273cee463985b052b72bc
|
||||
warnings: ""
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 01523703092d96be1ea46237d2ad870b68f0f8ef7fa79682ac4f1e5ea7017902
|
||||
type_checked_symbol_table: 3ea7b23e139b9addd88767afc9fb5e38e758562e065d1207177bc809992ac5e4
|
||||
unrolled_symbol_table: 3ea7b23e139b9addd88767afc9fb5e38e758562e065d1207177bc809992ac5e4
|
||||
- - initial_symbol_table: 513000ef5b6588b18b4e9307c998bdac2d0eaf3c0fbe8f972df99531d10fb990
|
||||
type_checked_symbol_table: 87970aa8e3bdb5c78b6316f4b6ce58036b334f72316b38e89f53ea0fa2cdc883
|
||||
unrolled_symbol_table: 87970aa8e3bdb5c78b6316f4b6ce58036b334f72316b38e89f53ea0fa2cdc883
|
||||
initial_ast: 031c8fde01e7664264477a68836b02a1509461bb352940221d35f62f51dcfce2
|
||||
unrolled_ast: 031c8fde01e7664264477a68836b02a1509461bb352940221d35f62f51dcfce2
|
||||
ssa_ast: 7a81bde21f8f85449b1ea0620e9feb46ca294f6d0c5dab6bdf6537bca42f1a26
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 95e740d972367a1daf68d1869ee407e5eb1f35dd0fe46daa7ce71caaeb37fe5b
|
||||
type_checked_symbol_table: e99438533ef3c0e9ecc457e1f73a0a18f1be7c92b9059a928c219a0977e406a4
|
||||
unrolled_symbol_table: e99438533ef3c0e9ecc457e1f73a0a18f1be7c92b9059a928c219a0977e406a4
|
||||
- - initial_symbol_table: 78fdfbc136a07b9056e6365495b010543217aae651dfa5b4991024873ba0396b
|
||||
type_checked_symbol_table: 820e08769c49cac44545850f7756291c7e7181f273a63f16a0ce4892e3c45a28
|
||||
unrolled_symbol_table: 820e08769c49cac44545850f7756291c7e7181f273a63f16a0ce4892e3c45a28
|
||||
initial_ast: 102d78cfa8f14fdfcb39e6ccbccbc78820acef97645800ffc84931f9b82e9f5d
|
||||
unrolled_ast: 102d78cfa8f14fdfcb39e6ccbccbc78820acef97645800ffc84931f9b82e9f5d
|
||||
ssa_ast: a09ab12ef7f9790e9a1725c1b2dc86d65564b489d1e685b380a28f9bbcb33b6a
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 002a658ff3a2db38eb21e316458d2473313bbe50f2b4a7cd4aa6e04444c2ed3c
|
||||
type_checked_symbol_table: e6cbe752fa16e7a820685d02f654c97c2ccf509f7bb3287ea7060017bda0a139
|
||||
unrolled_symbol_table: e6cbe752fa16e7a820685d02f654c97c2ccf509f7bb3287ea7060017bda0a139
|
||||
initial_ast: 659b1f4496488c035e2c7af9e48d090248ef1f25e6f5ace909950420b7ca3722
|
||||
unrolled_ast: 659b1f4496488c035e2c7af9e48d090248ef1f25e6f5ace909950420b7ca3722
|
||||
ssa_ast: 659b1f4496488c035e2c7af9e48d090248ef1f25e6f5ace909950420b7ca3722
|
||||
flattened_ast: e52025e727b8679a9b09feee810c3861651136d8876d4d5d73f77daa51bfef45
|
||||
destructured_ast: dc8685689d83ab1dd09388ad893b18898e470a4a6af29ad08bdfdc09f117ffc9
|
||||
inlined_ast: dc8685689d83ab1dd09388ad893b18898e470a4a6af29ad08bdfdc09f117ffc9
|
||||
dce_ast: dc8685689d83ab1dd09388ad893b18898e470a4a6af29ad08bdfdc09f117ffc9
|
||||
- - initial_symbol_table: 8d141d5fae8f9558d51c1c1724328232a0ec9ac2f2395536fd57c94fd3c0c9db
|
||||
type_checked_symbol_table: 18804e4a6c45cb4615393e10f9bcdf03d1b3c57c0543d47c9fbc9481330c80e5
|
||||
unrolled_symbol_table: 18804e4a6c45cb4615393e10f9bcdf03d1b3c57c0543d47c9fbc9481330c80e5
|
||||
initial_ast: 7d40187329bfa45bc12a8722d93ae749d18bc1e74140426242a684297dd1f3e8
|
||||
unrolled_ast: 7d40187329bfa45bc12a8722d93ae749d18bc1e74140426242a684297dd1f3e8
|
||||
ssa_ast: 7d40187329bfa45bc12a8722d93ae749d18bc1e74140426242a684297dd1f3e8
|
||||
flattened_ast: e2468a2b162270486b4c801ca8d53737250d16e11b1907aa0181ac2bdb710638
|
||||
destructured_ast: 3a14bdb199158262348c694d07030108f2dddd658c822d2a1e88e5b8640a1438
|
||||
inlined_ast: 3a14bdb199158262348c694d07030108f2dddd658c822d2a1e88e5b8640a1438
|
||||
dce_ast: 3a14bdb199158262348c694d07030108f2dddd658c822d2a1e88e5b8640a1438
|
||||
bytecode: bbabb76319d2c69ed28a19090796ad7f974be74a1ef138d0cc58507cc4787632
|
||||
warnings: ""
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 3904f1aa2958b38775e38de11a75ff1ab9d4416331b916a0f35eb0147a3958da
|
||||
type_checked_symbol_table: d7bba066fadd2cbffbb1552f84c707126d167b8ede1d135970f00518f6ff8729
|
||||
unrolled_symbol_table: d7bba066fadd2cbffbb1552f84c707126d167b8ede1d135970f00518f6ff8729
|
||||
- - initial_symbol_table: 03c3c6a161c2813b1e23ee475d096e4736319aeade6acd8a5c01d06bb6666d39
|
||||
type_checked_symbol_table: 725f7cb442d1391ac14f33a35f2f08b16172caa56311f0b8f62b0d890a89240e
|
||||
unrolled_symbol_table: 725f7cb442d1391ac14f33a35f2f08b16172caa56311f0b8f62b0d890a89240e
|
||||
initial_ast: 660059d86d20bf51414ba6a346b61dd0c6afa1d975d1ede5d238625971d2ece2
|
||||
unrolled_ast: 660059d86d20bf51414ba6a346b61dd0c6afa1d975d1ede5d238625971d2ece2
|
||||
ssa_ast: 4d231a23b66f1e53a4ee1710c9228f325595440c08b06a40e29021683d47ea17
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: e8ac93eb52e18afae7ffff457a3168cc86074d0883104bc167fcbb8f3ed48ab3
|
||||
type_checked_symbol_table: 5e1ba8b3a528d5611d262eb41dffaddd07e77c8005eeb27e3b8dd263b873564c
|
||||
unrolled_symbol_table: 5e1ba8b3a528d5611d262eb41dffaddd07e77c8005eeb27e3b8dd263b873564c
|
||||
initial_ast: 49b0e5f168b47054711d61ba56cd00fdd2f0bd9aae1887bd2b94cbd3f9acaa80
|
||||
unrolled_ast: 49b0e5f168b47054711d61ba56cd00fdd2f0bd9aae1887bd2b94cbd3f9acaa80
|
||||
ssa_ast: 6bbc73503618356a10b615a8f52d9d7fa4a0b0d76ab5ce77362dabf7f7e0c582
|
||||
flattened_ast: 559e530f8bb0b5b15b31b74c2bf902d37a48fed8ca763c3d8d272e43169e2dcb
|
||||
destructured_ast: d75497ef52e99688d2c1278b23f5bfae8970e630ad1998b9fbf7cde1e686ecce
|
||||
inlined_ast: d75497ef52e99688d2c1278b23f5bfae8970e630ad1998b9fbf7cde1e686ecce
|
||||
dce_ast: d75497ef52e99688d2c1278b23f5bfae8970e630ad1998b9fbf7cde1e686ecce
|
||||
- - initial_symbol_table: 26f877e6575661a91a28368e33498e6e6807f3a2027fb798a383c8bddce3218b
|
||||
type_checked_symbol_table: a156cac3eae20c8389876081217052404f77d236c4766e8bb0782d0b9594dffb
|
||||
unrolled_symbol_table: a156cac3eae20c8389876081217052404f77d236c4766e8bb0782d0b9594dffb
|
||||
initial_ast: f220b8582b245809648f0b3697d37949bd2fd02767b68e32271e8b333e51308a
|
||||
unrolled_ast: f220b8582b245809648f0b3697d37949bd2fd02767b68e32271e8b333e51308a
|
||||
ssa_ast: 4023197733bca77f2882eb2f3f2ade5191fbacbeca3732ef79e077d26f629fc1
|
||||
flattened_ast: eaa969f63bfd5010915975bd11f4d8cd9ef88936ffcfa1bf34b1a76af1c2b1e3
|
||||
destructured_ast: b2b04532023156c700a64414ed41664dbb7b36edff06bff46fb5f029fa48e094
|
||||
inlined_ast: b2b04532023156c700a64414ed41664dbb7b36edff06bff46fb5f029fa48e094
|
||||
dce_ast: b2b04532023156c700a64414ed41664dbb7b36edff06bff46fb5f029fa48e094
|
||||
bytecode: 53499e77217ba5d8d146384234cbed9abe5c47abcbfe547f7bff6fbef4194a56
|
||||
warnings: ""
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: dc9a652b7919e99cbb63ca541c7c1738c2fcfec2f13fc6809fd1b12cb0a5174a
|
||||
type_checked_symbol_table: bdb1049769f4a3f4c08132e4e5c8ebe7693fda64b8ffb3aa0c4fc4a45ee3f0b2
|
||||
unrolled_symbol_table: bdb1049769f4a3f4c08132e4e5c8ebe7693fda64b8ffb3aa0c4fc4a45ee3f0b2
|
||||
- - initial_symbol_table: 2736b9080cd1f7ee443af8ec180fb09deba000c8dfe4318dbb30f1709936ecdf
|
||||
type_checked_symbol_table: 01b285a9912018552f939ce1c1fb09776f50d1eb361299d9e9a5eb68287944ff
|
||||
unrolled_symbol_table: 01b285a9912018552f939ce1c1fb09776f50d1eb361299d9e9a5eb68287944ff
|
||||
initial_ast: 4a5225c722d8af4f266ec15f7e9ff05e2c9375daa78f21ee078a5e22198d0adf
|
||||
unrolled_ast: 4a5225c722d8af4f266ec15f7e9ff05e2c9375daa78f21ee078a5e22198d0adf
|
||||
ssa_ast: 1708017fb5ea18ede484da052f593113726832c08a726e6fb824827e4a7ea111
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
unrolled_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
initial_ast: cb1bfce0497f40547211ffaeffda34260f6757ae7d01a459b18bc67b8ac8f34a
|
||||
unrolled_ast: cb1bfce0497f40547211ffaeffda34260f6757ae7d01a459b18bc67b8ac8f34a
|
||||
ssa_ast: 2e2f85fc41a676f3000db2d8458423fdbc30249f4adc8586cdd5c8dd4c71f54f
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
unrolled_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
initial_ast: e4a47461dd96ca03ee0cf5f66cd341212a64411225adfe1f4650b5a0244dc505
|
||||
unrolled_ast: e4a47461dd96ca03ee0cf5f66cd341212a64411225adfe1f4650b5a0244dc505
|
||||
ssa_ast: 4b157ccde4b193233579fc52a44a24b89ab462bf370717bf274003f65e143567
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
unrolled_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
initial_ast: 61217aec18c2073eee84ec4213b7bc45ed3bf4743a7dd0f438697e081a881dc7
|
||||
unrolled_ast: 61217aec18c2073eee84ec4213b7bc45ed3bf4743a7dd0f438697e081a881dc7
|
||||
ssa_ast: 2279e268ed5b67453ec005211004ebee30d7577737a87ad4bc21e72c36be2db0
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
unrolled_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
initial_ast: c16f3e4533f6a833dd3429cdace72599198d9ffc0cff0c5262f7d2d817aecad2
|
||||
unrolled_ast: c16f3e4533f6a833dd3429cdace72599198d9ffc0cff0c5262f7d2d817aecad2
|
||||
ssa_ast: 4cb449adc13d9fc054d35a4306c031d95833037c377da5fc56b4a76f2eabaa9c
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 844670f23e97a001089c04ae83eed78640626d547c0c1c64aea5c2a38e268bb9
|
||||
unrolled_symbol_table: 844670f23e97a001089c04ae83eed78640626d547c0c1c64aea5c2a38e268bb9
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: a8f7a4e237c8966091f6c5fdef5b980e067d7d91ebc40ab89dccdc6e36de71fb
|
||||
unrolled_symbol_table: a8f7a4e237c8966091f6c5fdef5b980e067d7d91ebc40ab89dccdc6e36de71fb
|
||||
initial_ast: 34ef2d8c201f7799c13ebdffbc40ae7ce6cf81c04e30286b7eae833c6fc4b356
|
||||
unrolled_ast: 34ef2d8c201f7799c13ebdffbc40ae7ce6cf81c04e30286b7eae833c6fc4b356
|
||||
ssa_ast: fb94a65958ce35f26e3b445f2069f5a728bd48c94517eefa84a98ba589b22df8
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 2adc422d95ac044a24d85b8ab7638650452e9649dc3084ab229a2233565845a0
|
||||
type_checked_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
unrolled_symbol_table: 17210cdbf1e596a6355a342d5e5d855a0f883b6a30482f5d2725df7804208869
|
||||
- - initial_symbol_table: c2554df804e76bce64e5beedbf8d8e065838dbcbd414e55b572828825d0d697b
|
||||
type_checked_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
unrolled_symbol_table: 22b375401300c7518693377bd090bac20ee7b423925434817e9d88c889e7deba
|
||||
initial_ast: b1d21cb0ba71715333e75efca70fe0bcf972fe6cd829450005477642b87073fe
|
||||
unrolled_ast: b1d21cb0ba71715333e75efca70fe0bcf972fe6cd829450005477642b87073fe
|
||||
ssa_ast: 2d68d235dcd42e1f8bc6c6a7b33df61ea8f568ef47f0f8d45ec829f5ba322747
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: e8ab51452ace557f47719b795991a5b62a8dcf64615bd93a99de8aa28179a7d0
|
||||
type_checked_symbol_table: 49e9824efda3a995b682f3f39333e11665cee1e995bffd650bdf5e6eec3ed103
|
||||
unrolled_symbol_table: 49e9824efda3a995b682f3f39333e11665cee1e995bffd650bdf5e6eec3ed103
|
||||
initial_ast: 5d57d2bbac04f4c15babb8424fd8a4283a06c8c378ab41a9124c526e85287286
|
||||
unrolled_ast: 5d57d2bbac04f4c15babb8424fd8a4283a06c8c378ab41a9124c526e85287286
|
||||
ssa_ast: 4e1a8787fe8dacabcd494c8518ab8c8e9f4b571f598c47580fc64909efb9b926
|
||||
flattened_ast: 6a671fa7b39b60d50699f61febd0ffa0b6a06631140310f393abdc4644366851
|
||||
destructured_ast: 8be2edf79cb1c826e031b358f3d9047fc58d929406f4c43a9a3df8bb4d3e150b
|
||||
inlined_ast: 8be2edf79cb1c826e031b358f3d9047fc58d929406f4c43a9a3df8bb4d3e150b
|
||||
dce_ast: 8be2edf79cb1c826e031b358f3d9047fc58d929406f4c43a9a3df8bb4d3e150b
|
||||
- - initial_symbol_table: cd0dd5b8c35f4122c143671a9c75e32b149bb2d85693ae62cbb4b5368ac38892
|
||||
type_checked_symbol_table: 188525122dabaa0f219515b75de1edad0bb16a433c9f45c197b06a35c5982a12
|
||||
unrolled_symbol_table: 188525122dabaa0f219515b75de1edad0bb16a433c9f45c197b06a35c5982a12
|
||||
initial_ast: f86190debc635d37b9a18467587d9836ad3bcc07b8ec6a263267c928b81c85c9
|
||||
unrolled_ast: f86190debc635d37b9a18467587d9836ad3bcc07b8ec6a263267c928b81c85c9
|
||||
ssa_ast: 115eafc8a3d7b48c79363e4c8a56314d73407e4fed1d56056fcbabf752060fcf
|
||||
flattened_ast: 75138500773ddba4b63ea9199c36f24c48a3169977fa70fc4adfbd64daeb71df
|
||||
destructured_ast: 0cd440866d288992b0795dbcc202791d7969c088378be37c2e6828f37407fe9c
|
||||
inlined_ast: 0cd440866d288992b0795dbcc202791d7969c088378be37c2e6828f37407fe9c
|
||||
dce_ast: 0cd440866d288992b0795dbcc202791d7969c088378be37c2e6828f37407fe9c
|
||||
bytecode: 3c391009be59588562aa4a34d1b00508cd253c94d35a66741962352c76a92633
|
||||
warnings: ""
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 98fe1781611a543edd8044244e7dca9e21b1b5e5833edd466d76f61d0009b7bb
|
||||
type_checked_symbol_table: 7e6838ca6e2731e8031ed48ca064c74c37d9e75e4fc0d57012aa5ff68b2d3174
|
||||
unrolled_symbol_table: 7e6838ca6e2731e8031ed48ca064c74c37d9e75e4fc0d57012aa5ff68b2d3174
|
||||
- - initial_symbol_table: fa3884ac54aff755ef2586393599721511b7ce135c9bcbe74cabff30886e0b80
|
||||
type_checked_symbol_table: 23d793fbaa974bea4557caf161cb9e8e4f653b8513007155c7b6d790e3bdcaff
|
||||
unrolled_symbol_table: 23d793fbaa974bea4557caf161cb9e8e4f653b8513007155c7b6d790e3bdcaff
|
||||
initial_ast: b868f87536ee7782c8fbeff535d6df882416886dd5dfed4f9363f350c9e55511
|
||||
unrolled_ast: b868f87536ee7782c8fbeff535d6df882416886dd5dfed4f9363f350c9e55511
|
||||
ssa_ast: c34387f2e4798e36e23f5b992ef13f39dd128ea4f38bea1fa6d931a8564a3744
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: af2effe11f5047f1accaca1df1d8456dbb355969e1e843ba37eda44257570551
|
||||
type_checked_symbol_table: 354aa26afb5a249661053cf406c56c1b5434ef844d9706dd2cc6bf2d29422578
|
||||
unrolled_symbol_table: 3e547b48415783fedfc122912e44531723314de8d8838ac4a4da298463dd1160
|
||||
- - initial_symbol_table: 4257c099771eba0ebe56caedd81d40740538873eaa91636b4d2ad01ca0c11dee
|
||||
type_checked_symbol_table: d8240d6895acdb3c1c6f527c87077b41a7ab85a1fc62cda388b51835da6ffa44
|
||||
unrolled_symbol_table: 02f0a9e26712b0acf1fc296ec9613e364e23254fb0bd0eb162b5404b0bf1dfe3
|
||||
initial_ast: cdc5af7d6affe7f7b920e862890f7d1243dc796aee21811427c3c4b952888a82
|
||||
unrolled_ast: 2fc7bc4cc122c854272b545de15d6a96f9b0005c32ab5eb1acd6f367cb758faa
|
||||
ssa_ast: 2d2ff690858a75e0f0c731a11899732c4902b36d1e73550c443e82a6b988aaae
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 77b127880b95652f948bc184d24fb51eb368cc2ccb022093cd27c2fbc03bb70e
|
||||
type_checked_symbol_table: be1bdc9825b662e2070dabbd8e16d24d51ed989e91e385f9ebf27e11dc12b902
|
||||
unrolled_symbol_table: 435f5b6da45d68cf00a82aca5b9bd6e326c5d7d2252811db0e96afd1de00a727
|
||||
initial_ast: 482e827fb2c32ca61a931013cd1e6f8d29ee21d7807a864a9b00484e536305b8
|
||||
unrolled_ast: aecbef72ad4fed4eb0962d95206c23a6ee6f060f62e4c2ad05ca1cf58ddcc655
|
||||
ssa_ast: f4301d11941e8dbe05400954f46895716cae64f7e3a34852f7d286af982c1197
|
||||
flattened_ast: b59ae5f18324bf358616bd17646feb7c5dff11d2028b8e8af681ea96df7a85cd
|
||||
destructured_ast: a8c24ec9d97955518927812d4ef31b4891d50c1c053adf88b3fed8917698c23b
|
||||
inlined_ast: a8c24ec9d97955518927812d4ef31b4891d50c1c053adf88b3fed8917698c23b
|
||||
dce_ast: a8c24ec9d97955518927812d4ef31b4891d50c1c053adf88b3fed8917698c23b
|
||||
- - initial_symbol_table: 92e694cc0e2f719d64e8e9430ce0469914f77d894c54c9dc0c8bc1e0c1c842e0
|
||||
type_checked_symbol_table: d6f165eac19e1c00649f1adaeb9f04464cfa1be8f06868500386191a587504b9
|
||||
unrolled_symbol_table: 8956477975d1c096a484474aa44051bf03177e60c203b45a59188670a23e5ee6
|
||||
initial_ast: 7605e29ba9dd5e1fab7cdfb8aa89d2775203f5273b84735a3440c545ebffce03
|
||||
unrolled_ast: 517bd11485cc6cabac08d36b8d0bb4e6ab7eed9182b10cd04ef6a0f277e0465b
|
||||
ssa_ast: ab7055ad83cbd497b5561391dee9a179bd4d7b577de91ed9dc72582cd9b72c91
|
||||
flattened_ast: 703074571d3f3479b96465ca1dca76b05b1e1d34d4783d06dfc04bd1dea0dfe2
|
||||
destructured_ast: e2ec29080262ba2b3f1be10263b24950edd7920b38c86eb9295ef7e7baea5120
|
||||
inlined_ast: e2ec29080262ba2b3f1be10263b24950edd7920b38c86eb9295ef7e7baea5120
|
||||
dce_ast: e2ec29080262ba2b3f1be10263b24950edd7920b38c86eb9295ef7e7baea5120
|
||||
bytecode: 34335e40c3ca26e00044d055cc0cb8d262fce1ac49a4940b36b1136e0772d305
|
||||
warnings: ""
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: d1eed24f01e5256fec3b444fd3a38b7e25756c5fb20010872884a34d54ef888c
|
||||
type_checked_symbol_table: 89c060252a9e229b91f2ac52e5e3823e04400f3e060ead04999aa4911f42c731
|
||||
unrolled_symbol_table: c00e0818651bd9e2c068becdf3819b8d46238e0cfad46c87791efa9c97c6f9de
|
||||
- - initial_symbol_table: 9d2621a6655c3b4fc488b4303557b99756de606508b19dc917a2d2c004d05b3c
|
||||
type_checked_symbol_table: 63e4810a08f666b904fa09a6c923ddaed25dcefd5ab69a9dbfb0067f5563c494
|
||||
unrolled_symbol_table: 6979a1a8c5d4216808b49ffdd08823c90bb7bb453ba0a24f929a4e8a4713f806
|
||||
initial_ast: 9ebde40ca2971771bf7ff4af11a88482f32aee303723c87cfe5b4a0795a560bb
|
||||
unrolled_ast: 338b820767e2fc502f9530c16635f6a8589c0c48c18157f3d76c924193b65b03
|
||||
ssa_ast: c3265796218829ddfdd6e34b50beaefadabdb49695cbf3034330442571766e61
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: c6a4e40ae8f466c3ff6bf5d356d6ba89684438f88015e8ea23ff43eadb662b49
|
||||
type_checked_symbol_table: 0b88104308fe0b9e390a59a4359d6245170347557911b21ba04cd1d9124da14d
|
||||
unrolled_symbol_table: af56532f8dd6c6ca6f5fc8af3667202298898a54fe2f871a7874684a712f141d
|
||||
- - initial_symbol_table: 29e97965dc9ebb3ed0ec705736fbdc7dbb9f813faeac344da82d0456e333f874
|
||||
type_checked_symbol_table: e82c690e31df9895a2e07093511bc47a321ceabb638540d5fba59641db0e8abc
|
||||
unrolled_symbol_table: 649c16b1edb5c10fc698f4ed9912a0438208546bc8b06f50f004b3176db37f47
|
||||
initial_ast: 6256a249cbc21507d80bb44e2915179d77485e9c7974b09dad5ac31c80857779
|
||||
unrolled_ast: 9c4e9b3fa952b1eb43ad69e5374eaa14dd6a7028e993cfef8183f832869d5a5d
|
||||
ssa_ast: 10a72521616bff5daf9a6086d3c4a86a98abb246ccebe02f62d92ef3885f8138
|
||||
|
@ -2,9 +2,9 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: c6a4e40ae8f466c3ff6bf5d356d6ba89684438f88015e8ea23ff43eadb662b49
|
||||
type_checked_symbol_table: 1f2f455b3509dd7c93fa6799a0f3f01843aaab11efbc772223dcb5de29ae93f9
|
||||
unrolled_symbol_table: 1ff2f86af30a607b97e5d1795e0ff64aee075c340aa13d8c1b98df2595eddd58
|
||||
- - initial_symbol_table: 29e97965dc9ebb3ed0ec705736fbdc7dbb9f813faeac344da82d0456e333f874
|
||||
type_checked_symbol_table: 0d2450e4e9dbdf81f3509cfd8a2ddf47db37aa8980bf1c268305e4e0558772d4
|
||||
unrolled_symbol_table: 1380d27733d07cc968b92d018486a2c5a7dce3ede1253f4c6694b7ae5e477105
|
||||
initial_ast: 2edeabb90f14e92b8eeab4396b1ddcc6e707da5e3b3ca9936ba946bbaba68822
|
||||
unrolled_ast: 305dc314c5c7272d119542345476398ae0e349b6fbc38ea8286e5a53510ea821
|
||||
ssa_ast: 04080337c157b9b1b50422ee764a6bd8ecb102d6198a48ffc83919f07d339806
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: 707f488348423358f9abd38688d3501da41a6b6ca5655302a7ade6e656b05e58
|
||||
unrolled_symbol_table: 707f488348423358f9abd38688d3501da41a6b6ca5655302a7ade6e656b05e58
|
||||
initial_ast: dcba8db0243dff2d3c5311005e63d0647ed42363d0362422c33f95925a36dad8
|
||||
unrolled_ast: dcba8db0243dff2d3c5311005e63d0647ed42363d0362422c33f95925a36dad8
|
||||
ssa_ast: 804d72944c1e4c4c491108bda45dc1c48d856b332d18f985f791d3f813d2430a
|
||||
flattened_ast: 927cd1441ff9c59ac177e9a2d783d9f8c49f58fa474412095200b0ca6d5effee
|
||||
destructured_ast: da6c4f48019a88521e69e131dfb94fed21a3109e623c0c9d0e1db6d02d56fab4
|
||||
inlined_ast: da6c4f48019a88521e69e131dfb94fed21a3109e623c0c9d0e1db6d02d56fab4
|
||||
dce_ast: 5ff2ea345d15672bbfc673a9e773299d94783e41f819c221507387df6b1f12fc
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 1ab6493df9354a7e0a097a8f78ad1614dee1166e9de8ab017279fa02bcc1ee28
|
||||
unrolled_symbol_table: 1ab6493df9354a7e0a097a8f78ad1614dee1166e9de8ab017279fa02bcc1ee28
|
||||
initial_ast: 14ed8952c476c2b24bf9ad6cd7da7091e8aacd49975682bc4876f9b2d3aedbbe
|
||||
unrolled_ast: 14ed8952c476c2b24bf9ad6cd7da7091e8aacd49975682bc4876f9b2d3aedbbe
|
||||
ssa_ast: dcb235411309bf2559c2a427c29e716b2069631a485110e9a82e23994bb3fc52
|
||||
flattened_ast: 9020e9b164148797cd34c2dc0031396ad860ef0dcdad67762943a00bd7d7d4f7
|
||||
destructured_ast: 9da93c6eb49d492936f1d950dd4e3a2aaa93dff67b23fd6f8667f4c20b626861
|
||||
inlined_ast: 9da93c6eb49d492936f1d950dd4e3a2aaa93dff67b23fd6f8667f4c20b626861
|
||||
dce_ast: 665fb2235b45e4fe8801daa263ced1e9183789878e536c7b8d18e47681937947
|
||||
bytecode: 03845ec2f54d49f71640659603ead8f68ad067a15fda438e5e13524777d1559b
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: bc000e895baf69a211930d29f38a0526e602ffebbe81b996fe8d88ffcd793239
|
||||
unrolled_symbol_table: bc000e895baf69a211930d29f38a0526e602ffebbe81b996fe8d88ffcd793239
|
||||
initial_ast: 4720b451bb96d91b8d5d632ea11e2394d9b34bd4c396633658905acf7e08ac94
|
||||
unrolled_ast: 4720b451bb96d91b8d5d632ea11e2394d9b34bd4c396633658905acf7e08ac94
|
||||
ssa_ast: c5998a0356afed2adbafa1d0ed223f3d848c09e783119a51b38cf42f37aa1930
|
||||
flattened_ast: 498ab5e011ce4ca54e190bc80ea436c39443029c1d7be50894d740ed16baaa7d
|
||||
destructured_ast: 61e71696de1b8067a8fcaf4cb63a61512a0a35c69026fa8cb9d0d56cce32f416
|
||||
inlined_ast: 61e71696de1b8067a8fcaf4cb63a61512a0a35c69026fa8cb9d0d56cce32f416
|
||||
dce_ast: b7bfe7c834ca23bb98558e0e802401b75f2eb4cc9c03bae8098ecc602a4f8117
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 8e5ad458f96ada8c3cdd6424e864c7a94692cfab224dc16b6941cfd5fc99f883
|
||||
unrolled_symbol_table: 8e5ad458f96ada8c3cdd6424e864c7a94692cfab224dc16b6941cfd5fc99f883
|
||||
initial_ast: 4658c53df803f432b94e89b89f9919e362fa9fb1a36cec6a4bfaeef9a7024434
|
||||
unrolled_ast: 4658c53df803f432b94e89b89f9919e362fa9fb1a36cec6a4bfaeef9a7024434
|
||||
ssa_ast: d9edec3b6bee6695344a4f8f7c0ef735d02838a800a0d10737083ed7956a919f
|
||||
flattened_ast: de70fa794947b7c4cd24beac167e076dded5e8325eb95f36b5f906746950deda
|
||||
destructured_ast: 16c6941986501843ab532ce7750e13b1db6b35b66a2903bce1a81e5d7ac640fd
|
||||
inlined_ast: 16c6941986501843ab532ce7750e13b1db6b35b66a2903bce1a81e5d7ac640fd
|
||||
dce_ast: bea3bf327ec7a8509c0b2dd9c08a8ad66f22cb4997a17fed66ff21c362ce4de7
|
||||
bytecode: 89209e8d86f847dbf47309d0092ee98ff4c7e72f93c06aa16b185b87931b4163
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: fd9620b494239c2b62c2da7b951d51f08a1c0ad366a726e6b108da648ce5fb58
|
||||
type_checked_symbol_table: 392b4afe780015c412cfb5e45a1b084b40873e9eda40e05ef94ab54aaadf8a3d
|
||||
unrolled_symbol_table: 392b4afe780015c412cfb5e45a1b084b40873e9eda40e05ef94ab54aaadf8a3d
|
||||
initial_ast: df1a8e245bf68db29b7e51bd474d925561f71360f9bcaf8191395fb32dc307d4
|
||||
unrolled_ast: df1a8e245bf68db29b7e51bd474d925561f71360f9bcaf8191395fb32dc307d4
|
||||
ssa_ast: 272eb3fc1c47b2b004ed89eb8eb01942082b1e6497221d27c28513d47570fbdf
|
||||
flattened_ast: 95e9236617e41f9860d237f4db626b50cffccc079fa5342c735192d9c4847970
|
||||
destructured_ast: ddc393fca22f1ff67682d324bf7e97e9d9f346361fa05b8b355ec26a5f49eb7b
|
||||
inlined_ast: ddc393fca22f1ff67682d324bf7e97e9d9f346361fa05b8b355ec26a5f49eb7b
|
||||
dce_ast: c56ccba1e524a36abd2d6a080963e02681b3906e2588e7418c345037f40ee75a
|
||||
- - initial_symbol_table: bc00a6f0fa880e2cddf4bc424ff5f9968e43ce903d50d465f4f546e7cd4a2cf2
|
||||
type_checked_symbol_table: 2b3107f8a94acb12092cb40d6eca58305e01681f8aaf3c4fe128ca80378d5390
|
||||
unrolled_symbol_table: 2b3107f8a94acb12092cb40d6eca58305e01681f8aaf3c4fe128ca80378d5390
|
||||
initial_ast: c195cd96cb533417c22ee288a309dc785869aead578882b8de25adaa7138767a
|
||||
unrolled_ast: c195cd96cb533417c22ee288a309dc785869aead578882b8de25adaa7138767a
|
||||
ssa_ast: d61f8c38d5972e527ca0774933f12701948204aabf235bcc410234b0cca6ffa7
|
||||
flattened_ast: c2913b758f62dc5bfb9578736623c6f555e92843ef2640e7b8c4017010bab71e
|
||||
destructured_ast: 5e47cadb8b30359951bb55d17f62114e21c36cb22909bdd8922d280e205fad79
|
||||
inlined_ast: 5e47cadb8b30359951bb55d17f62114e21c36cb22909bdd8922d280e205fad79
|
||||
dce_ast: 32ceba1bad1d48a88a8bec44db7202e2666ee7a1eace8065dfa7e643a04b6922
|
||||
bytecode: 44723f1147fbb09b330db772453005ab5dae98a53925a9dc45b66daa51584290
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: aaaec423b2c439b4857751e7dec72e29fbe3cf863753d6f21e52c9d0f5e98558
|
||||
unrolled_symbol_table: aaaec423b2c439b4857751e7dec72e29fbe3cf863753d6f21e52c9d0f5e98558
|
||||
initial_ast: 2244e3ecab6e4c4f0d3a04a2fccffa870b542be65fe973a3734acf2c95e8ad3f
|
||||
unrolled_ast: 2244e3ecab6e4c4f0d3a04a2fccffa870b542be65fe973a3734acf2c95e8ad3f
|
||||
ssa_ast: b07230fc8f516422ef9f80eef3a0341b2300bc017db7109e1a0e95cb135cff0b
|
||||
flattened_ast: 8bbb94ce31bbbf42d3bfb5db2db9a82e0c0abde78ef902cc970e3ef97ea4175a
|
||||
destructured_ast: 128428fb8bc285f8de9ec60c68bdd14a68ac89f1b3d1b32147159de9528191a0
|
||||
inlined_ast: 128428fb8bc285f8de9ec60c68bdd14a68ac89f1b3d1b32147159de9528191a0
|
||||
dce_ast: d1aaa70ff1de70aad1729694e33da529dfb87e5308939a7bae4b4448c35c6649
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 7ea97bd3f2f1366697977d015b733d7f70222006a2c318ffd71f85b486683aa0
|
||||
unrolled_symbol_table: 7ea97bd3f2f1366697977d015b733d7f70222006a2c318ffd71f85b486683aa0
|
||||
initial_ast: 7e158eb4d35f3576485510266c8bf65e43a8a01e112c893a9b207f22455fff6c
|
||||
unrolled_ast: 7e158eb4d35f3576485510266c8bf65e43a8a01e112c893a9b207f22455fff6c
|
||||
ssa_ast: 580070ba6c54295ee57adad120f1e289e0383a9924b33483d418d578984516df
|
||||
flattened_ast: 9a9f97a65090fb04e4923f03168ff633de8dd8df5d0d77771e0297895327f8ad
|
||||
destructured_ast: af85d016afeb7bb8f094f29d35efa0d587d7318ab7ddcf0d1e7dcb8c41995e13
|
||||
inlined_ast: af85d016afeb7bb8f094f29d35efa0d587d7318ab7ddcf0d1e7dcb8c41995e13
|
||||
dce_ast: 3398f3b5688a2adfd3e1a729066f970183d1cd3d0081a35b566ef5a78025c691
|
||||
bytecode: 03845ec2f54d49f71640659603ead8f68ad067a15fda438e5e13524777d1559b
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: f51b6c1660b8bb5b45ca5e05c303bf2fb92e47d575ff34c69abec002486452f4
|
||||
unrolled_symbol_table: f51b6c1660b8bb5b45ca5e05c303bf2fb92e47d575ff34c69abec002486452f4
|
||||
initial_ast: 6862efe8b596e629b2378b738167947a2fa19089e649fa1fc48a4b166bc56335
|
||||
unrolled_ast: 6862efe8b596e629b2378b738167947a2fa19089e649fa1fc48a4b166bc56335
|
||||
ssa_ast: a27a2e149590e24904d3f874cf7aaf0c4cd8b720b978d2b254c33d31fd4be31d
|
||||
flattened_ast: afcbe91351846e907371ce92509d19adfda10428ff31d81281f3730fb1b05aba
|
||||
destructured_ast: defef5668f0ec16f7c85197153c526d329e41e9a3c068ad273f8a2fc153b521e
|
||||
inlined_ast: defef5668f0ec16f7c85197153c526d329e41e9a3c068ad273f8a2fc153b521e
|
||||
dce_ast: 683f503ccc7ccb5b9c8c45b019338ef1228ea93b793076bcc31ed7c6639c192f
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 857ddcccc8ba5f91784b3dde333bcc63b5883ee12d4110112eda378ac43ccdc5
|
||||
unrolled_symbol_table: 857ddcccc8ba5f91784b3dde333bcc63b5883ee12d4110112eda378ac43ccdc5
|
||||
initial_ast: cf0620436443663eee9dd1767bbdba9c2a68b350a02a32df0b203b6c07c28e3d
|
||||
unrolled_ast: cf0620436443663eee9dd1767bbdba9c2a68b350a02a32df0b203b6c07c28e3d
|
||||
ssa_ast: ee7a71f44f12f31dbed39bc4db57b50c72012769af87c4ccb24f408d0955f49e
|
||||
flattened_ast: 64ddd1307acda3369319ec275d0d1a1e2b3c58941bf55da4533f0b4e59815838
|
||||
destructured_ast: 482ea7d3d89a58dc0167fc45c84d402fb4fb150dd7e583b8edde3f0c93b12a34
|
||||
inlined_ast: 482ea7d3d89a58dc0167fc45c84d402fb4fb150dd7e583b8edde3f0c93b12a34
|
||||
dce_ast: 557dcaf33a9988d441fbe85b0fe13bef52bf00e214b9631224765930c8b733b4
|
||||
bytecode: 1ee04c880a78442953925baa8e3c60e416d77c926da80774db6961188aaba65a
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: fd9620b494239c2b62c2da7b951d51f08a1c0ad366a726e6b108da648ce5fb58
|
||||
type_checked_symbol_table: 392b4afe780015c412cfb5e45a1b084b40873e9eda40e05ef94ab54aaadf8a3d
|
||||
unrolled_symbol_table: 392b4afe780015c412cfb5e45a1b084b40873e9eda40e05ef94ab54aaadf8a3d
|
||||
initial_ast: 724b1b99450b4b86135c4466d0096fa0a1604587bc67b200b48c10beff1ddc8a
|
||||
unrolled_ast: 724b1b99450b4b86135c4466d0096fa0a1604587bc67b200b48c10beff1ddc8a
|
||||
ssa_ast: c526d668c728b43d6c65616f11bef25cd64ffecebb0bd4c879fb252bb6ec27ce
|
||||
flattened_ast: 1043a107ea8f2bd3c010df9f98a9615aace849d7c8a811d8cfc6d13f2c395e3c
|
||||
destructured_ast: 25f2b52c4f11522535461a96a6547e6da3fe3877e004d54bf88da6bc0ba662cd
|
||||
inlined_ast: 25f2b52c4f11522535461a96a6547e6da3fe3877e004d54bf88da6bc0ba662cd
|
||||
dce_ast: e478366ce2754d6ea16a10244d81226bb04183347cc53bcdd558ee4d6d0c3926
|
||||
- - initial_symbol_table: bc00a6f0fa880e2cddf4bc424ff5f9968e43ce903d50d465f4f546e7cd4a2cf2
|
||||
type_checked_symbol_table: 2b3107f8a94acb12092cb40d6eca58305e01681f8aaf3c4fe128ca80378d5390
|
||||
unrolled_symbol_table: 2b3107f8a94acb12092cb40d6eca58305e01681f8aaf3c4fe128ca80378d5390
|
||||
initial_ast: 18367bef5242c3d05bf9b634b7c4283827cc2b139dd34321ca7bdf15548ebed4
|
||||
unrolled_ast: 18367bef5242c3d05bf9b634b7c4283827cc2b139dd34321ca7bdf15548ebed4
|
||||
ssa_ast: f304a3aa5bfea73165262ef32997e06905caf181a1128dd491901f3e9ab8894d
|
||||
flattened_ast: d1b14cb4e3e6741c59fd51d1f1d9c7586d0a3b277b988bc23bbf62a5b3205f2a
|
||||
destructured_ast: 9a60cdb4272353ea39b520c6395ee2728947743ac8f1168a7749b6284f69302b
|
||||
inlined_ast: 9a60cdb4272353ea39b520c6395ee2728947743ac8f1168a7749b6284f69302b
|
||||
dce_ast: b251f2c19953b697d980b2ced31dba59d0620b4a82c66f5e0c3895f12bfb4032
|
||||
bytecode: 6e17954a1a55bf11bcac1b381fc6a82ee849f92a9af06d755ee3d6e3cd3b748d
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 15549a7085ac019c35b881b7ef00f56cbfbf0a21e9ceb4d4599fa4e06359d9e5
|
||||
type_checked_symbol_table: 3955df6eabb0bfb8f9df5a34a49c11bf3bf95325f88a0affd038b820e7541266
|
||||
unrolled_symbol_table: 3955df6eabb0bfb8f9df5a34a49c11bf3bf95325f88a0affd038b820e7541266
|
||||
initial_ast: 70ae6cfc27164672f73bac7b6b5405e0e876162dfbdfe6b618fe8184287a49f1
|
||||
unrolled_ast: 70ae6cfc27164672f73bac7b6b5405e0e876162dfbdfe6b618fe8184287a49f1
|
||||
ssa_ast: 8349db51da75a1c832f8586699473243b34ef5b524bac62371e36172570aa996
|
||||
flattened_ast: 8fb875c484788763c74e64d0718d4b574fe2a5db6c4893f1228a3b77aa096858
|
||||
destructured_ast: 05c1ec59b3cbd71655714f3f35f5ff6ede1426e7ef57799fd7d9c55fa989d05d
|
||||
inlined_ast: 05c1ec59b3cbd71655714f3f35f5ff6ede1426e7ef57799fd7d9c55fa989d05d
|
||||
dce_ast: 971bc4589f1a71c59114995383e04bf98125ed5d7ed800cc91d7e98dcbfa57e3
|
||||
- - initial_symbol_table: 79eed2f6e683aa3a028ae2e9dab1002207743d7b4a651658bbc6a5b8185e0f8c
|
||||
type_checked_symbol_table: 17abd653b2f3fa7cd1996c2f7675fb6f64a4b5dbdd281c46e8977676e7eb857c
|
||||
unrolled_symbol_table: 17abd653b2f3fa7cd1996c2f7675fb6f64a4b5dbdd281c46e8977676e7eb857c
|
||||
initial_ast: e30e680035a999fddf3f6bf727d96a91bcb315e0015e68f06be3bc6a5fea60ee
|
||||
unrolled_ast: e30e680035a999fddf3f6bf727d96a91bcb315e0015e68f06be3bc6a5fea60ee
|
||||
ssa_ast: 20eab109b98f072405d4e7491e12625dd8c32912f0744b06c426f0a67e67b636
|
||||
flattened_ast: c07c880e72d3e0ee980acd278d7e1583a2bb57edb5279c8b8876ff0daf23b411
|
||||
destructured_ast: 5d6134b5ce819e2425216bb82a34b4d030520031b333d8cfdbde495cfb140a53
|
||||
inlined_ast: 5d6134b5ce819e2425216bb82a34b4d030520031b333d8cfdbde495cfb140a53
|
||||
dce_ast: bd6a7668dbd9fb4fb4ee5988d6888995ca9e0fd9c0e3e078bc578162d0321bf6
|
||||
bytecode: 16448534dab09040c482f623815abdd0bd2e330d2cb99bc095142027c80e9bf0
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: 707f488348423358f9abd38688d3501da41a6b6ca5655302a7ade6e656b05e58
|
||||
unrolled_symbol_table: 707f488348423358f9abd38688d3501da41a6b6ca5655302a7ade6e656b05e58
|
||||
initial_ast: 4b0b99b3510b8312cd185c02e161adffd10b25c431b7bb0999fee6190c4d34bb
|
||||
unrolled_ast: 4b0b99b3510b8312cd185c02e161adffd10b25c431b7bb0999fee6190c4d34bb
|
||||
ssa_ast: 3975b2a6e35a69ea3081d68079929b67f09ea675d17e011fb3367bdbe37183a6
|
||||
flattened_ast: e1956e1f27dcd6451eaa3a6d94fd28de9d92edbbd37819953124c89a3b0b7abc
|
||||
destructured_ast: 3e1689b9d4b2469981aaa5f35b7505504c2283dd3817f9351517de4ad54b156e
|
||||
inlined_ast: 3e1689b9d4b2469981aaa5f35b7505504c2283dd3817f9351517de4ad54b156e
|
||||
dce_ast: d7186f00033b3a34ccec5d56bf8e7986e61cd99a8e7da17752a67646e00a82c3
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 1ab6493df9354a7e0a097a8f78ad1614dee1166e9de8ab017279fa02bcc1ee28
|
||||
unrolled_symbol_table: 1ab6493df9354a7e0a097a8f78ad1614dee1166e9de8ab017279fa02bcc1ee28
|
||||
initial_ast: c0ca1427cdd60625ce2d8bd7c687a6b7820a2cb690fb99e406b5e84513c1a01f
|
||||
unrolled_ast: c0ca1427cdd60625ce2d8bd7c687a6b7820a2cb690fb99e406b5e84513c1a01f
|
||||
ssa_ast: 7f8e1c97b94aa7a8d2935fd64c8c2ad0e043344226e69e1b57d09021644e94d7
|
||||
flattened_ast: f77d1031edd766b0818fdda872ad8df55cf34c17c24f0dd9c68bc60d625b4237
|
||||
destructured_ast: 4ba710fd1e4b97e48a60a9934f98af9575d7d889eaa87ff11978b955a49812f6
|
||||
inlined_ast: 4ba710fd1e4b97e48a60a9934f98af9575d7d889eaa87ff11978b955a49812f6
|
||||
dce_ast: 47690fcd1ee8d2cdba48c23272c73e8c4a5bb7dcb2ecacb9f88cd75c56d842b1
|
||||
bytecode: 03845ec2f54d49f71640659603ead8f68ad067a15fda438e5e13524777d1559b
|
||||
warnings: ""
|
||||
|
@ -2,15 +2,15 @@
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- - initial_symbol_table: 1f96df1e414fd96505a23c658692de40614d28804ebeaeafc90835f4087c91cc
|
||||
type_checked_symbol_table: bc000e895baf69a211930d29f38a0526e602ffebbe81b996fe8d88ffcd793239
|
||||
unrolled_symbol_table: bc000e895baf69a211930d29f38a0526e602ffebbe81b996fe8d88ffcd793239
|
||||
initial_ast: 93b0131377f218c67f41be2b8b795349a742fcbbd6a7f61a0bd18990d5fabe8e
|
||||
unrolled_ast: 93b0131377f218c67f41be2b8b795349a742fcbbd6a7f61a0bd18990d5fabe8e
|
||||
ssa_ast: 0a5800473375620b508c3f4fec976b9770ebce5685289a8889ebe094b8f8ed23
|
||||
flattened_ast: 6f8d62220e2d6c71a71c8631d7b154f7be88b7204d08ca2a799833ac84c679dd
|
||||
destructured_ast: 4b3207f15d35554170e7f06c3b9c30fd30c66c90fbf5e8838465ff4e4e992190
|
||||
inlined_ast: 4b3207f15d35554170e7f06c3b9c30fd30c66c90fbf5e8838465ff4e4e992190
|
||||
dce_ast: d8c20485466ea4656dc3cc6b57e25833cc2ac39443e21976bcac3fa67c700a71
|
||||
- - initial_symbol_table: 0b53989640055bef15deab2fb1e4d8691b4f1b439f1bdba64f34278be1cb37e0
|
||||
type_checked_symbol_table: 8e5ad458f96ada8c3cdd6424e864c7a94692cfab224dc16b6941cfd5fc99f883
|
||||
unrolled_symbol_table: 8e5ad458f96ada8c3cdd6424e864c7a94692cfab224dc16b6941cfd5fc99f883
|
||||
initial_ast: ae1a7a56279a9af54fffb6da377fbc46de742e00b3238b2aeba45d09a6632130
|
||||
unrolled_ast: ae1a7a56279a9af54fffb6da377fbc46de742e00b3238b2aeba45d09a6632130
|
||||
ssa_ast: 7c0adf4a4225d8c741214ceefaf4a9b56958a913c3ad8eca468e07a2e28bed58
|
||||
flattened_ast: d9baa25d51c87537ad3a3030d3122c948cd8e3796c164eeb8c6618db2269761f
|
||||
destructured_ast: d9c5da617aaf0e94e0269fa93f3f2ed1361b49f5f3f454bcc18d4762f91d2c12
|
||||
inlined_ast: d9c5da617aaf0e94e0269fa93f3f2ed1361b49f5f3f454bcc18d4762f91d2c12
|
||||
dce_ast: 1cd99533251f8450ee6d930c75909bd831feddedeaf232cf4f6fa0962665ada0
|
||||
bytecode: cbaea392a3a5a598090b5c75eebfc840f9fd1f4dd9460704bd82c17acfedcedf
|
||||
warnings: ""
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user