Skip to content

Commit

Permalink
Updating documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
troelsfr committed Oct 31, 2023
1 parent e539b49 commit 1144d2c
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 28 deletions.
60 changes: 55 additions & 5 deletions products/bluebell/core/src/intermediate_representation/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,84 @@ use log::info;

use std::mem;

/// Byte Code Generation Process
///
/// The process of generating byte code from Scilla source code involves several steps and transformations.
/// Here is a high-level overview of the process:
///
/// ```plaintext
/// [Scilla source code]
/// |
/// v
/// [Abstract Syntax Tree (AST)]
/// |
/// | (AstConverting)
/// v
/// [Intermediate Representation (IR)]
/// |
/// | (PassManager)
/// v
/// [Optimized Intermediate Representation]
/// |
/// | (EvmBytecodeGenerator)
/// v
/// [EVM Bytecode]
/// ```
///
/// Each arrow (`| v`) represents a transformation or a step in the process.
/// The name in parentheses (e.g., `(AstConverting)`) is the component or the process that performs the transformation.
///
/// 1. Scilla source code is parsed into an Abstract Syntax Tree (AST).
/// 2. The AST is converted into an Intermediate Representation (IR) using the `AstConverting` trait.
/// 3. The IR is optimized using the `PassManager`.
/// 4. The optimized IR is then converted into EVM bytecode using the `EvmBytecodeGenerator`.
///
/// `StackObject` is an enum representing the different types of objects that can be placed on the stack during the conversion process.
/// It includes EnumValue, IrIdentifier, Instruction, VariableDeclaration, FunctionBody, and FunctionBlock.
#[derive(Debug, Clone)]
enum StackObject {
/// Represents an EnumValue object on the stack.
EnumValue(EnumValue),

/// Represents an IrIdentifier object on the stack.
IrIdentifier(IrIdentifier),

/// Represents an Instruction object on the stack.
Instruction(Box<Instruction>),

/// Represents a VariableDeclaration object on the stack.
VariableDeclaration(VariableDeclaration),

/// Represents a FunctionBody object on the stack.
FunctionBody(Box<FunctionBody>),

/// Represents a FunctionBlock object on the stack.
FunctionBlock(Box<FunctionBlock>),
}

/// The `IrEmitter` struct is used for bookkeeping during the conversion of a Scilla AST to an intermediate representation.
/// It implements the `AstConverting` trait, which is a generic trait for AST conversions.
pub struct IrEmitter {
/// Stack of objects used during the conversion process.
stack: Vec<StackObject>,

// Used for transition and procedure
/// Current function block being processed.
current_block: Box<FunctionBlock>,
current_body: Box<FunctionBody>,

// Used for let function declarations
// current_state: Option< Box< ComputableState > >,
/// Current function body being processed.
current_body: Box<FunctionBody>,

// Other
/// Current namespace being processed.
current_namespace: IrIdentifier,

/// Stack of namespaces used during the conversion process.
namespace_stack: Vec<IrIdentifier>,

/// Intermediate representation of the AST.
ir: Box<IntermediateRepresentation>,

/// Source positions of the AST nodes.
source_positions: Vec<(SourcePosition, SourcePosition)>,
}

Expand Down
34 changes: 34 additions & 0 deletions products/bluebell/core/src/intermediate_representation/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,130 @@ use crate::constants::{TraversalResult, TreeTraversalMode};
use crate::intermediate_representation::primitives::*;
use crate::intermediate_representation::symbol_table::SymbolTable;

/// `IrPass` is an abstract pass that is used by the `PassManager` to manipulate the Intermediate Representation (IR).
/// It provides methods to visit and potentially alter different parts of the IR during the traversal.
pub trait IrPass {
/// Visit and potentially alter a symbol kind in the IR.
fn visit_symbol_kind(
&mut self,
mode: TreeTraversalMode,
symbol_kind: &mut IrIndentifierKind,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a symbol name in the IR.
fn visit_symbol_name(
&mut self,
mode: TreeTraversalMode,
symbol_name: &mut IrIdentifier,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter an enum value in the IR.
fn visit_enum_value(
&mut self,
mode: TreeTraversalMode,
enum_value: &mut EnumValue,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a tuple in the IR.
fn visit_tuple(
&mut self,
mode: TreeTraversalMode,
tuple: &mut Tuple,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a variant in the IR.
fn visit_variant(
&mut self,
mode: TreeTraversalMode,
variant: &mut Variant,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a variable declaration in the IR.
fn visit_variable_declaration(
&mut self,
mode: TreeTraversalMode,
var_dec: &mut VariableDeclaration,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter an operation in the IR.
fn visit_operation(
&mut self,
mode: TreeTraversalMode,
operation: &mut Operation,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter an instruction in the IR.
fn visit_instruction(
&mut self,
mode: TreeTraversalMode,
instruction: &mut Instruction,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a function block in the IR.
fn visit_function_block(
&mut self,
mode: TreeTraversalMode,
function_block: &mut FunctionBlock,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a function body in the IR.
fn visit_function_body(
&mut self,
mode: TreeTraversalMode,
function_body: &mut FunctionBody,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a concrete type in the IR.
fn visit_concrete_type(
&mut self,
mode: TreeTraversalMode,
con_type: &mut ConcreteType,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a contract field in the IR.
fn visit_contract_field(
&mut self,
mode: TreeTraversalMode,
function_kind: &mut ContractField,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a function kind in the IR.
fn visit_function_kind(
&mut self,
mode: TreeTraversalMode,
function_kind: &mut FunctionKind,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a concrete function in the IR.
fn visit_concrete_function(
&mut self,
mode: TreeTraversalMode,
con_function: &mut ConcreteFunction,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter a case clause in the IR.
fn visit_case_clause(
&mut self,
mode: TreeTraversalMode,
con_function: &mut CaseClause,
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Visit and potentially alter primitives in the IR.
fn visit_primitives(
// TODO Remove
&mut self,
Expand All @@ -103,6 +134,9 @@ pub trait IrPass {
symbol_table: &mut SymbolTable,
) -> Result<TraversalResult, String>;

/// Initiate the pass.
fn initiate(&mut self);

/// Finalize the pass.
fn finalize(&mut self);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ use crate::intermediate_representation::pass::IrPass;
use crate::intermediate_representation::primitives::*;
use crate::intermediate_representation::symbol_table::SymbolTable;

/// `PassExecutor` is a trait that provides a method for visiting and altering
/// the Intermediate Representation (IR) primitives. It is used by the `PassManager`
/// to traverse the IR and apply transformations.
///
/// The `visit` method takes a mutable reference to the `IrPass` and the `SymbolTable`.
/// It returns a `Result` with the `TraversalResult` and a `String` in case of an error.
/// The traversult result determines how the algorithm proceeds in visiting subsequent nodes
/// in the IR.
pub trait PassExecutor {
fn visit(
&mut self,
Expand All @@ -11,6 +19,33 @@ pub trait PassExecutor {
) -> Result<TraversalResult, String>;
}

/// The `IntermediateRepresentation` struct represents the Scilla Intermediate Representation (IR).
/// It contains definitions for types, contract fields, and functions.
///
/// The `run_pass` method is used to run a pass on the IR. It takes a mutable reference to the `IrPass`
/// and initiates the pass, visits each type definition, contract field, and function definition in the IR,
/// and finalizes the pass. It returns a `Result` with the `TraversalResult` and a `String` in case of an error.
impl IntermediateRepresentation {
pub fn run_pass(&mut self, pass: &mut dyn IrPass) -> Result<TraversalResult, String> {
pass.initiate();

for type_def in &mut self.type_definitions {
type_def.visit(pass, &mut self.symbol_table)?;
}

for contract_field in &mut self.fields_definitions {
contract_field.visit(pass, &mut self.symbol_table)?;
}

for function_def in &mut self.function_definitions {
function_def.visit(pass, &mut self.symbol_table)?;
}

pass.finalize();
Ok(TraversalResult::Continue)
}
}

impl PassExecutor for IrIndentifierKind {
fn visit(
&mut self,
Expand Down Expand Up @@ -474,24 +509,3 @@ impl PassExecutor for CaseClause {
}
}
}

impl IntermediateRepresentation {
pub fn run_pass(&mut self, pass: &mut dyn IrPass) -> Result<TraversalResult, String> {
pass.initiate();

for type_def in &mut self.type_definitions {
type_def.visit(pass, &mut self.symbol_table)?;
}

for contract_field in &mut self.fields_definitions {
contract_field.visit(pass, &mut self.symbol_table)?;
}

for function_def in &mut self.function_definitions {
function_def.visit(pass, &mut self.symbol_table)?;
}

pass.finalize();
Ok(TraversalResult::Continue)
}
}
Loading

0 comments on commit 1144d2c

Please sign in to comment.