diff --git a/compiler/ast/src/expressions/locator.rs b/compiler/ast/src/expressions/locator.rs
index 5c0ce3e8c5..91f36599fe 100644
--- a/compiler/ast/src/expressions/locator.rs
+++ b/compiler/ast/src/expressions/locator.rs
@@ -14,31 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-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(&self, state: &mut H) {
- self.name.hash(state);
- self.program.hash(state);
- self.span.hash(state);
- }
-}
-
-impl Serialize for LocatorExpression {
- fn serialize(&self, serializer: S) -> Result {
- // Converts an element that implements Serialize into a string.
- fn to_json_string(element: &E) -> Result {
- 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 = 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>(deserializer: D) -> Result {
- 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(self, value: &str) -> Result {
- // 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 {
- 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 = 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)
}
}
diff --git a/compiler/parser/src/parser/expression.rs b/compiler/parser/src/parser/expression.rs
index 7296cc0ecf..fb4ea55c7c 100644
--- a/compiler/parser/src/parser/expression.rs
+++ b/compiler/parser/src/parser/expression.rs
@@ -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 {
+ fn parse_external_resource(&mut self, expr: Expression, network_span: Span) -> Result {
// 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()?;
diff --git a/compiler/passes/src/type_checking/check_expressions.rs b/compiler/passes/src/type_checking/check_expressions.rs
index 1b39450dec..ab6b7c6ae6 100644
--- a/compiler/passes/src/type_checking/check_expressions.rs
+++ b/compiler/passes/src/type_checking/check_expressions.rs
@@ -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()));
diff --git a/tests/expectations/compiler/mappings/read_external_mapping.out b/tests/expectations/compiler/mappings/read_external_mapping.out
index 263216bd08..a39c306127 100644
--- a/tests/expectations/compiler/mappings/read_external_mapping.out
+++ b/tests/expectations/compiler/mappings/read_external_mapping.out
@@ -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: ""