Changeset - b7031c27683b
[Not reviewed]
0 1 0
mh - 3 years ago 2022-02-08 15:17:28
contact@maxhenger.nl
WIP: Commit before pending change to scope construction
1 file changed with 65 insertions and 15 deletions:
0 comments (0 inline, 0 general)
src/protocol/parser/pass_rewriting.rs
Show inline comments
 
// TODO: File contains a lot of manual AST element construction. Wherein we have
 
//  (for the first time in this compiler) a lot of fields that have no real
 
//  meaning (e.g. the InputSpan of a AST-transformation). What are we going to
 
//  do with this to make the code and datastructures more easily grokable?
 
//  We could do an intermediate AST structure. But considering how close this
 
//  phase of compilation is to bytecode generation, that might be a lot of busy-
 
//  work with few results. Alternatively we may put the AST elements inside
 
//  a special substructure. We could also force ourselves (and put the
 
//  appropriate comments in the code) to not use certain fields anymore after
 
//  a particular stage of compilation.
 

	
 
use crate::collections::*;
 
use crate::protocol::*;
 

	
 
@@ -96,12 +85,38 @@ impl Visitor for PassRewriting {
 
    // --- Visiting the select statement
 

	
 
    fn visit_select_stmt(&mut self, ctx: &mut Ctx, id: SelectStatementId) -> VisitorResult {
 
        // Utility for the last stage of rewriting process
 
        fn transform_select_case_code(ctx: &mut Ctx, select_id: SelectStatementId, case_index: usize, select_var_id: VariableId) -> (IfStatementId, EndIfStatementId) {
 
            // Retrieve statement IDs associated with case
 
            let case = &ctx.heap[select_id].cases[case_index];
 
            let case_guard_id = case.guard;
 
            let case_body_id = case.block;
 

	
 
            // Create the if-statement for the result of the select statement
 
            let compare_expr_id = create_ast_equality_comparison_expr(ctx, select_var_id, case_index as u64);
 
            let (if_stmt_id, end_if_stmt_id) = create_ast_if_stmt(ctx, compare_expr_id.upcast(), case_body_id, None);
 

	
 
            // Modify body of case to link up to the surrounding statements
 
            // correctly
 
            let case_body = &mut ctx.heap[case_body_id];
 
            let case_end_body_id = case_body.end_block;
 
            case_body.statements.insert(0, case_guard_id);
 

	
 
            let case_end_body = &mut ctx.heap[case_end_body_id];
 
            case_end_body.next = end_if_stmt_id.upcast();
 

	
 
            return (if_stmt_id, end_if_stmt_id)
 
        }
 

	
 
        // We're going to transform the select statement by a block statement
 
        // containing builtin runtime-calls. And to do so we create temporary
 
        // variables and move some other statements around.
 
        let select_stmt = &ctx.heap[id];
 
        let mut total_num_cases = select_stmt.cases.len();
 
        let mut total_num_ports = 0;
 
        let end_select_stmt_id = select_stmt.end_select;
 
        let end_select = &ctx.heap[end_select_stmt_id];
 
        let stmt_id_after_select_stmt = end_select.next;
 

	
 
        // Put heap IDs into temporary buffers to handle borrowing rules
 
        let mut call_id_section = self.call_expr_buffer.start_section();
 
@@ -178,7 +193,7 @@ impl Visitor for PassRewriting {
 

	
 
                    // Create runtime call, then store it
 
                    let runtime_call_expr_id = create_ast_call_expr(ctx, Method::SelectRegisterCasePort, runtime_call_arguments);
 
                    let runtime_call_stmt_id = create_ast_expression_stmt(ctx, runtime_call_expr_id);
 
                    let runtime_call_stmt_id = create_ast_expression_stmt(ctx, runtime_call_expr_id.upcast());
 

	
 
                    transformed_stmts.push(runtime_call_stmt_id.upcast());
 

	
 
@@ -201,11 +216,46 @@ impl Visitor for PassRewriting {
 
        call_id_section.forget();
 
        expr_id_section.forget();
 

	
 
        // Precreate the block statement that will be the replacement of the
 
        // select statement. Do not set its members yet.
 
        let replacement_stmt_id = ctx.heap.alloc_block_statement(|this| BlockStatement{
 
            this,
 
            is_implicit: true,
 
            span: InputSpan::new(),
 
            statements: Vec::new(),
 
            end_block: EndBlockStatementId::new_invalid(),
 
            scope_node: ScopeNode::new_invalid(),
 
            first_unique_id_in_scope: -1,
 
            next_unique_id_in_scope: -1,
 
            locals: Vec::new(),
 
            labels: Vec::new(),
 
            next: StatementId::new_invalid(),
 
        });
 
        let end_block_id = ctx.heap.alloc_end_block_statement(|this| EndBlockStatement{
 
            this,
 
            start_block: replacement_stmt_id,
 
            next: stmt_id_after_select_stmt,
 
        });
 

	
 
        // Now we transform each of the select block case's guard and code into
 
        // a chained if-else statement.
 
        if total_num_cases > 0 {
 
            let cmp_expr_id = create_ast_equality_comparison_expr(ctx, select_variable_id, 0);
 
            let mut (if_stmt_id, end_if_stmt_id) = create_ast_if_statement(ctx, cmp_expr_id.upcast(), )
 
            let (if_stmt_id, end_if_stmt_id) = transform_select_case_code(ctx, id, 0, select_variable_id);
 
            let mut last_if_stmt_id = if_stmt_id;
 
            let mut last_end_if_stmt_id = end_if_stmt_id;
 
            transformed_stmts.push(last_if_stmt_id.upcast());
 

	
 
            for case_index in 1..total_num_cases {
 
                let (if_stmt_id, end_if_stmt_id) = transform_select_case_code(ctx, id, case_index, select_variable_id);
 
                let last_if_stmt = &mut ctx.heap[last_if_stmt_id];
 
                last_if_stmt.false_body = Some(if_stmt_id.upcast());
 

	
 
                // TODO:
 
                //  1. Change scoping such that it is a separate datastructure with separate IDs
 
                //  2. Change statements that contain "implicit scopes" to explicitly point to the appropriate scopes
 
                //  3. Continue here setting the true-body and false-body.
 
                //  4. Figure out how we're going to link everything up again
 
            }
 
        }
 

	
 
        // let block = ctx.heap.alloc_block_statement(|this| BlockStatement{
 
@@ -438,7 +488,7 @@ fn create_ast_variable_declaration_stmt(ctx: &mut Ctx, variable_id: VariableId,
 
    return memory_stmt_id;
 
}
 

	
 
fn create_ast_if_statement(ctx: &mut Ctx, condition_expression_id: ExpressionId, true_body: BlockStatementId, false_body: Option<BlockStatementId>) -> (IfStatementId, EndIfStatementId) {
 
fn create_ast_if_stmt(ctx: &mut Ctx, condition_expression_id: ExpressionId, true_body: BlockStatementId, false_body: Option<BlockStatementId>) -> (IfStatementId, EndIfStatementId) {
 
    // Create if statement and the end-if statement
 
    let if_stmt_id = ctx.heap.alloc_if_statement(|this| IfStatement{
 
        this,
0 comments (0 inline, 0 general)