yulang-native 0.1.1

Native backend experiments for Yulang
Documentation
use crate::cps_ir::{CpsContinuationId, CpsModule, CpsValueId};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CpsEnvironmentLayout {
    pub functions: Vec<CpsFunctionEnvironmentLayout>,
    pub roots: Vec<CpsFunctionEnvironmentLayout>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CpsFunctionEnvironmentLayout {
    pub name: String,
    pub continuations: Vec<CpsContinuationEnvironmentLayout>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CpsContinuationEnvironmentLayout {
    pub continuation: CpsContinuationId,
    pub slots: Vec<CpsEnvironmentSlot>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CpsEnvironmentSlot {
    pub index: usize,
    pub value: CpsValueId,
}

pub fn layout_cps_environments(module: &CpsModule) -> CpsEnvironmentLayout {
    CpsEnvironmentLayout {
        functions: module
            .functions
            .iter()
            .map(layout_function_environments)
            .collect(),
        roots: module
            .roots
            .iter()
            .map(layout_function_environments)
            .collect(),
    }
}

fn layout_function_environments(
    function: &crate::cps_ir::CpsFunction,
) -> CpsFunctionEnvironmentLayout {
    CpsFunctionEnvironmentLayout {
        name: function.name.clone(),
        continuations: function
            .continuations
            .iter()
            .map(|continuation| CpsContinuationEnvironmentLayout {
                continuation: continuation.id,
                slots: continuation
                    .captures
                    .iter()
                    .copied()
                    .enumerate()
                    .map(|(index, value)| CpsEnvironmentSlot { index, value })
                    .collect(),
            })
            .collect(),
    }
}

#[cfg(test)]
mod tests {
    use crate::cps_ir::{
        CpsContinuation, CpsContinuationId, CpsFunction, CpsModule, CpsShotKind, CpsTerminator,
        CpsValueId,
    };

    use super::*;

    #[test]
    fn assigns_stable_slots_from_continuation_capture_order() {
        let module = CpsModule {
            functions: Vec::new(),
            roots: vec![CpsFunction {
                name: "root".to_string(),
                params: Vec::new(),
                entry: CpsContinuationId(0),
                continuations: vec![CpsContinuation {
                    id: CpsContinuationId(0),
                    params: Vec::new(),
                    captures: vec![CpsValueId(4), CpsValueId(2)],
                    shot_kind: CpsShotKind::MultiShot,
                    stmts: Vec::new(),
                    terminator: CpsTerminator::Return(CpsValueId(4)),
                }],
                handlers: Vec::new(),
            }],
        };

        assert_eq!(
            layout_cps_environments(&module).roots[0].continuations[0].slots,
            vec![
                CpsEnvironmentSlot {
                    index: 0,
                    value: CpsValueId(4),
                },
                CpsEnvironmentSlot {
                    index: 1,
                    value: CpsValueId(2),
                },
            ]
        );
    }
}