vyre-libs 0.6.3

vyre Category A library ecosystem - pure-IR compositions over vyre-ops hardware primitives
Documentation
use crate::parsing::c::lex::tokens::{TOK_INTEGER, TOK_LPAREN};
use crate::parsing::core::ast::node::{AST_CONST_INT, AST_VAR};
use vyre::ir::{Expr, Node};

use super::operator::{ast_opcode, precedence, should_pop_cached};
use super::STACK_SLOTS_PER_STATEMENT;

pub(super) fn emit_value_leaf(
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
) -> Vec<Node> {
    vec![
        Node::let_bind(
            "ast_idx",
            Expr::atomic_add(out_ast_count, Expr::u32(0), Expr::u32(4)),
        ),
        Node::let_bind(
            "opcode",
            Expr::select(
                Expr::eq(Expr::var("tok"), Expr::u32(TOK_INTEGER)),
                Expr::u32(AST_CONST_INT),
                Expr::u32(AST_VAR),
            ),
        ),
        Node::store(out_ast_nodes, Expr::var("ast_idx"), Expr::var("opcode")),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(1)),
            Expr::u32(u32::MAX),
        ),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(2)),
            Expr::u32(u32::MAX),
        ),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(3)),
            Expr::var("tok_idx"),
        ),
        Node::store(
            scratch_val_stack,
            Expr::add(val_stack_base, Expr::var("v_sp")),
            Expr::var("ast_idx"),
        ),
        Node::assign("v_sp", Expr::add(Expr::var("v_sp"), Expr::u32(1))),
    ]
}

fn reduce_loaded_operator(
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
    opcode: Expr,
) -> Vec<Node> {
    vec![
        Node::assign("v_sp", Expr::sub(Expr::var("v_sp"), Expr::u32(1))),
        Node::let_bind(
            "right_child",
            Expr::load(
                scratch_val_stack,
                Expr::add(val_stack_base.clone(), Expr::var("v_sp")),
            ),
        ),
        Node::assign("v_sp", Expr::sub(Expr::var("v_sp"), Expr::u32(1))),
        Node::let_bind(
            "left_child",
            Expr::load(
                scratch_val_stack,
                Expr::add(val_stack_base.clone(), Expr::var("v_sp")),
            ),
        ),
        Node::let_bind(
            "ast_idx",
            Expr::atomic_add(out_ast_count, Expr::u32(0), Expr::u32(4)),
        ),
        Node::store(out_ast_nodes, Expr::var("ast_idx"), opcode),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(1)),
            Expr::var("left_child"),
        ),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(2)),
            Expr::var("right_child"),
        ),
        Node::store(
            out_ast_nodes,
            Expr::add(Expr::var("ast_idx"), Expr::u32(3)),
            Expr::u32(u32::MAX),
        ),
        Node::store(
            scratch_val_stack,
            Expr::add(val_stack_base, Expr::var("v_sp")),
            Expr::var("ast_idx"),
        ),
        Node::assign("v_sp", Expr::add(Expr::var("v_sp"), Expr::u32(1))),
    ]
}

fn reduce_if_allowed(
    scratch_op_stack: &str,
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
    op_stack_base: Expr,
) -> Vec<Node> {
    let mut body = vec![Node::assign(
        "o_sp",
        Expr::sub(Expr::var("o_sp"), Expr::u32(1)),
    )];
    body.extend(reduce_loaded_operator(
        out_ast_nodes,
        out_ast_count,
        scratch_val_stack,
        val_stack_base,
        Expr::var("top_ast_opcode"),
    ));

    vec![
        Node::let_bind(
            "top_op",
            Expr::load(
                scratch_op_stack,
                Expr::add(op_stack_base, Expr::sub(Expr::var("o_sp"), Expr::u32(1))),
            ),
        ),
        Node::let_bind("top_op_prec", precedence(Expr::var("top_op"))),
        Node::let_bind("top_ast_opcode", ast_opcode(Expr::var("top_op"))),
        Node::let_bind(
            "reduce_now",
            Expr::and(
                should_pop_cached(
                    Expr::var("top_op"),
                    Expr::var("top_op_prec"),
                    Expr::var("tok_prec"),
                    Expr::var("tok_is_assignment"),
                ),
                Expr::ge(Expr::var("v_sp"), Expr::u32(2)),
            ),
        ),
        Node::if_then(Expr::var("reduce_now"), body),
        Node::if_then(
            Expr::not(Expr::var("reduce_now")),
            vec![Node::assign("done_bin", Expr::u32(1))],
        ),
    ]
}

pub(super) fn binary_token_body(
    scratch_op_stack: &str,
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
    op_stack_base: Expr,
) -> Vec<Node> {
    let reduce_one = reduce_if_allowed(
        scratch_op_stack,
        out_ast_nodes,
        out_ast_count,
        scratch_val_stack,
        val_stack_base,
        op_stack_base.clone(),
    );

    vec![
        Node::let_bind("done_bin", Expr::u32(0)),
        Node::loop_for(
            "pop",
            Expr::u32(0),
            Expr::u32(STACK_SLOTS_PER_STATEMENT),
            vec![Node::if_then(
                Expr::eq(Expr::var("done_bin"), Expr::u32(0)),
                vec![
                    Node::if_then(
                        Expr::eq(Expr::var("o_sp"), Expr::u32(0)),
                        vec![Node::assign("done_bin", Expr::u32(1))],
                    ),
                    Node::if_then(Expr::ne(Expr::var("o_sp"), Expr::u32(0)), reduce_one),
                ],
            )],
        ),
        Node::store(
            scratch_op_stack,
            Expr::add(op_stack_base, Expr::var("o_sp")),
            Expr::var("tok"),
        ),
        Node::assign("o_sp", Expr::add(Expr::var("o_sp"), Expr::u32(1))),
    ]
}

pub(super) fn rparen_body(
    scratch_op_stack: &str,
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
    op_stack_base: Expr,
) -> Vec<Node> {
    vec![
        Node::let_bind("done_rp", Expr::u32(0)),
        Node::loop_for(
            "pop",
            Expr::u32(0),
            Expr::u32(STACK_SLOTS_PER_STATEMENT),
            vec![Node::if_then(
                Expr::eq(Expr::var("done_rp"), Expr::u32(0)),
                vec![
                    Node::if_then(
                        Expr::eq(Expr::var("o_sp"), Expr::u32(0)),
                        vec![Node::assign("done_rp", Expr::u32(1))],
                    ),
                    Node::if_then(Expr::ne(Expr::var("o_sp"), Expr::u32(0)), {
                        let mut body = vec![
                            Node::assign("o_sp", Expr::sub(Expr::var("o_sp"), Expr::u32(1))),
                            Node::let_bind(
                                "top_op",
                                Expr::load(
                                    scratch_op_stack,
                                    Expr::add(op_stack_base.clone(), Expr::var("o_sp")),
                                ),
                            ),
                            Node::let_bind("top_ast_opcode", ast_opcode(Expr::var("top_op"))),
                            Node::if_then(
                                Expr::eq(Expr::var("top_op"), Expr::u32(TOK_LPAREN)),
                                vec![Node::assign("done_rp", Expr::u32(1))],
                            ),
                        ];
                        body.push(Node::if_then(
                            Expr::and(
                                Expr::ne(Expr::var("top_op"), Expr::u32(TOK_LPAREN)),
                                Expr::ge(Expr::var("v_sp"), Expr::u32(2)),
                            ),
                            reduce_loaded_operator(
                                out_ast_nodes,
                                out_ast_count,
                                scratch_val_stack,
                                val_stack_base.clone(),
                                Expr::var("top_ast_opcode"),
                            ),
                        ));
                        body
                    }),
                ],
            )],
        ),
    ]
}

pub(super) fn final_sweep_body(
    scratch_op_stack: &str,
    out_ast_nodes: &str,
    out_ast_count: &str,
    scratch_val_stack: &str,
    val_stack_base: Expr,
    op_stack_base: Expr,
) -> Vec<Node> {
    vec![
        Node::let_bind("done_fs", Expr::u32(0)),
        Node::loop_for(
            "pop",
            Expr::u32(0),
            Expr::u32(STACK_SLOTS_PER_STATEMENT),
            vec![Node::if_then(
                Expr::eq(Expr::var("done_fs"), Expr::u32(0)),
                vec![
                    Node::if_then(
                        Expr::eq(Expr::var("o_sp"), Expr::u32(0)),
                        vec![Node::assign("done_fs", Expr::u32(1))],
                    ),
                    Node::if_then(Expr::ne(Expr::var("o_sp"), Expr::u32(0)), {
                        let mut body = vec![
                            Node::assign("o_sp", Expr::sub(Expr::var("o_sp"), Expr::u32(1))),
                            Node::let_bind(
                                "top_op",
                                Expr::load(
                                    scratch_op_stack,
                                    Expr::add(op_stack_base, Expr::var("o_sp")),
                                ),
                            ),
                            Node::let_bind("top_ast_opcode", ast_opcode(Expr::var("top_op"))),
                        ];
                        body.push(Node::if_then(
                            Expr::and(
                                Expr::ne(Expr::var("top_op"), Expr::u32(TOK_LPAREN)),
                                Expr::ge(Expr::var("v_sp"), Expr::u32(2)),
                            ),
                            reduce_loaded_operator(
                                out_ast_nodes,
                                out_ast_count,
                                scratch_val_stack,
                                val_stack_base,
                                Expr::var("top_ast_opcode"),
                            ),
                        ));
                        body
                    }),
                ],
            )],
        ),
    ]
}