Refactor LocatorExpression

This commit is contained in:
evan-schott 2024-03-29 10:32:58 -07:00
parent a92e2814c4
commit 94b5d927d7
4 changed files with 29 additions and 121 deletions

View File

@ -14,31 +14,20 @@
// 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_errors::Result;
use leo_span::{Span, Symbol};
use crate::{simple_node_impl, Node, NodeID};
use serde::{
de::{
Visitor,
{self},
},
Deserialize,
Deserializer,
Serialize,
Serializer,
};
use crate::{simple_node_impl, Node, NodeID, ProgramId};
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
use std::{
collections::BTreeMap,
fmt,
hash::{Hash, Hasher},
};
/// A locator that references an external resource.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct LocatorExpression {
/// The program that the resource is in.
pub program: Symbol,
pub program: ProgramId,
/// The name of the resource.
pub name: Symbol,
/// A span indicating where the locator occurred in the source.
@ -51,7 +40,7 @@ simple_node_impl!(LocatorExpression);
impl LocatorExpression {
/// Constructs a new Locator with `name`, `program` and `id` and a default span.
pub fn new(program: Symbol, name: Symbol, id: NodeID) -> Self {
pub fn new(program: ProgramId, name: Symbol, id: NodeID) -> Self {
Self { program, name, span: Span::default(), id }
}
@ -63,97 +52,11 @@ impl LocatorExpression {
impl fmt::Display for LocatorExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.aleo/{}", self.program, self.name)
write!(f, "{}/{}", self.program, self.name)
}
}
impl fmt::Debug for LocatorExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.aleo/{}", self.program, self.name)
}
}
impl PartialEq for LocatorExpression {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.program == other.program && self.span == other.span
}
}
impl Eq for LocatorExpression {}
impl Hash for LocatorExpression {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.program.hash(state);
self.span.hash(state);
}
}
impl Serialize for LocatorExpression {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
// Converts an element that implements Serialize into a string.
fn to_json_string<E: Serialize, Error: serde::ser::Error>(element: &E) -> Result<String, Error> {
serde_json::to_string(&element).map_err(|e| Error::custom(e.to_string()))
}
// Load the struct elements into a BTreeMap (to preserve serialized ordering of keys).
let mut key: BTreeMap<String, String> = BTreeMap::new();
key.insert("name".to_string(), self.name.to_string());
key.insert("program".to_string(), self.program.to_string());
key.insert("span".to_string(), to_json_string(&self.span)?);
key.insert("id".to_string(), to_json_string(&self.id)?);
// Convert the serialized object into a string for use as a key.
serializer.serialize_str(&to_json_string(&key)?)
}
}
impl<'de> Deserialize<'de> for LocatorExpression {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct LocatorVisitor;
impl Visitor<'_> for LocatorVisitor {
type Value = LocatorExpression;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string encoding the ast Identifier struct")
}
/// Implementation for recovering a string that serializes Locator.
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
// Converts a serialized string into an element that implements Deserialize.
fn to_json_string<'a, D: Deserialize<'a>, Error: serde::de::Error>(
serialized: &'a str,
) -> Result<D, Error> {
serde_json::from_str::<'a>(serialized).map_err(|e| Error::custom(e.to_string()))
}
// Convert the serialized string into a BTreeMap to recover Locator.
let key: BTreeMap<String, String> = to_json_string(value)?;
let name = match key.get("name") {
Some(name) => Symbol::intern(name),
None => return Err(E::custom("missing 'name' in serialized Identifier struct")),
};
let program = match key.get("program") {
Some(program) => Symbol::intern(program),
None => return Err(E::custom("missing 'program' in serialized Identifier struct")),
};
let span: Span = match key.get("span") {
Some(span) => to_json_string(span)?,
None => return Err(E::custom("missing 'span' in serialized Identifier struct")),
};
let id: NodeID = match key.get("id") {
Some(id) => to_json_string(id)?,
None => return Err(E::custom("missing 'id' in serialized Identifier struct")),
};
Ok(LocatorExpression { program, name, span, id })
}
}
deserializer.deserialize_str(LocatorVisitor)
write!(f, "{}/{}", self.program, self.name)
}
}

View File

@ -430,7 +430,7 @@ impl ParserContext<'_> {
}
// Parses an external function call `credits.aleo/transfer()` or locator `token.aleo/accounts`.
fn parse_external_resource(&mut self, expr: Expression) -> Result<Expression> {
fn parse_external_resource(&mut self, expr: Expression, network_span: Span) -> Result<Expression> {
// Eat an external function call.
self.eat(&Token::Div); // todo: Make `/` a more general token.
@ -438,8 +438,8 @@ impl ParserContext<'_> {
let name = self.expect_identifier()?;
// Parse the parent program identifier.
let program: Symbol = match expr {
Expression::Identifier(identifier) => identifier.name,
let program: Identifier = match expr {
Expression::Identifier(identifier) => identifier,
_ => unreachable!("Function called must be preceded by a program identifier."),
};
@ -452,7 +452,10 @@ impl ParserContext<'_> {
if self.token.token != Token::LeftParen {
// Parse an external resource locator.
return Ok(Expression::Locator(LocatorExpression {
program,
program: ProgramId {
name: program,
network: Identifier { name: sym::aleo, span: network_span, id: self.node_builder.next_id() },
},
name: name.name,
span: expr.span() + name.span(),
id: self.node_builder.next_id(),
@ -465,7 +468,7 @@ impl ParserContext<'_> {
Ok(Expression::Call(CallExpression {
span: expr.span() + span,
function: Box::new(Expression::Identifier(name)),
program: Some(program),
program: Some(program.name),
arguments,
id: self.node_builder.next_id(),
}))
@ -494,7 +497,7 @@ impl ParserContext<'_> {
} else if self.eat(&Token::Leo) {
return Err(ParserError::only_aleo_external_calls(expr.span()).into());
} else if self.eat(&Token::Aleo) {
expr = self.parse_external_resource(expr)?;
expr = self.parse_external_resource(expr, self.prev_token.span)?;
} else {
// Parse identifier name.
let name = self.expect_identifier()?;

View File

@ -771,7 +771,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
fn visit_locator(&mut self, input: &'a LocatorExpression, expected: &Self::AdditionalInput) -> Self::Output {
// Check that the locator points to a valid resource in the ST.
if let Some(var) = self.symbol_table.borrow().lookup_variable(Location::new(Some(input.program), input.name)) {
if let Some(var) =
self.symbol_table.borrow().lookup_variable(Location::new(Some(input.program.name.name), input.name))
{
Some(self.assert_and_return_type(var.type_.clone(), expected, input.span()))
} else {
self.emit_err(TypeCheckerError::unknown_sym("variable", input.name, input.span()));

View File

@ -16,16 +16,16 @@ outputs:
bytecode: c44dd5a8d2158e3729310c6e423739cde6f4f8261609820886f26aa09afe707b
errors: ""
warnings: ""
- initial_symbol_table: f1bdf4ae2702708d6d85ba318ad8ff9808124a83f107a19b15f4d30e167e6d11
type_checked_symbol_table: d687b1f3c123bda116691c0b5a1b9a1895f20fa0d88511473a0881fe749ef9b7
unrolled_symbol_table: d687b1f3c123bda116691c0b5a1b9a1895f20fa0d88511473a0881fe749ef9b7
initial_ast: f4f8e8eb75a9ae12e391ee4107b0fd10a2013e768d1ecb742b636b554baf7ae6
unrolled_ast: 365df4c78ec80b1018c3916d6c6c5f166a973ec95f6312b2215e3aa44b6dfef9
ssa_ast: 94499ab484cb507a2a09279e4adbeea903a418ef516cb0a13fadf41e26482a3b
flattened_ast: 41167a9098ff4dcdb91390effc77000faa121a41cd1f4d056f994c8a09f80c28
destructured_ast: 604f5ded275781d99f1b6bcc7443a8b1cadb30c8cce0ccc8abf66b7acc77fc6d
inlined_ast: 604f5ded275781d99f1b6bcc7443a8b1cadb30c8cce0ccc8abf66b7acc77fc6d
dce_ast: 604f5ded275781d99f1b6bcc7443a8b1cadb30c8cce0ccc8abf66b7acc77fc6d
- initial_symbol_table: fbe7b97bd85bd4d788d8973a17a73ef63cb42b389639ee166301a6928d9aa429
type_checked_symbol_table: f712c16610a96ec846141df4068ade8878ddfd8bebc4d1e182b69a4a2b6c81fe
unrolled_symbol_table: f712c16610a96ec846141df4068ade8878ddfd8bebc4d1e182b69a4a2b6c81fe
initial_ast: 443e7342407db51c493d0b22ac4a678c3dec2d285600c58c90f045987d88c683
unrolled_ast: 4d735be74cb434f8e080c4ff9f53585ff7552e7e6974237afb19ebb23b8930de
ssa_ast: c39b19084cdfbc1f78aaeaaa6ddac65d0278cf7c6364427c874015609a710544
flattened_ast: a53f8520f941543dcf9faa21c9de585b2331ebacc062a20855fc809c23087da2
destructured_ast: 05e43dddfc454213755f457a4acb3bf165dab99980811c0ed8d6e959439304c2
inlined_ast: 05e43dddfc454213755f457a4acb3bf165dab99980811c0ed8d6e959439304c2
dce_ast: 05e43dddfc454213755f457a4acb3bf165dab99980811c0ed8d6e959439304c2
bytecode: 1260b31fff8f93549822bd3a3bba846b38ca6dd13eacaf908842384748b4ea4c
errors: ""
warnings: ""