Skip to main content

rue_hir/
symbol.rs

1use std::fmt;
2
3use id_arena::Id;
4use indexmap::IndexMap;
5use rue_diagnostic::Name;
6use rue_types::TypeId;
7
8use crate::{HirId, ScopeId, Value};
9
10pub type SymbolId = Id<Symbol>;
11
12#[derive(Debug, Clone)]
13pub enum Symbol {
14    Unresolved,
15    Module(ModuleSymbol),
16    Function(FunctionSymbol),
17    Builtin(Builtin),
18    Parameter(ParameterSymbol),
19    Constant(ConstantSymbol),
20    Binding(BindingSymbol),
21}
22
23impl Symbol {
24    pub fn name(&self) -> Option<Name> {
25        match self {
26            Self::Unresolved => None,
27            Self::Module(module) => module.name.clone(),
28            Self::Function(function) => function.name.clone(),
29            Self::Builtin(builtin) => Some(Name::new(builtin.to_string(), None)),
30            Self::Parameter(parameter) => parameter.name.clone(),
31            Self::Constant(constant) => constant.name.clone(),
32            Self::Binding(binding) => binding.name.clone(),
33        }
34    }
35}
36
37#[derive(Debug, Clone)]
38pub struct ModuleSymbol {
39    pub name: Option<Name>,
40    pub scope: ScopeId,
41    pub declarations: ModuleDeclarations,
42}
43
44#[derive(Debug, Default, Clone)]
45pub struct ModuleDeclarations {
46    pub types: Vec<(TypeId, ScopeId)>,
47    pub symbols: Vec<SymbolId>,
48    pub modules: Vec<SymbolId>,
49}
50
51#[derive(Debug, Clone)]
52pub struct FunctionSymbol {
53    pub name: Option<Name>,
54    pub ty: TypeId,
55    pub scope: ScopeId,
56    pub vars: Vec<TypeId>,
57    pub parameters: IndexMap<String, SymbolId>,
58    pub nil_terminated: bool,
59    pub return_type: TypeId,
60    pub body: HirId,
61    pub kind: FunctionKind,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65pub enum FunctionKind {
66    BinaryTree,
67    Sequential,
68    External,
69    Inline,
70}
71
72#[derive(Debug, Clone)]
73pub struct ParameterSymbol {
74    pub name: Option<Name>,
75    pub ty: TypeId,
76}
77
78#[derive(Debug, Clone)]
79pub struct ConstantSymbol {
80    pub name: Option<Name>,
81    pub value: Value,
82    pub inline: bool,
83}
84
85#[derive(Debug, Clone)]
86pub struct BindingSymbol {
87    pub name: Option<Name>,
88    pub value: Value,
89    pub inline: bool,
90}
91
92#[derive(Debug, Clone, Copy)]
93pub enum Builtin {
94    Sha256 { inline: bool },
95    Keccak256 { inline: bool },
96    Concat,
97    CoinId,
98    Substr,
99    Sum,
100    Difference,
101    Product,
102    Divmod,
103    Modpow,
104    Any,
105    All,
106    PubkeyForExp,
107    G1Sum,
108    G1Difference,
109    G2Sum,
110    G2Difference,
111    G1Map,
112    G2Map,
113    BlsPairingIdentity,
114    BlsVerify,
115    Secp256K1Verify,
116    Secp256R1Verify,
117}
118
119impl Builtin {
120    /// Human readable signatures for each of the ways this builtin can be called, used for
121    /// documentation. Builtins are type checked specially, so they don't have a function type.
122    pub fn signatures(&self) -> &'static [&'static str] {
123        match self {
124            Self::Sha256 { inline: false } | Self::Keccak256 { inline: false } => &[
125                "(value: Bytes) -> Bytes32",
126                "(...values: List<Bytes>) -> Bytes32",
127            ],
128            Self::Sha256 { inline: true } | Self::Keccak256 { inline: true } => {
129                &["(value: Bytes) -> Bytes32"]
130            }
131            Self::Concat => &["(values: List<Bytes>) -> Bytes"],
132            Self::CoinId => {
133                &["(parent_coin_id: Bytes, puzzle_hash: Bytes, amount: Int) -> Bytes32"]
134            }
135            Self::Substr => &[
136                "(value: Bytes, start: Int) -> Bytes",
137                "(value: Bytes, start: Int, end: Int) -> Bytes",
138            ],
139            Self::Sum | Self::Difference | Self::Product => &["(values: List<Int>) -> Int"],
140            Self::Divmod => &["(numerator: Int, denominator: Int) -> (Int, Int)"],
141            Self::Modpow => &["(base: Int, exponent: Int, modulus: Int) -> Int"],
142            Self::Any | Self::All => &["(values: List<Bool>) -> Bool"],
143            Self::PubkeyForExp => &["(exponent: Int | Bytes32) -> PublicKey"],
144            Self::G1Sum | Self::G1Difference => &["(values: List<PublicKey>) -> PublicKey"],
145            Self::G2Sum | Self::G2Difference => &["(values: List<Signature>) -> Signature"],
146            Self::G1Map => &[
147                "(data: Bytes) -> PublicKey",
148                "(data: Bytes, dst: Bytes) -> PublicKey",
149            ],
150            Self::G2Map => &[
151                "(data: Bytes) -> Signature",
152                "(data: Bytes, dst: Bytes) -> Signature",
153            ],
154            Self::BlsPairingIdentity => &[
155                "(g1: PublicKey, g2: Signature, ...) -> nil",
156                "(...pairs: AlternatingList<PublicKey, Signature>) -> nil",
157            ],
158            Self::BlsVerify => &[
159                "(signature: Signature, public_key: PublicKey, message: Bytes, ...) -> nil",
160                "(signature: Signature, ...pairs: AlternatingList<PublicKey, Bytes>) -> nil",
161            ],
162            Self::Secp256K1Verify => {
163                &["(public_key: K1PublicKey, message_hash: Bytes32, signature: K1Signature) -> nil"]
164            }
165            Self::Secp256R1Verify => {
166                &["(public_key: R1PublicKey, message_hash: Bytes32, signature: R1Signature) -> nil"]
167            }
168        }
169    }
170}
171
172impl fmt::Display for Builtin {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        write!(
175            f,
176            "{}",
177            match self {
178                Self::Sha256 { inline } =>
179                    if *inline {
180                        "sha256_inline"
181                    } else {
182                        "sha256"
183                    },
184                Self::Keccak256 { inline } =>
185                    if *inline {
186                        "keccak256_inline"
187                    } else {
188                        "keccak256"
189                    },
190                Self::Concat => "concat",
191                Self::CoinId => "coinid",
192                Self::Substr => "substr",
193                Self::Sum => "sum",
194                Self::Difference => "difference",
195                Self::Product => "product",
196                Self::Divmod => "divmod",
197                Self::Modpow => "modpow",
198                Self::Any => "any",
199                Self::All => "all",
200                Self::PubkeyForExp => "pubkey_for_exp",
201                Self::G1Sum => "g1_sum",
202                Self::G1Difference => "g1_difference",
203                Self::G2Sum => "g2_sum",
204                Self::G2Difference => "g2_difference",
205                Self::G1Map => "g1_map",
206                Self::G2Map => "g2_map",
207                Self::BlsPairingIdentity => "bls_pairing_identity",
208                Self::BlsVerify => "bls_verify",
209                Self::Secp256K1Verify => "secp256k1_verify",
210                Self::Secp256R1Verify => "secp256r1_verify",
211            }
212        )
213    }
214}