use phoenix_lang::chunk::FunctionType::Script;
use phoenix_lang::chunk::OpCode::*;
use phoenix_lang::chunk::{Chunk, FunctionChunk, Instr, ModuleChunk};
use phoenix_lang::compiler::{CompilationResult, Compiler};
use phoenix_lang::value::Value;
use phoenix_lang::value::Value::*;
use phoenix_lang::{chunk, VERSION};
fn do_test_functions(
code: &str,
constants: Vec<Value>,
identifiers: Vec<String>,
functions: Vec<FunctionChunk>,
classes: Vec<chunk::ClassChunk>,
) {
let result = Compiler::compile_code(code.to_string(), false, false);
let cur_pos = result.clone().unwrap().cur_pos;
assert_eq!(
result,
Some(CompilationResult {
version: VERSION.to_string(),
modules: vec![ModuleChunk {
name: "main".parse().unwrap(),
main: true,
file: "script".parse().unwrap(),
constants,
identifiers,
functions,
classes,
has_init: false,
}],
modules_table: Default::default(),
cur_pos,
})
);
}
fn do_test(
code: &str,
constants: Vec<Value>,
identifiers: Vec<String>,
functions: Vec<Instr>,
classes: Vec<chunk::ClassChunk>,
) {
do_test_functions(
code,
constants,
identifiers,
vec![FunctionChunk {
arity: 0,
chunk: Chunk { code: functions },
name: None,
upvalues: None,
fn_type: Script,
}],
classes,
);
}
#[test]
fn addition() {
do_test(
"1 + 2;",
vec![Long(1), Long(2)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpAdd,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn subtraction() {
do_test(
"1 - 2;",
vec![Long(1), Long(2)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpSubtract,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn multiplication() {
do_test(
"1 * 2;",
vec![Long(1), Long(2)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpMultiply,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn division() {
do_test(
"1 / 2;",
vec![Long(1), Long(2)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpDivide,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn complex1() {
do_test(
"1 + 2 * 3;",
vec![Long(1), Long(2), Long(3)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpConstant(2),
line_num: 0,
},
Instr {
op_code: OpMultiply,
line_num: 0,
},
Instr {
op_code: OpAdd,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn complex2() {
do_test(
"1 * 2 + 3;",
vec![Long(1), Long(2), Long(3)],
vec![],
vec![
Instr {
op_code: OpConstant(0),
line_num: 0,
},
Instr {
op_code: OpConstant(1),
line_num: 0,
},
Instr {
op_code: OpMultiply,
line_num: 0,
},
Instr {
op_code: OpConstant(2),
line_num: 0,
},
Instr {
op_code: OpAdd,
line_num: 0,
},
Instr {
op_code: OpPop,
line_num: 0,
},
Instr {
op_code: OpNil,
line_num: 0,
},
Instr {
op_code: OpReturn,
line_num: 0,
},
],
vec![],
);
}
#[test]
fn calling_function() {
}
#[test]
fn declare_and_call_function() {
}