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 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}