seax_scheme 0.3.0

Scheme compiler for the Seax VM.
use super::*;
use super::NumNode::*;
use super::ExprNode::*;

use svm::cell::Atom::*;
use svm::cell::Inst::*;
use svm::cell::SVMCell::*;

use svm::slist::List::{Cons,Nil};

#[test]
fn test_compile_add() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "+".to_string() }),
        operands: vec![
            NumConst(IntConst(IntNode{ value: 1 })),
            NumConst(IntConst(IntNode{ value: 2 }))
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(SInt(2)),
            InstCell(LDC), AtomCell(SInt(1)),
            InstCell(ADD)
        ])
    )
}

#[test]
fn test_compile_sub() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "-".to_string() }),
        operands: vec![
            NumConst(UIntConst(UIntNode{ value: 9 })),
            NumConst(UIntConst(UIntNode{ value: 9 })),
            NumConst(UIntConst(UIntNode{ value: 9 }))
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(UInt(9)),
            InstCell(LDC), AtomCell(UInt(9)),
            InstCell(SUB),
            InstCell(LDC), AtomCell(UInt(9)),
            InstCell(SUB)
        ])
    )
}

#[test]
fn test_compile_div() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "/".to_string() }),
        operands: vec![
            NumConst(IntConst(IntNode{ value: 1 })),
            NumConst(IntConst(IntNode{ value: 2 })),
            NumConst(IntConst(IntNode{ value: 3 })),
            NumConst(IntConst(IntNode{ value: 4 }))
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(SInt(4)),
            InstCell(LDC), AtomCell(SInt(3)),
            InstCell(DIV),
            InstCell(LDC), AtomCell(SInt(2)),
            InstCell(DIV),
            InstCell(LDC), AtomCell(SInt(1)),
            InstCell(DIV)

        ])
    )
}

#[test]
fn test_compile_mul() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "*".to_string() }),
        operands: vec![
            NumConst(FloatConst(FloatNode{ value: 1f64 })),
            NumConst(FloatConst(FloatNode{ value: 2f64 })),
            NumConst(FloatConst(FloatNode{ value: 3f64 })),
            NumConst(FloatConst(FloatNode{ value: 4f64 }))
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(Float(4f64)),
            InstCell(LDC), AtomCell(Float(3f64)),
            InstCell(MUL),
            InstCell(LDC), AtomCell(Float(2f64)),
            InstCell(MUL),
            InstCell(LDC), AtomCell(Float(1f64)),
            InstCell(MUL)
        ])
    )
}

#[test]
fn test_compile_nested_sexpr() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "+".to_string() }),
        operands: vec![
            NumConst(IntConst(IntNode{ value: 4 })),
            SExpr(SExprNode {
                operator: box Name(NameNode { name: "-".to_string() }),
                operands: vec![
                    NumConst(IntConst(IntNode{ value: 1 })),
                    NumConst(IntConst(IntNode{ value: 2 })),
                    NumConst(IntConst(IntNode{ value: 3 }))
                ]
            })
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(SInt(3)),
            InstCell(LDC), AtomCell(SInt(2)),
            InstCell(SUB),
            InstCell(LDC), AtomCell(SInt(1)),
            InstCell(SUB),
            InstCell(LDC), AtomCell(SInt(4)),
            InstCell(ADD)
        ])
    )
}

#[test]
fn test_compile_gte() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: ">=".to_string() }),
        operands: vec![
            NumConst(FloatConst(FloatNode{ value: 1f64 })),
            NumConst(IntConst(IntNode{ value: 2 })),
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(SInt(2)),
            InstCell(LDC), AtomCell(Float(1f64)),
            InstCell(GTE)
        ])
    )
}

#[test]
fn test_compile_lte() {
    let ast = SExprNode {
        operator: box Name(NameNode { name: "<=".to_string() }),
        operands: vec![
            NumConst(UIntConst(UIntNode{ value: 3 })),
            NumConst(IntConst(IntNode{ value: 2 })),
        ]
    };
    assert_eq!(
        ast.compile(&SymTable::new()),
        Ok(vec![
            InstCell(LDC), AtomCell(SInt(2)),
            InstCell(LDC), AtomCell(UInt(3)),
            InstCell(LTE)
        ])
    )
}

#[test]
fn test_compile_string() {
    assert_eq!(
        StringNode{ value: "a string".to_string() }
            .compile(&SymTable::new()),
        Ok(vec![ListCell(box list!(
            AtomCell(Char('a')),
            AtomCell(Char(' ')),
            AtomCell(Char('s')),
            AtomCell(Char('t')),
            AtomCell(Char('r')),
            AtomCell(Char('i')),
            AtomCell(Char('n')),
            AtomCell(Char('g'))
            ))])
        )
}