Merge pull request #26901 from AleoHQ/feat/leo-deploy

Leo Deploy
This commit is contained in:
d0cd 2024-02-11 22:05:42 -06:00 committed by GitHub
commit a2e31558c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
753 changed files with 5952 additions and 5076 deletions

488
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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" ]

View File

@ -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)
}
}

View File

@ -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}")?;

View File

@ -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) })
}
}

View File

@ -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(),
}

View File

@ -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.

View File

@ -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
}

View File

@ -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) {}
}

View File

@ -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() },
}
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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(),
})),

View File

@ -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,
}
}
}

View File

@ -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.

View File

@ -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", "")),
}
}

View File

@ -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::*;

View 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)
}
}

View File

@ -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"),
}
}
}

View File

@ -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());

View File

@ -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

View File

@ -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(),
});

View File

@ -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(),

View File

@ -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)?;

View File

@ -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"]

View File

@ -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);

View File

@ -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()));

View File

@ -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_),

View File

@ -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) {

View 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))
}
}

View File

@ -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);
});
}
}

View File

@ -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,

View File

@ -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),

View File

@ -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
},
});

View File

@ -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,
}
}
}

View File

@ -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());
}

View File

@ -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.

View File

@ -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};

View File

@ -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);

View File

@ -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,
}
}

View File

@ -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());

View File

@ -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(),

View File

@ -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,

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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);

View File

@ -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) => {

View File

@ -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 {

View File

@ -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::*;

View File

@ -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;

View File

@ -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()),
}
);

View File

@ -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,
}
);

View File

@ -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,
}
);

View File

@ -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,
}
);

View File

@ -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()),
}
);

View File

@ -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()),
}
);

View File

@ -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);
}

View File

@ -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();
});
}
}

View File

@ -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.

View File

@ -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())
}
}

View File

@ -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()?;

View File

@ -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.")]

View File

@ -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)
}
}

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: ""

View File

@ -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

View File

@ -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

View File

@ -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: ""

View File

@ -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

View File

@ -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: ""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: ""

View File

@ -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

View File

@ -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

View File

@ -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: ""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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: ""

View File

@ -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