Change representation of external records in AST

This commit is contained in:
evan-schott 2024-01-12 20:14:23 -08:00
parent 278f59bba7
commit 4b8131c036
5 changed files with 103 additions and 41 deletions

View File

@ -44,6 +44,8 @@ pub struct Struct {
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.
pub is_record: bool,
@ -66,6 +68,41 @@ impl Struct {
pub fn name(&self) -> Symbol {
self.identifier.name
}
pub fn from_external_record<N: Network>(input: &RecordType<N>, external_program: Symbol) -> Self {
Self {
identifier: Identifier::from(input.name()),
members: [
vec![Member {
mode: if input.owner().is_private() { Mode::Public } else { Mode::Private },
identifier: Identifier::new(Symbol::intern("owner"), Default::default()),
type_: Type::Address,
span: Default::default(),
id: Default::default(),
}],
input
.entries()
.iter()
.map(|(id, entry)| Member {
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),
},
span: Default::default(),
id: Default::default(),
})
.collect_vec(),
]
.concat(),
external: Some(external_program),
is_record: true,
span: Default::default(),
id: Default::default(),
}
}
}
impl fmt::Debug for Struct {
@ -102,45 +139,10 @@ impl<N: Network> From<&StructType<N>> for Struct {
id: Default::default(),
})
.collect(),
external: None,
is_record: false,
span: Default::default(),
id: Default::default(),
}
}
}
impl<N: Network> From<&RecordType<N>> for Struct {
fn from(input: &RecordType<N>) -> Self {
Self {
identifier: Identifier::from(input.name()),
members: [
vec![Member {
mode: if input.owner().is_private() { Mode::Public } else { Mode::Private },
identifier: Identifier::new(Symbol::intern("owner"), Default::default()),
type_: Type::Address,
span: Default::default(),
id: Default::default(),
}],
input
.entries()
.iter()
.map(|(id, entry)| Member {
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),
},
span: Default::default(),
id: Default::default(),
})
.collect_vec(),
]
.concat(),
is_record: true,
span: Default::default(),
id: Default::default(),
}
}
}

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,39 @@
// 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 struct type of a identifier and optional external program name.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Copy)]
pub struct StructType {
// The identifier of the struct definition.
pub id: Identifier,
// The external program that this struct is defined in.
pub external: Option<Symbol>,
}
impl fmt::Display for StructType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.external {
Some(external) => write!(f, "{external}/{id}", id = self.id),
None => write!(f, "{id}", id = self.id),
}
}
}

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::{common, ArrayType, Identifier, IntegerType, MappingType, TupleType};
use crate::{common, ArrayType, Identifier, IntegerType, MappingType, StructType, TupleType};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
@ -34,6 +34,8 @@ pub enum Type {
Array(ArrayType),
/// The `bool` type.
Boolean,
/// The `struct` type.
Struct(StructType),
/// The `field` type.
Field,
/// The `group` type.
@ -88,6 +90,14 @@ impl Type {
.iter()
.zip_eq(right.elements().iter())
.all(|(left_type, right_type)| left_type.eq_flat(right_type)),
(Type::Struct(left), Type::Struct(right)) => {
left.id.name == right.id.name
&& match (left.external, right.external) {
(Some(left), Some(right)) => left == right,
(None, None) => true,
_ => false,
}
}
_ => false,
}
}
@ -107,6 +117,7 @@ impl fmt::Display for Type {
Type::Scalar => write!(f, "scalar"),
Type::Signature => write!(f, "signature"),
Type::String => write!(f, "string"),
Type::Struct(ref struct_type) => write!(f, "{struct_type}"),
Type::Tuple(ref tuple) => write!(f, "{tuple}"),
Type::Unit => write!(f, "()"),
Type::Err => write!(f, "error"),
@ -136,7 +147,7 @@ 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)),
Struct(s) => Type::Struct(StructType { id: common::Identifier::from(s), external: None }),
Array(array) => Type::Array(ArrayType::from(array)),
}
}

View File

@ -27,13 +27,18 @@ use leo_errors::UtilError;
pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
program: ProgramCore<N, Instruction, Command>,
) -> Stub {
let program_id = ProgramId::from(program.id());
Stub {
imports: program.imports().into_iter().map(|(id, _)| ProgramId::from(id)).collect(),
stub_id: ProgramId::from(program.id()),
stub_id: program_id,
consts: Vec::new(),
structs: [
program.structs().iter().map(|(id, s)| (Identifier::from(id).name, Struct::from(s))).collect_vec(),
program.records().iter().map(|(id, s)| (Identifier::from(id).name, Struct::from(s))).collect_vec(),
program
.records()
.iter()
.map(|(id, s)| (Identifier::from(id).name, Struct::from_external_record(s, program_id.name.name)))
.collect_vec(),
]
.concat(),
mappings: program.mappings().into_iter().map(|(id, m)| (Identifier::from(id).name, Mapping::from(m))).collect(),
@ -46,7 +51,9 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
program
.functions()
.iter()
.map(|(id, function)| (Identifier::from(id).name, FunctionStub::from(function)))
.map(|(id, function)| {
(Identifier::from(id).name, FunctionStub::from_function_core(function, program_id.name.name))
})
.collect_vec(),
]
.concat(),