Skip to main content

scilla_parser/simplified_representation/
emitter.rs

1use crate::{
2    ast::{converting::AstConverting, nodes::*, visitor::AstVisitor},
3    parser::lexer::SourcePosition,
4    simplified_representation::primitives::*,
5    Contract, Field, FieldList, Transition,
6};
7
8use crate::ast::{TraversalResult, TreeTraversalMode};
9
10#[derive(Debug, Clone)]
11enum StackObject {
12    IrIdentifier(SrIdentifier),
13    VariableDeclaration(Field),
14    TypeDefinition(SrType),
15}
16
17/// The `SrEmitter` struct is used for bookkeeping during the conversion of a Scilla AST to a simplified representation.
18/// It implements the `AstConverting` trait, which is a generic trait for AST conversions.
19#[derive(Default)]
20pub struct SrEmitter {
21    stack: Vec<StackObject>,
22    contract: Contract,
23}
24
25impl SrEmitter {
26    fn pop_ir_identifier(&mut self) -> Result<SrIdentifier, String> {
27        let ret = if let Some(candidate) = self.stack.pop() {
28            match candidate {
29                StackObject::IrIdentifier(n) => n,
30                _ => {
31                    return Err(format!("Expected symbol name, but found {:?}.", candidate));
32                }
33            }
34        } else {
35            return Err("Expected symbol name, but found nothing.".to_string());
36        };
37
38        Ok(ret)
39    }
40
41    fn pop_variable_declaration(&mut self) -> Result<Field, String> {
42        let ret = if let Some(candidate) = self.stack.pop() {
43            match candidate {
44                StackObject::VariableDeclaration(n) => n,
45                _ => {
46                    return Err(format!(
47                        "Expected variable declaration, but found {:?}.",
48                        candidate
49                    ));
50                }
51            }
52        } else {
53            return Err("Expected variable declaration, but found nothing.".to_string());
54        };
55
56        Ok(ret)
57    }
58
59    fn pop_type_definition(&mut self) -> Result<SrType, String> {
60        let ret = if let Some(candidate) = self.stack.pop() {
61            match candidate {
62                StackObject::TypeDefinition(n) => n,
63                _ => {
64                    return Err(format!(
65                        "Expected type definition, but found {:?}.",
66                        candidate
67                    ));
68                }
69            }
70        } else {
71            return Err("Expected type definition, but found nothing.".to_string());
72        };
73
74        Ok(ret)
75    }
76    pub fn emit(mut self, node: &NodeProgram) -> Result<Contract, String> {
77        node.contract_definition.visit(&mut self)?;
78        Ok(self.contract)
79    }
80}
81
82impl AstConverting for SrEmitter {
83    fn push_source_position(&mut self, _start: &SourcePosition, _end: &SourcePosition) {}
84
85    fn pop_source_position(&mut self) {}
86
87    fn emit_byte_str(
88        &mut self,
89        _mode: TreeTraversalMode,
90        _node: &NodeByteStr,
91    ) -> Result<TraversalResult, String> {
92        Ok(TraversalResult::Continue)
93    }
94    fn emit_type_name_identifier(
95        &mut self,
96        mode: TreeTraversalMode,
97        node: &NodeTypeNameIdentifier,
98    ) -> Result<TraversalResult, String> {
99        match mode {
100            TreeTraversalMode::Enter => match node {
101                NodeTypeNameIdentifier::ByteStringType(bytestr) => {
102                    let symbol = SrIdentifier::new(bytestr.to_string(), SrIdentifierKind::Unknown);
103
104                    self.stack.push(StackObject::IrIdentifier(symbol));
105                }
106                NodeTypeNameIdentifier::EventType => {}
107                NodeTypeNameIdentifier::TypeOrEnumLikeIdentifier(name) => {
108                    let symbol = SrIdentifier::new(name.to_string(), SrIdentifierKind::Unknown);
109
110                    self.stack.push(StackObject::IrIdentifier(symbol));
111                }
112            },
113            TreeTraversalMode::Exit => (),
114        }
115        Ok(TraversalResult::Continue)
116    }
117    fn emit_imported_name(
118        &mut self,
119        _mode: TreeTraversalMode,
120        _node: &NodeImportedName,
121    ) -> Result<TraversalResult, String> {
122        unimplemented!();
123    }
124    fn emit_import_declarations(
125        &mut self,
126        _mode: TreeTraversalMode,
127        _node: &NodeImportDeclarations,
128    ) -> Result<TraversalResult, String> {
129        unimplemented!();
130    }
131    fn emit_meta_identifier(
132        &mut self,
133        _mode: TreeTraversalMode,
134        _node: &NodeMetaIdentifier,
135    ) -> Result<TraversalResult, String> {
136        Ok(TraversalResult::Continue)
137    }
138    fn emit_variable_identifier(
139        &mut self,
140        _mode: TreeTraversalMode,
141        _node: &NodeVariableIdentifier,
142    ) -> Result<TraversalResult, String> {
143        Ok(TraversalResult::SkipChildren)
144    }
145    fn emit_builtin_arguments(
146        &mut self,
147        _mode: TreeTraversalMode,
148        _node: &NodeBuiltinArguments,
149    ) -> Result<TraversalResult, String> {
150        unimplemented!();
151    }
152    fn emit_type_map_key(
153        &mut self,
154        _mode: TreeTraversalMode,
155        node: &NodeTypeMapKey,
156    ) -> Result<TraversalResult, String> {
157        match node {
158            NodeTypeMapKey::GenericMapKey(key) => key.visit(self)?,
159            NodeTypeMapKey::EnclosedGenericId(key) => key.visit(self)?,
160            NodeTypeMapKey::EnclosedAddressMapKeyType(key) => key.visit(self)?,
161            NodeTypeMapKey::AddressMapKeyType(key) => key.visit(self)?,
162        };
163        Ok(TraversalResult::SkipChildren)
164    }
165    fn emit_type_map_value(
166        &mut self,
167        mode: TreeTraversalMode,
168        node: &NodeTypeMapValue,
169    ) -> Result<TraversalResult, String> {
170        match mode {
171            TreeTraversalMode::Enter => {
172                match node {
173                    NodeTypeMapValue::MapValueTypeOrEnumLikeIdentifier(value) => {
174                        value.visit(self)?;
175                        let value = self.pop_ir_identifier()?;
176                        let key = self.pop_ir_identifier()?;
177                        let map = SrType {
178                            main_type: "Map".to_string(),
179                            sub_types: vec![key.into(), value.into()],
180                            address_type: None,
181                        };
182                        self.stack.push(StackObject::TypeDefinition(map));
183                    }
184                    NodeTypeMapValue::MapKeyValue(value) => {
185                        value.visit(self)?;
186                    }
187                    NodeTypeMapValue::MapValueParenthesizedType(value) => {
188                        value.visit(self)?;
189                        let value = self.pop_type_definition()?;
190                        let key = self.pop_ir_identifier()?;
191                        let map = SrType {
192                            main_type: "Map".to_string(),
193                            sub_types: vec![key.into(), value],
194                            address_type: None,
195                        };
196                        self.stack.push(StackObject::TypeDefinition(map));
197                    }
198                    NodeTypeMapValue::MapValueAddressType(_value) => unimplemented!(),
199                };
200            }
201            TreeTraversalMode::Exit => {}
202        }
203        Ok(TraversalResult::SkipChildren)
204    }
205    fn emit_type_argument(
206        &mut self,
207        _mode: TreeTraversalMode,
208        node: &NodeTypeArgument,
209    ) -> Result<TraversalResult, String> {
210        match node {
211            NodeTypeArgument::EnclosedTypeArgument(t) => {
212                let _ = t.visit(self)?;
213            }
214            NodeTypeArgument::GenericTypeArgument(n) => {
215                let _ = n.visit(self)?;
216                let identifier = self.pop_ir_identifier()?;
217                self.stack
218                    .push(StackObject::TypeDefinition(identifier.into()));
219            }
220            NodeTypeArgument::TemplateTypeArgument(_) => {
221                unimplemented!();
222            }
223            NodeTypeArgument::AddressTypeArgument(_) => {
224                unimplemented!();
225            }
226            NodeTypeArgument::MapTypeArgument(_, _) => {
227                unimplemented!();
228            }
229        }
230        Ok(TraversalResult::SkipChildren)
231    }
232    fn emit_scilla_type(
233        &mut self,
234        _mode: TreeTraversalMode,
235        node: &NodeScillaType,
236    ) -> Result<TraversalResult, String> {
237        match node {
238            NodeScillaType::GenericTypeWithArgs(lead, args) => {
239                let _ = lead.visit(self)?;
240                let identifier = self.pop_ir_identifier()?;
241                self.stack
242                    .push(StackObject::TypeDefinition(identifier.into()));
243                if !args.is_empty() {
244                    let mut main_type = self.pop_type_definition()?;
245                    for arg in args {
246                        let _ = arg.visit(self)?;
247                        let sub_type = self.pop_type_definition()?;
248                        main_type.push_sub_type(sub_type);
249                    }
250                    self.stack.push(StackObject::TypeDefinition(main_type));
251                }
252            }
253            NodeScillaType::MapType(key, value) => {
254                let _ = key.visit(self)?;
255                let _ = value.visit(self)?;
256            }
257            NodeScillaType::FunctionType(_a, _b) => {
258                unimplemented!()
259            }
260
261            NodeScillaType::PolyFunctionType(_name, _a) => {
262                unimplemented!()
263            }
264            NodeScillaType::EnclosedType(a) => {
265                let _ = (*a).visit(self)?;
266            }
267            NodeScillaType::ScillaAddresseType(a) => {
268                let _ = (*a).visit(self)?;
269            }
270            NodeScillaType::TypeVarType(_name) => {
271                unimplemented!()
272            }
273        };
274        Ok(TraversalResult::SkipChildren)
275    }
276
277    fn emit_type_map_entry(
278        &mut self,
279        _mode: TreeTraversalMode,
280        _node: &NodeTypeMapEntry,
281    ) -> Result<TraversalResult, String> {
282        Ok(TraversalResult::Continue)
283    }
284    fn emit_address_type_field(
285        &mut self,
286        _mode: TreeTraversalMode,
287        node: &NodeAddressTypeField,
288    ) -> Result<TraversalResult, String> {
289        if let NodeVariableIdentifier::VariableName(n) = &node.identifier.node {
290            node.type_name.visit(self)?;
291            let typename = self.pop_type_definition()?;
292            let s = StackObject::VariableDeclaration(Field::new(&n.node, typename.into()));
293            self.stack.push(s);
294        }
295        Ok(TraversalResult::SkipChildren)
296    }
297    fn emit_address_type(
298        &mut self,
299        _mode: TreeTraversalMode,
300        node: &NodeAddressType,
301    ) -> Result<TraversalResult, String> {
302        node.identifier.visit(self)?;
303        let identifier = self.pop_ir_identifier()?;
304        self.stack
305            .push(StackObject::TypeDefinition(identifier.into()));
306        let mut main_type = self.pop_type_definition()?;
307        let mut fields = vec![];
308        for field in &node.address_fields {
309            field.visit(self)?;
310            let field = self.pop_variable_declaration()?;
311            fields.push(field);
312        }
313        main_type.address_type = Some(AddressType {
314            type_name: node.type_name.node.clone(),
315            fields: FieldList(fields),
316        });
317        self.stack.push(StackObject::TypeDefinition(main_type));
318        Ok(TraversalResult::SkipChildren)
319    }
320
321    fn emit_full_expression(
322        &mut self,
323        _mode: TreeTraversalMode,
324        _node: &NodeFullExpression,
325    ) -> Result<TraversalResult, String> {
326        Ok(TraversalResult::SkipChildren)
327    }
328
329    fn emit_message_entry(
330        &mut self,
331        _mode: TreeTraversalMode,
332        _node: &NodeMessageEntry,
333    ) -> Result<TraversalResult, String> {
334        unimplemented!();
335    }
336    fn emit_pattern_match_expression_clause(
337        &mut self,
338        _mode: TreeTraversalMode,
339        _node: &NodePatternMatchExpressionClause,
340    ) -> Result<TraversalResult, String> {
341        unimplemented!();
342    }
343    fn emit_atomic_expression(
344        &mut self,
345        _mode: TreeTraversalMode,
346        _node: &NodeAtomicExpression,
347    ) -> Result<TraversalResult, String> {
348        unimplemented!();
349    }
350    fn emit_contract_type_arguments(
351        &mut self,
352        _mode: TreeTraversalMode,
353        _node: &NodeContractTypeArguments,
354    ) -> Result<TraversalResult, String> {
355        unimplemented!();
356    }
357    fn emit_value_literal(
358        &mut self,
359        _mode: TreeTraversalMode,
360        _node: &NodeValueLiteral,
361    ) -> Result<TraversalResult, String> {
362        Ok(TraversalResult::SkipChildren)
363    }
364    fn emit_map_access(
365        &mut self,
366        _mode: TreeTraversalMode,
367        _node: &NodeMapAccess,
368    ) -> Result<TraversalResult, String> {
369        unimplemented!();
370    }
371    fn emit_pattern(
372        &mut self,
373        _mode: TreeTraversalMode,
374        _node: &NodePattern,
375    ) -> Result<TraversalResult, String> {
376        Ok(TraversalResult::SkipChildren)
377    }
378    fn emit_argument_pattern(
379        &mut self,
380        _mode: TreeTraversalMode,
381        _node: &NodeArgumentPattern,
382    ) -> Result<TraversalResult, String> {
383        unimplemented!();
384    }
385    fn emit_pattern_match_clause(
386        &mut self,
387        _mode: TreeTraversalMode,
388        _node: &NodePatternMatchClause,
389    ) -> Result<TraversalResult, String> {
390        unimplemented!();
391    }
392    fn emit_blockchain_fetch_arguments(
393        &mut self,
394        _mode: TreeTraversalMode,
395        _node: &NodeBlockchainFetchArguments,
396    ) -> Result<TraversalResult, String> {
397        unimplemented!();
398    }
399
400    fn emit_statement(
401        &mut self,
402        _mode: TreeTraversalMode,
403        _node: &NodeStatement,
404    ) -> Result<TraversalResult, String> {
405        Ok(TraversalResult::SkipChildren)
406    }
407
408    fn emit_remote_fetch_statement(
409        &mut self,
410        _mode: TreeTraversalMode,
411        _node: &NodeRemoteFetchStatement,
412    ) -> Result<TraversalResult, String> {
413        unimplemented!();
414    }
415    fn emit_component_id(
416        &mut self,
417        _mode: TreeTraversalMode,
418        node: &NodeComponentId,
419    ) -> Result<TraversalResult, String> {
420        match node {
421            NodeComponentId::WithRegularId(name) => {
422                self.stack.push(StackObject::IrIdentifier(SrIdentifier {
423                    unresolved: name.to_string(),
424                    resolved: None,
425                    type_reference: None,
426                    kind: SrIdentifierKind::ComponentName,
427                    is_definition: false,
428                }));
429            }
430            NodeComponentId::WithTypeLikeName(name) => {
431                self.stack.push(StackObject::IrIdentifier(SrIdentifier {
432                    unresolved: name.to_string(),
433                    resolved: None,
434                    type_reference: None,
435                    kind: SrIdentifierKind::ComponentName,
436                    is_definition: false,
437                }));
438            }
439        }
440
441        Ok(TraversalResult::SkipChildren)
442    }
443
444    fn emit_component_parameters(
445        &mut self,
446        mode: TreeTraversalMode,
447        node: &NodeComponentParameters,
448    ) -> Result<TraversalResult, String> {
449        match mode {
450            TreeTraversalMode::Enter => {
451                for param in node.parameters.iter() {
452                    let _ = param.visit(self)?;
453                    let init_param = self.pop_variable_declaration()?;
454                    self.contract.init_params.push(init_param);
455                }
456            }
457            TreeTraversalMode::Exit => {}
458        }
459        Ok(TraversalResult::Continue)
460    }
461
462    fn emit_parameter_pair(
463        &mut self,
464        _mode: TreeTraversalMode,
465        _node: &NodeParameterPair,
466    ) -> Result<TraversalResult, String> {
467        // Deliberate pass through
468        Ok(TraversalResult::Continue)
469    }
470
471    fn emit_component_body(
472        &mut self,
473        _mode: TreeTraversalMode,
474        _node: &NodeComponentBody,
475    ) -> Result<TraversalResult, String> {
476        Ok(TraversalResult::SkipChildren)
477    }
478
479    fn emit_statement_block(
480        &mut self,
481        _node: TreeTraversalMode,
482        _mode: &NodeStatementBlock,
483    ) -> Result<TraversalResult, String> {
484        Ok(TraversalResult::Continue)
485    }
486    fn emit_typed_identifier(
487        &mut self,
488        _mode: TreeTraversalMode,
489        node: &NodeTypedIdentifier,
490    ) -> Result<TraversalResult, String> {
491        let name = node.identifier_name.clone();
492        let _ = node.annotation.visit(self)?;
493
494        let typename = self.pop_type_definition()?;
495
496        let s = StackObject::VariableDeclaration(Field::new(&name.node, typename.into()));
497        self.stack.push(s);
498
499        Ok(TraversalResult::SkipChildren)
500    }
501    fn emit_type_annotation(
502        &mut self,
503        _mode: TreeTraversalMode,
504        _node: &NodeTypeAnnotation,
505    ) -> Result<TraversalResult, String> {
506        // Pass through
507        Ok(TraversalResult::Continue)
508    }
509
510    fn emit_program(
511        &mut self,
512        _mode: TreeTraversalMode,
513        _node: &NodeProgram,
514    ) -> Result<TraversalResult, String> {
515        Ok(TraversalResult::Continue)
516    }
517
518    fn emit_library_definition(
519        &mut self,
520        _mode: TreeTraversalMode,
521        _node: &NodeLibraryDefinition,
522    ) -> Result<TraversalResult, String> {
523        unimplemented!()
524    }
525
526    fn emit_library_single_definition(
527        &mut self,
528        _mode: TreeTraversalMode,
529        _node: &NodeLibrarySingleDefinition,
530    ) -> Result<TraversalResult, String> {
531        unimplemented!()
532    }
533
534    fn emit_contract_definition(
535        &mut self,
536        _mode: TreeTraversalMode,
537        node: &NodeContractDefinition,
538    ) -> Result<TraversalResult, String> {
539        let _ = node.contract_name.visit(self)?;
540        self.contract.name = node.contract_name.to_string();
541
542        let _ = node.parameters.visit(self)?;
543
544        if let Some(constraint) = &node.constraint {
545            let _ = constraint.visit(self)?;
546        }
547
548        for field in node.fields.iter() {
549            let _ = field.visit(self)?;
550        }
551
552        for component in node.components.iter() {
553            let _ = component.visit(self)?;
554        }
555
556        Ok(TraversalResult::SkipChildren)
557    }
558
559    fn emit_contract_field(
560        &mut self,
561        _mode: TreeTraversalMode,
562        node: &NodeContractField,
563    ) -> Result<TraversalResult, String> {
564        let _ = node.typed_identifier.visit(self)?;
565
566        let field = self.pop_variable_declaration()?;
567        let _ = node.right_hand_side.visit(self)?;
568
569        self.contract.fields.push(field);
570
571        Ok(TraversalResult::SkipChildren)
572    }
573    fn emit_with_constraint(
574        &mut self,
575        _mode: TreeTraversalMode,
576        _node: &NodeWithConstraint,
577    ) -> Result<TraversalResult, String> {
578        Ok(TraversalResult::Continue)
579    }
580    fn emit_component_definition(
581        &mut self,
582        _mode: TreeTraversalMode,
583        _node: &NodeComponentDefinition,
584    ) -> Result<TraversalResult, String> {
585        Ok(TraversalResult::Continue)
586    }
587    fn emit_procedure_definition(
588        &mut self,
589        _mode: TreeTraversalMode,
590        _node: &NodeProcedureDefinition,
591    ) -> Result<TraversalResult, String> {
592        Ok(TraversalResult::SkipChildren)
593    }
594
595    fn emit_transition_definition(
596        &mut self,
597        _mode: TreeTraversalMode,
598        node: &NodeTransitionDefinition,
599    ) -> Result<TraversalResult, String> {
600        // Enter
601        let _ = node.name.visit(self)?;
602
603        let arguments = node
604            .parameters
605            .node
606            .parameters
607            .iter()
608            .map(|arg| {
609                let _ = arg.visit(self)?;
610                self.pop_variable_declaration()
611            })
612            .collect::<Result<Vec<Field>, _>>()?;
613
614        let mut function_name = self.pop_ir_identifier()?;
615        assert!(function_name.kind == SrIdentifierKind::ComponentName);
616        function_name.kind = SrIdentifierKind::TransitionName;
617        function_name.is_definition = true;
618
619        self.contract.transitions.push(Transition::new(
620            &function_name.unresolved,
621            FieldList(arguments),
622        ));
623
624        Ok(TraversalResult::SkipChildren)
625    }
626
627    fn emit_type_alternative_clause(
628        &mut self,
629        _mode: TreeTraversalMode,
630        _node: &NodeTypeAlternativeClause,
631    ) -> Result<TraversalResult, String> {
632        Ok(TraversalResult::SkipChildren)
633    }
634    fn emit_type_map_value_arguments(
635        &mut self,
636        mode: TreeTraversalMode,
637        node: &NodeTypeMapValueArguments,
638    ) -> Result<TraversalResult, String> {
639        match mode {
640            TreeTraversalMode::Enter => {
641                match node {
642                    NodeTypeMapValueArguments::EnclosedTypeMapValue(_) => todo!(),
643                    NodeTypeMapValueArguments::GenericMapValueArgument(g) => {
644                        g.visit(self)?;
645                        let identifier = self.pop_ir_identifier()?;
646                        self.stack
647                            .push(StackObject::TypeDefinition(identifier.into()));
648                    }
649                    NodeTypeMapValueArguments::MapKeyValueType(_, _) => todo!(),
650                };
651            }
652            TreeTraversalMode::Exit => (),
653        }
654        Ok(TraversalResult::SkipChildren)
655    }
656    fn emit_type_map_value_allowing_type_arguments(
657        &mut self,
658        mode: TreeTraversalMode,
659        node: &NodeTypeMapValueAllowingTypeArguments,
660    ) -> Result<TraversalResult, String> {
661        match mode {
662            TreeTraversalMode::Enter => {
663                match node {
664                    NodeTypeMapValueAllowingTypeArguments::TypeMapValueNoArgs(m) => {
665                        m.visit(self)?;
666                    }
667                    NodeTypeMapValueAllowingTypeArguments::TypeMapValueWithArgs(m, args) => {
668                        m.visit(self)?;
669                        let identifier = self.pop_ir_identifier()?;
670                        self.stack
671                            .push(StackObject::TypeDefinition(identifier.into()));
672                        if !args.is_empty() {
673                            let mut main_type = self.pop_type_definition()?;
674                            for arg in args {
675                                let _ = arg.visit(self)?;
676                                let sub_type = self.pop_type_definition()?;
677                                main_type.push_sub_type(sub_type);
678                            }
679                            self.stack.push(StackObject::TypeDefinition(main_type));
680                        }
681                    }
682                };
683            }
684            TreeTraversalMode::Exit => (),
685        }
686        Ok(TraversalResult::SkipChildren)
687    }
688}