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