leo_ast/common/identifier.rs
1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use crate::{Expression, Node, NodeID, Path, simple_node_impl};
18
19use leo_span::{Span, Symbol};
20
21use snarkvm::{console::program::Identifier as IdentifierCore, prelude::Network};
22use std::{
23 fmt,
24 hash::{Hash, Hasher},
25};
26
27use serde::{Deserialize, Serialize};
28
29/// An identifier in a program.
30///
31/// Attention - When adding or removing fields from this struct,
32/// please remember to update its Serialize and Deserialize implementation
33/// to reflect the new struct instantiation.
34#[derive(Clone, Copy, Default, Serialize, Deserialize)]
35pub struct Identifier {
36 /// The symbol that the user wrote, e.g., `foo`.
37 pub name: Symbol,
38 /// A span locating where the identifier occurred in the source.
39 pub span: Span,
40 /// The ID of the node.
41 pub id: NodeID,
42}
43
44simple_node_impl!(Identifier);
45
46impl Identifier {
47 /// Constructs a new identifier with `name` and `id` and a default span.
48 pub fn new(name: Symbol, id: NodeID) -> Self {
49 Self { name, span: Span::default(), id }
50 }
51
52 /// Check if the Identifier name matches the other name.
53 pub fn matches(&self, other: &Self) -> bool {
54 self.name == other.name
55 }
56}
57
58impl fmt::Display for Identifier {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 self.name.fmt(f)
61 }
62}
63impl fmt::Debug for Identifier {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 self.name.fmt(f)
66 }
67}
68
69impl PartialEq for Identifier {
70 fn eq(&self, other: &Self) -> bool {
71 self.name == other.name && self.span == other.span
72 }
73}
74
75impl Eq for Identifier {}
76
77impl Hash for Identifier {
78 fn hash<H: Hasher>(&self, state: &mut H) {
79 self.name.hash(state);
80 self.span.hash(state);
81 }
82}
83
84impl<N: Network> From<&IdentifierCore<N>> for Identifier {
85 fn from(id: &IdentifierCore<N>) -> Self {
86 Self { name: Symbol::intern(&id.to_string()), span: Default::default(), id: Default::default() }
87 }
88}
89
90// Converts an `Identifier` to a `Path` expression
91// Note that this sets the `absolute_path` field in `Path` to `None`.
92// It's up to the caller of this method to figure out what to do `absolute_path`.
93impl From<Identifier> for Expression {
94 fn from(value: Identifier) -> Self {
95 Expression::Path(crate::Path::from(value))
96 }
97}
98
99// Converts an `Identifier` to a `Path`
100// Note that this sets the `absolute_path` field in `Path` to `None`.
101// It's up to the caller of this method to figure out what to do `absolute_path`.
102impl From<Identifier> for Path {
103 fn from(value: Identifier) -> Self {
104 Path::new(vec![], value, None, value.span, value.id)
105 }
106}