1
0

Remove types from chunks; Add new tests

This commit is contained in:
Jeff 2024-12-02 05:59:01 -05:00
parent eb083c2972
commit 636bd7ce5b
17 changed files with 539 additions and 447 deletions

View File

@ -18,7 +18,7 @@ pub struct Chunk {
name: Option<String>,
r#type: FunctionType,
instructions: Vec<(Instruction, Type, Span)>,
instructions: Vec<(Instruction, Span)>,
constants: Vec<ConcreteValue>,
locals: Vec<Local>,
}
@ -41,7 +41,7 @@ impl Chunk {
pub fn with_data(
name: Option<String>,
r#type: FunctionType,
instructions: Vec<(Instruction, Type, Span)>,
instructions: Vec<(Instruction, Span)>,
constants: Vec<ConcreteValue>,
locals: Vec<Local>,
) -> Self {
@ -74,7 +74,7 @@ impl Chunk {
&self.constants
}
pub fn instructions(&self) -> &Vec<(Instruction, Type, Span)> {
pub fn instructions(&self) -> &Vec<(Instruction, Span)> {
&self.instructions
}

View File

@ -112,11 +112,16 @@ impl<'src> Compiler<'src> {
value_parameters,
return_type: Box::new(self.return_type.unwrap_or(Type::None)),
};
let instructions = self
.instructions
.into_iter()
.map(|(i, _, s)| (i, s))
.collect();
Chunk::with_data(
self.self_name,
r#type,
self.instructions,
instructions,
self.constants,
self.locals,
)

View File

@ -47,8 +47,8 @@ use crate::{value::ConcreteValue, Chunk, Local};
const INSTRUCTION_HEADER: [&str; 4] = [
"Instructions",
"------------",
" i POSITION OPERATION TYPE INFO ",
"--- ---------- ------------- -------------- --------------------------------",
" i POSITION OPERATION INFO ",
"--- ---------- ------------- --------------------------------",
];
const CONSTANT_HEADER: [&str; 4] = [
@ -61,8 +61,8 @@ const CONSTANT_HEADER: [&str; 4] = [
const LOCAL_HEADER: [&str; 4] = [
"Locals",
"------",
" i SCOPE MUTABLE TYPE IDENTIFIER ",
"--- ------- ------- -------------------------------- ----------------",
" i SCOPE MUTABLE TYPE IDENTIFIER ",
"--- ------- ------- ---------------- ----------------",
];
/// Builder that constructs a human-readable representation of a chunk.
@ -89,11 +89,11 @@ impl<'a> Disassembler<'a> {
}
}
/// The default width of the disassembly output, including borders.
/// The default width of the disassembly output, including borders and padding.
pub fn default_width() -> usize {
let longest_line = INSTRUCTION_HEADER[3];
(longest_line.chars().count() + 2).max(80)
longest_line.chars().count() + 4 // Allow for one border and one padding space on each side.
}
pub fn source(mut self, source: &'a str) -> Self {
@ -209,22 +209,12 @@ impl<'a> Disassembler<'a> {
self.push_header(line);
}
for (index, (instruction, r#type, position)) in self.chunk.instructions().iter().enumerate()
{
for (index, (instruction, position)) in self.chunk.instructions().iter().enumerate() {
let position = position.to_string();
let operation = instruction.operation().to_string();
let type_display = {
let mut type_string = r#type.to_string();
if type_string.len() > 14 {
type_string = format!("{type_string:.11}...");
}
type_string
};
let info = instruction.disassembly_info();
let instruction_display =
format!("{index:^3} {position:^10} {operation:13} {type_display:^14} {info:^32}");
format!("{index:^3} {position:^10} {operation:13} {info:^32}");
self.push_details(&instruction_display);
}
@ -254,7 +244,7 @@ impl<'a> Disassembler<'a> {
let type_display = r#type.to_string();
let scope = scope.to_string();
let local_display = format!(
"{index:^3} {scope:^7} {is_mutable:^7} {type_display:^32} {identifier_display:^16}"
"{index:^3} {scope:^7} {is_mutable:^7} {type_display:^16} {identifier_display:^16}"
);
self.push_details(&local_display);

View File

@ -715,13 +715,12 @@ impl<'a> Vm<'a> {
}
fn read(&mut self) -> Result<Instruction, VmError> {
let (instruction, _type, position) =
self.chunk.instructions().get(self.ip).ok_or_else(|| {
VmError::InstructionIndexOutOfBounds {
index: self.ip,
position: self.current_position,
}
})?;
let (instruction, position) = self.chunk.instructions().get(self.ip).ok_or_else(|| {
VmError::InstructionIndexOutOfBounds {
index: self.ip,
position: self.current_position,
}
})?;
self.ip += 1;
self.current_position = *position;

View File

@ -16,10 +16,9 @@ fn constant() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(0, 2)
),
(Instruction::r#return(true), Type::None, Span(2, 2))
(Instruction::r#return(true), Span(2, 2))
],
vec![ConcreteValue::Integer(42)],
vec![]
@ -42,7 +41,7 @@ fn empty() {
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![(Instruction::r#return(false), Type::None, Span(0, 0))],
vec![(Instruction::r#return(false), Span(0, 0))],
vec![],
vec![]
))
@ -70,7 +69,6 @@ fn parentheses_precedence() {
Argument::Constant(0),
Argument::Constant(1)
),
Type::Integer,
Span(3, 4)
),
(
@ -79,10 +77,9 @@ fn parentheses_precedence() {
Argument::Register(0),
Argument::Constant(2)
),
Type::Integer,
Span(8, 9)
),
(Instruction::r#return(true), Type::None, Span(11, 11)),
(Instruction::r#return(true), Span(11, 11)),
],
vec![
ConcreteValue::Integer(1),

View File

@ -16,21 +16,18 @@ fn equal() {
vec![
(
Instruction::equal(true, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 4)
),
(Instruction::jump(1, true), Type::None, Span(2, 4)),
(Instruction::jump(1, true), Span(2, 4)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 4)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 4)
),
(Instruction::r#return(true), Type::None, Span(6, 6)),
(Instruction::r#return(true), Span(6, 6)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -56,21 +53,18 @@ fn greater() {
vec![
(
Instruction::less_equal(false, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 3)
),
(Instruction::jump(1, true), Type::None, Span(2, 3)),
(Instruction::jump(1, true), Span(2, 3)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 3)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -96,21 +90,18 @@ fn greater_than_or_equal() {
vec![
(
Instruction::less(false, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 4)
),
(Instruction::jump(1, true), Type::None, Span(2, 4)),
(Instruction::jump(1, true), Span(2, 4)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 4)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 4)
),
(Instruction::r#return(true), Type::None, Span(6, 6)),
(Instruction::r#return(true), Span(6, 6)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -136,21 +127,18 @@ fn less_than() {
vec![
(
Instruction::less(true, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 3)
),
(Instruction::jump(1, true), Type::None, Span(2, 3)),
(Instruction::jump(1, true), Span(2, 3)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 3)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -176,21 +164,18 @@ fn less_than_or_equal() {
vec![
(
Instruction::less_equal(true, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 4)
),
(Instruction::jump(1, true), Type::None, Span(2, 4)),
(Instruction::jump(1, true), Span(2, 4)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 4)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 4)
),
(Instruction::r#return(true), Type::None, Span(6, 6)),
(Instruction::r#return(true), Span(6, 6)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -216,21 +201,18 @@ fn not_equal() {
vec![
(
Instruction::equal(false, Argument::Constant(0), Argument::Constant(1)),
Type::None,
Span(2, 4)
),
(Instruction::jump(1, true), Type::None, Span(2, 4)),
(Instruction::jump(1, true), Span(2, 4)),
(
Instruction::load_boolean(Destination::Register(0), true, true),
Type::Boolean,
Span(2, 4)
),
(
Instruction::load_boolean(Destination::Register(0), false, false),
Type::Boolean,
Span(2, 4)
),
(Instruction::r#return(true), Type::None, Span(6, 6)),
(Instruction::r#return(true), Span(6, 6)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]

View File

@ -24,10 +24,9 @@ fn function() {
Argument::Local(0),
Argument::Local(1)
),
Type::Integer,
Span(30, 31)
),
(Instruction::r#return(true), Type::None, Span(35, 35)),
(Instruction::r#return(true), Span(35, 35)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b"),],
vec![
@ -54,29 +53,21 @@ fn function_call() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Function(FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),
return_type: Box::new(Type::Integer),
}),
Span(0, 36)
),
(
Instruction::load_constant(Destination::Register(1), 1, false),
Type::Integer,
Span(36, 37)
),
(
Instruction::load_constant(Destination::Register(2), 2, false),
Type::Integer,
Span(39, 40)
),
(
Instruction::call(Destination::Register(3), Argument::Constant(0), 2),
Type::Integer,
Span(35, 41)
),
(Instruction::r#return(true), Type::None, Span(41, 41)),
(Instruction::r#return(true), Span(41, 41)),
],
vec![
ConcreteValue::Function(Chunk::with_data(
@ -93,10 +84,9 @@ fn function_call() {
Argument::Local(0),
Argument::Local(1)
),
Type::Integer,
Span(30, 31)
),
(Instruction::r#return(true), Type::None, Span(35, 36)),
(Instruction::r#return(true), Span(35, 36)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b"),],
vec![
@ -130,19 +120,10 @@ fn function_declaration() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Function(FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),
return_type: Box::new(Type::Integer),
}),
Span(0, 40)
),
(
Instruction::define_local(0, 0, false),
Type::None,
Span(3, 6)
),
(Instruction::r#return(false), Type::None, Span(40, 40))
(Instruction::define_local(0, 0, false), Span(3, 6)),
(Instruction::r#return(false), Span(40, 40))
],
vec![
ConcreteValue::Function(Chunk::with_data(
@ -159,10 +140,9 @@ fn function_declaration() {
Argument::Local(0),
Argument::Local(1)
),
Type::Integer,
Span(35, 36)
),
(Instruction::r#return(true), Type::None, Span(40, 40)),
(Instruction::r#return(true), Span(40, 40)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b")],
vec![

View File

@ -16,10 +16,9 @@ fn empty_list() {
vec![
(
Instruction::load_list(Destination::Register(0), 0),
Type::List(Box::new(Type::Any)),
Span(0, 2)
),
(Instruction::r#return(true), Type::None, Span(2, 2)),
(Instruction::r#return(true), Span(2, 2)),
],
vec![],
vec![]
@ -45,25 +44,21 @@ fn list() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(1, 2)
),
(
Instruction::load_constant(Destination::Register(1), 1, false),
Type::Integer,
Span(4, 5)
),
(
Instruction::load_constant(Destination::Register(2), 2, false),
Type::Integer,
Span(7, 8)
),
(
Instruction::load_list(Destination::Register(3), 0),
Type::List(Box::new(Type::Integer)),
Span(0, 9)
),
(Instruction::r#return(true), Type::None, Span(9, 9)),
(Instruction::r#return(true), Span(9, 9)),
],
vec![
ConcreteValue::Integer(1),
@ -100,7 +95,6 @@ fn list_with_complex_expression() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(1, 2)
),
(
@ -109,7 +103,6 @@ fn list_with_complex_expression() {
Argument::Constant(1),
Argument::Constant(2)
),
Type::Integer,
Span(6, 7)
),
(
@ -118,7 +111,6 @@ fn list_with_complex_expression() {
Argument::Constant(3),
Argument::Constant(4)
),
Type::Integer,
Span(14, 15)
),
(
@ -127,16 +119,14 @@ fn list_with_complex_expression() {
Argument::Register(1),
Argument::Register(2)
),
Type::Integer,
Span(10, 11)
),
(Instruction::close(1, 3), Type::None, Span(17, 18)),
(Instruction::close(1, 3), Span(17, 18)),
(
Instruction::load_list(Destination::Register(4), 0),
Type::List(Box::new(Type::Integer)),
Span(0, 18)
),
(Instruction::r#return(true), Type::None, Span(18, 18)),
(Instruction::r#return(true), Span(18, 18)),
],
vec![
ConcreteValue::Integer(1),
@ -174,7 +164,6 @@ fn list_with_simple_expression() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(1, 2)
),
(
@ -183,20 +172,17 @@ fn list_with_simple_expression() {
Argument::Constant(1),
Argument::Constant(2)
),
Type::Integer,
Span(6, 7)
),
(
Instruction::load_constant(Destination::Register(2), 3, false),
Type::Integer,
Span(11, 12)
),
(
Instruction::load_list(Destination::Register(3), 0),
Type::List(Box::new(Type::Integer)),
Span(0, 13)
),
(Instruction::r#return(true), Type::None, Span(13, 13)),
(Instruction::r#return(true), Span(13, 13)),
],
vec![
ConcreteValue::Integer(1),

View File

@ -1,160 +0,0 @@
use dust_lang::*;
#[test]
fn and() {
let source = "true && false";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Type::Boolean,
Span(0, 4)
),
(
Instruction::test(Argument::Register(0), true),
Type::None,
Span(5, 7)
),
(Instruction::jump(1, true), Type::None, Span(5, 7)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Type::Boolean,
Span(8, 13)
),
(Instruction::r#return(true), Type::None, Span(13, 13)),
],
vec![],
vec![]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn or() {
let source = "true || false";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Type::Boolean,
Span(0, 4)
),
(
Instruction::test(Argument::Register(0), false),
Type::None,
Span(5, 7)
),
(Instruction::jump(1, true), Type::None, Span(5, 7)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Type::Boolean,
Span(8, 13)
),
(Instruction::r#return(true), Type::None, Span(13, 13)),
],
vec![],
vec![]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}
#[test]
fn and_and_or() {
let source = "let a = true; let b = true; let c = false; a && b || c";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Type::Boolean,
Span(8, 12)
),
(
Instruction::define_local(0, 0, false),
Type::None,
Span(4, 5)
),
(
Instruction::load_boolean(Destination::Register(1), true, false),
Type::Boolean,
Span(22, 26)
),
(
Instruction::define_local(1, 1, false),
Type::None,
Span(18, 19)
),
(
Instruction::load_boolean(Destination::Register(2), false, false),
Type::Boolean,
Span(36, 41)
),
(
Instruction::define_local(2, 2, false),
Type::None,
Span(32, 33)
),
(
Instruction::test(Argument::Local(0), true),
Type::None,
Span(45, 47)
),
(Instruction::jump(1, true), Type::None, Span(45, 47)),
(
Instruction::test(Argument::Local(1), false),
Type::None,
Span(50, 52)
),
(Instruction::jump(1, true), Type::None, Span(50, 52)),
(
Instruction::get_local(Destination::Register(3), 2),
Type::Boolean,
Span(53, 54)
),
(Instruction::r#return(true), Type::None, Span(54, 54)),
],
vec![
ConcreteValue::string("a"),
ConcreteValue::string("b"),
ConcreteValue::string("c")
],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default()),
Local::new(2, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}

View File

@ -0,0 +1,69 @@
use dust_lang::*;
#[test]
fn and() {
let source = "true && false";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(0, 4)
),
(Instruction::test(Argument::Register(0), true), Span(5, 7)),
(Instruction::jump(1, true), Span(5, 7)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Span(8, 13)
),
(Instruction::r#return(true), Span(13, 13)),
],
vec![],
vec![]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn or() {
let source = "true || false";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(0, 4)
),
(Instruction::test(Argument::Register(0), false), Span(5, 7)),
(Instruction::jump(1, true), Span(5, 7)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Span(8, 13)
),
(Instruction::r#return(true), Span(13, 13)),
],
vec![],
vec![]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}

View File

@ -0,0 +1,378 @@
use dust_lang::*;
#[test]
fn true_and_true() {
let source = "let a = true; let b = true; a && b";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(8, 12)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), true, false),
Span(22, 26)
),
(Instruction::define_local(1, 1, false), Span(18, 19)),
(
Instruction::get_local(Destination::Register(2), 0),
Span(28, 29)
),
(Instruction::test(Argument::Local(0), true), Span(30, 32)),
(Instruction::jump(1, true), Span(30, 32)),
(
Instruction::get_local(Destination::Register(3), 1),
Span(33, 34)
),
(Instruction::r#return(true), Span(34, 34)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b")],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}
#[test]
fn false_and_false() {
let source = "let a = false; let b = false; a && b";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), false, false),
Span(8, 13)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Span(23, 28)
),
(Instruction::define_local(1, 1, false), Span(19, 20)),
(
Instruction::get_local(Destination::Register(2), 0),
Span(30, 31)
),
(Instruction::test(Argument::Local(0), true), Span(32, 34)),
(Instruction::jump(1, true), Span(32, 34)),
(
Instruction::get_local(Destination::Register(3), 1),
Span(35, 36)
),
(Instruction::r#return(true), Span(36, 36)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b")],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn true_and_false() {
let source = "let a = true; let b = false; a && b";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(8, 12)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Span(22, 27)
),
(Instruction::define_local(1, 1, false), Span(18, 19)),
(
Instruction::get_local(Destination::Register(2), 0),
Span(29, 30)
),
(Instruction::test(Argument::Local(0), true), Span(31, 33)),
(Instruction::jump(1, true), Span(31, 33)),
(
Instruction::get_local(Destination::Register(3), 1),
Span(34, 35)
),
(Instruction::r#return(true), Span(35, 35)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b")],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn false_and_true() {
let source = "let a = false; let b = true; a && b";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), false, false),
Span(8, 13)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), true, false),
Span(23, 27)
),
(Instruction::define_local(1, 1, false), Span(19, 20)),
(
Instruction::get_local(Destination::Register(2), 0),
Span(29, 30)
),
(Instruction::test(Argument::Local(0), true), Span(31, 33)),
(Instruction::jump(1, true), Span(31, 33)),
(
Instruction::get_local(Destination::Register(3), 1),
Span(34, 35)
),
(Instruction::r#return(true), Span(35, 35)),
],
vec![ConcreteValue::string("a"), ConcreteValue::string("b")],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn true_and_true_and_true() {
let source = "let a = true; let b = true; let c = true; a && b && c";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(8, 12)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), true, false),
Span(22, 26)
),
(Instruction::define_local(1, 1, false), Span(18, 19)),
(
Instruction::load_boolean(Destination::Register(2), true, false),
Span(36, 40)
),
(Instruction::define_local(2, 2, false), Span(32, 33)),
(
Instruction::get_local(Destination::Register(3), 0),
Span(42, 43)
),
(Instruction::test(Argument::Local(0), true), Span(44, 46)),
(Instruction::jump(1, true), Span(44, 46)),
(
Instruction::get_local(Destination::Register(4), 1),
Span(47, 48)
),
(Instruction::test(Argument::Local(1), true), Span(49, 51)),
(Instruction::jump(1, true), Span(49, 51)),
(
Instruction::get_local(Destination::Register(5), 2),
Span(52, 53)
),
(Instruction::r#return(true), Span(53, 53)),
],
vec![
ConcreteValue::string("a"),
ConcreteValue::string("b"),
ConcreteValue::string("c")
],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default()),
Local::new(2, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}
#[test]
fn false_and_false_and_false() {
let source = "let a = false; let b = false; let c = false; a && b && c";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), false, false),
Span(8, 13)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), false, false),
Span(23, 28)
),
(Instruction::define_local(1, 1, false), Span(19, 20)),
(
Instruction::load_boolean(Destination::Register(2), false, false),
Span(38, 43)
),
(Instruction::define_local(2, 2, false), Span(34, 35)),
(
Instruction::get_local(Destination::Register(3), 0),
Span(45, 46)
),
(Instruction::test(Argument::Local(0), true), Span(47, 49)),
(Instruction::jump(1, true), Span(47, 49)),
(
Instruction::get_local(Destination::Register(4), 1),
Span(50, 51)
),
(Instruction::test(Argument::Local(1), true), Span(52, 54)),
(Instruction::jump(1, true), Span(52, 54)),
(
Instruction::get_local(Destination::Register(5), 2),
Span(55, 56)
),
(Instruction::r#return(true), Span(56, 56)),
],
vec![
ConcreteValue::string("a"),
ConcreteValue::string("b"),
ConcreteValue::string("c")
],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default()),
Local::new(2, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(false))));
}
#[test]
fn true_and_true_or_false() {
let source = "let a = true; let b = true; let c = false; a && b || c";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Span(8, 12)
),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(
Instruction::load_boolean(Destination::Register(1), true, false),
Span(22, 26)
),
(Instruction::define_local(1, 1, false), Span(18, 19)),
(
Instruction::load_boolean(Destination::Register(2), false, false),
Span(36, 41)
),
(Instruction::define_local(2, 2, false), Span(32, 33)),
(
Instruction::get_local(Destination::Register(3), 0),
Span(43, 44)
),
(Instruction::test(Argument::Local(0), true), Span(45, 47)),
(Instruction::jump(1, true), Span(45, 47)),
(
Instruction::get_local(Destination::Register(4), 1),
Span(48, 49)
),
(Instruction::test(Argument::Local(1), false), Span(50, 52)),
(Instruction::jump(1, true), Span(50, 52)),
(
Instruction::get_local(Destination::Register(5), 2),
Span(53, 54)
),
(Instruction::r#return(true), Span(54, 54)),
],
vec![
ConcreteValue::string("a"),
ConcreteValue::string("b"),
ConcreteValue::string("c")
],
vec![
Local::new(0, Type::Boolean, false, Scope::default()),
Local::new(1, Type::Boolean, false, Scope::default()),
Local::new(2, Type::Boolean, false, Scope::default())
]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::Boolean(true))));
}

View File

@ -16,36 +16,28 @@ fn r#while() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 13)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::less(true, Argument::Local(0), Argument::Constant(2)),
Type::None,
Span(23, 24)
),
(Instruction::jump(2, true), Type::None, Span(41, 42)),
(Instruction::jump(2, true), Span(41, 42)),
(
Instruction::add(
Destination::Local(0),
Argument::Local(0),
Argument::Constant(3)
),
Type::Integer,
Span(35, 36)
),
(Instruction::jump(3, false), Type::None, Span(41, 42)),
(Instruction::jump(3, false), Span(41, 42)),
(
Instruction::get_local(Destination::Register(1), 0),
Type::Integer,
Span(41, 42)
),
(Instruction::r#return(true), Type::None, Span(42, 42)),
(Instruction::r#return(true), Span(42, 42)),
],
vec![
ConcreteValue::Integer(0),

View File

@ -20,10 +20,9 @@ fn add() {
Argument::Constant(0),
Argument::Constant(1)
),
Type::Integer,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5))
(Instruction::r#return(true), Span(5, 5))
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -49,29 +48,22 @@ fn add_assign() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 13)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::add(
Destination::Local(0),
Argument::Local(0),
Argument::Constant(2)
),
Type::None,
Span(17, 19)
),
(
Instruction::get_local(Destination::Register(1), 0),
Type::Integer,
Span(23, 24)
),
(Instruction::r#return(true), Type::None, Span(24, 24))
(Instruction::r#return(true), Span(24, 24))
],
vec![
ConcreteValue::Integer(1),
@ -137,10 +129,9 @@ fn divide() {
Argument::Constant(0),
Argument::Constant(0)
),
Type::Integer,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5))
(Instruction::r#return(true), Span(5, 5))
],
vec![ConcreteValue::Integer(2)],
vec![]
@ -166,29 +157,22 @@ fn divide_assign() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 13)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::divide(
Destination::Local(0),
Argument::Local(0),
Argument::Constant(0)
),
Type::None,
Span(17, 19)
),
(
Instruction::get_local(Destination::Register(1), 0),
Type::Integer,
Span(23, 24)
),
(Instruction::r#return(true), Type::None, Span(24, 24))
(Instruction::r#return(true), Span(24, 24))
],
vec![ConcreteValue::Integer(2), ConcreteValue::string("a")],
vec![Local::new(1, Type::Integer, true, Scope::default())]
@ -234,7 +218,6 @@ fn math_operator_precedence() {
Argument::Constant(0),
Argument::Constant(1)
),
Type::Integer,
Span(2, 3)
),
(
@ -243,7 +226,6 @@ fn math_operator_precedence() {
Argument::Constant(2),
Argument::Constant(3)
),
Type::Integer,
Span(10, 11)
),
(
@ -252,7 +234,6 @@ fn math_operator_precedence() {
Argument::Register(1),
Argument::Constant(4)
),
Type::Integer,
Span(14, 15)
),
(
@ -261,10 +242,9 @@ fn math_operator_precedence() {
Argument::Register(0),
Argument::Register(2)
),
Type::Integer,
Span(6, 7)
),
(Instruction::r#return(true), Type::None, Span(17, 17)),
(Instruction::r#return(true), Span(17, 17)),
],
vec![
ConcreteValue::Integer(1),
@ -300,10 +280,9 @@ fn multiply() {
Argument::Constant(0),
Argument::Constant(1)
),
Type::Integer,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -329,29 +308,22 @@ fn multiply_assign() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 13)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::multiply(
Destination::Local(0),
Argument::Local(0),
Argument::Constant(2)
),
Type::None,
Span(17, 19)
),
(
Instruction::get_local(Destination::Register(1), 0),
Type::Integer,
Span(22, 23)
),
(Instruction::r#return(true), Type::None, Span(23, 23))
(Instruction::r#return(true), Span(23, 23))
],
vec![
ConcreteValue::Integer(2),
@ -401,10 +373,9 @@ fn subtract() {
Argument::Constant(0),
Argument::Constant(1)
),
Type::Integer,
Span(2, 3)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![ConcreteValue::Integer(1), ConcreteValue::Integer(2)],
vec![]
@ -430,29 +401,22 @@ fn subtract_assign() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 14)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::subtract(
Destination::Local(0),
Argument::Local(0),
Argument::Constant(2)
),
Type::None,
Span(18, 20)
),
(
Instruction::get_local(Destination::Register(1), 0),
Type::Integer,
Span(24, 25)
),
(Instruction::r#return(true), Type::None, Span(25, 25)),
(Instruction::r#return(true), Span(25, 25)),
],
vec![
ConcreteValue::Integer(42),

View File

@ -16,20 +16,17 @@ fn panic() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::String,
Span(6, 22)
),
(
Instruction::load_constant(Destination::Register(1), 1, false),
Type::Integer,
Span(24, 26)
),
(
Instruction::call_native(Destination::Register(2), NativeFunction::Panic, 2),
Type::None,
Span(0, 27)
),
(Instruction::r#return(false), Type::None, Span(27, 27))
(Instruction::r#return(false), Span(27, 27))
],
vec![
ConcreteValue::string("Goodbye world!"),
@ -67,15 +64,13 @@ fn to_string() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(10, 12)
),
(
Instruction::call_native(Destination::Register(1), NativeFunction::ToString, 1),
Type::String,
Span(0, 13)
),
(Instruction::r#return(true), Type::None, Span(13, 13))
(Instruction::r#return(true), Span(13, 13))
],
vec![ConcreteValue::Integer(42)],
vec![]

View File

@ -38,55 +38,30 @@ fn block_scope() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(17, 18)
),
(
Instruction::define_local(0, 0, false),
Type::None,
Span(13, 14)
),
(Instruction::define_local(0, 0, false), Span(13, 14)),
(
Instruction::load_constant(Destination::Register(1), 2, false),
Type::Integer,
Span(50, 52)
),
(
Instruction::define_local(1, 1, false),
Type::None,
Span(46, 47)
),
(Instruction::define_local(1, 1, false), Span(46, 47)),
(
Instruction::load_constant(Destination::Register(2), 4, false),
Type::Integer,
Span(92, 93)
),
(
Instruction::define_local(2, 2, false),
Type::None,
Span(88, 89)
),
(Instruction::define_local(2, 2, false), Span(88, 89)),
(
Instruction::load_constant(Destination::Register(3), 6, false),
Type::Integer,
Span(129, 130)
),
(
Instruction::define_local(3, 3, false),
Type::None,
Span(125, 126)
),
(Instruction::define_local(3, 3, false), Span(125, 126)),
(
Instruction::load_constant(Destination::Register(4), 4, false),
Type::Integer,
Span(158, 159)
),
(
Instruction::define_local(4, 4, false),
Type::None,
Span(154, 155)
),
(Instruction::r#return(false), Type::None, Span(165, 165))
(Instruction::define_local(4, 4, false), Span(154, 155)),
(Instruction::r#return(false), Span(165, 165))
],
vec![
ConcreteValue::Integer(0),
@ -146,95 +121,50 @@ fn multiple_block_scopes() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(17, 18)
),
(
Instruction::define_local(0, 0, false),
Type::None,
Span(13, 14)
),
(Instruction::define_local(0, 0, false), Span(13, 14)),
(
Instruction::load_constant(Destination::Register(1), 2, false),
Type::Integer,
Span(50, 52)
),
(
Instruction::define_local(1, 1, false),
Type::None,
Span(46, 47)
),
(Instruction::define_local(1, 1, false), Span(46, 47)),
(
Instruction::load_constant(Destination::Register(2), 4, false),
Type::Integer,
Span(92, 93)
),
(
Instruction::define_local(2, 2, false),
Type::None,
Span(88, 89)
),
(Instruction::define_local(2, 2, false), Span(88, 89)),
(
Instruction::get_local(Destination::Register(3), 1),
Type::Integer,
Span(129, 130)
),
(
Instruction::define_local(3, 3, false),
Type::None,
Span(125, 126)
),
(Instruction::define_local(3, 3, false), Span(125, 126)),
(
Instruction::get_local(Destination::Register(4), 0),
Type::Integer,
Span(158, 159)
),
(
Instruction::define_local(4, 4, false),
Type::None,
Span(154, 155)
),
(Instruction::define_local(4, 4, false), Span(154, 155)),
(
Instruction::load_constant(Destination::Register(5), 2, false),
Type::Integer,
Span(191, 193)
),
(
Instruction::define_local(5, 5, false),
Type::None,
Span(187, 188)
),
(Instruction::define_local(5, 5, false), Span(187, 188)),
(
Instruction::load_constant(Destination::Register(6), 4, false),
Type::Integer,
Span(233, 234)
),
(
Instruction::define_local(6, 6, false),
Type::None,
Span(229, 230)
),
(Instruction::define_local(6, 6, false), Span(229, 230)),
(
Instruction::get_local(Destination::Register(7), 5),
Type::Integer,
Span(270, 271)
),
(
Instruction::define_local(7, 7, false),
Type::None,
Span(266, 267)
),
(Instruction::define_local(7, 7, false), Span(266, 267)),
(
Instruction::get_local(Destination::Register(8), 0),
Type::Integer,
Span(299, 300)
),
(
Instruction::define_local(8, 8, false),
Type::None,
Span(295, 296)
),
(Instruction::r#return(false), Type::None, Span(306, 306))
(Instruction::define_local(8, 8, false), Span(295, 296)),
(Instruction::r#return(false), Span(306, 306))
],
vec![
ConcreteValue::Integer(0),

View File

@ -16,10 +16,9 @@ fn negate() {
vec![
(
Instruction::negate(Destination::Register(0), Argument::Constant(0)),
Type::Integer,
Span(0, 1)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![ConcreteValue::Integer(42)],
vec![]
@ -45,15 +44,13 @@ fn not() {
vec![
(
Instruction::load_boolean(Destination::Register(0), true, false),
Type::Boolean,
Span(1, 5)
),
(
Instruction::not(Destination::Register(1), Argument::Register(0)),
Type::Boolean,
Span(0, 1)
),
(Instruction::r#return(true), Type::None, Span(5, 5)),
(Instruction::r#return(true), Span(5, 5)),
],
vec![],
vec![]

View File

@ -16,15 +16,10 @@ fn define_local() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(8, 10)
),
(
Instruction::define_local(0, 0, false),
Type::None,
Span(4, 5)
),
(Instruction::r#return(false), Type::None, Span(11, 11))
(Instruction::define_local(0, 0, false), Span(4, 5)),
(Instruction::r#return(false), Span(11, 11))
],
vec![ConcreteValue::Integer(42), ConcreteValue::string("x")],
vec![Local::new(1, Type::Integer, false, Scope::default())]
@ -67,26 +62,19 @@ fn set_local() {
vec![
(
Instruction::load_constant(Destination::Register(0), 0, false),
Type::Integer,
Span(12, 14)
),
(
Instruction::define_local(0, 0, true),
Type::None,
Span(8, 9)
),
(Instruction::define_local(0, 0, true), Span(8, 9)),
(
Instruction::load_constant(Destination::Register(1), 2, false),
Type::Integer,
Span(20, 22)
),
(Instruction::set_local(1, 0), Type::None, Span(16, 17)),
(Instruction::set_local(1, 0), Span(16, 17)),
(
Instruction::get_local(Destination::Register(2), 0),
Type::Integer,
Span(24, 25)
),
(Instruction::r#return(true), Type::None, Span(25, 25)),
(Instruction::r#return(true), Span(25, 25)),
],
vec![
ConcreteValue::Integer(41),