1
0

Continue adding type evaluations

This commit is contained in:
Jeff 2024-11-16 05:16:51 -05:00
parent 960931ce6e
commit 0f3924341f
17 changed files with 369 additions and 85 deletions

View File

@ -40,20 +40,17 @@ impl Chunk {
pub fn with_data(
name: Option<String>,
r#type: FunctionType,
instructions: Vec<(Instruction, Span)>,
constants: Vec<ConcreteValue>,
locals: Vec<Local>,
) -> Self {
Self {
name,
r#type,
instructions,
constants,
locals,
r#type: FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
},
}
}
@ -61,12 +58,16 @@ impl Chunk {
self.name.as_ref()
}
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub fn r#type(&self) -> &FunctionType {
&self.r#type
}
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
pub fn set_type(&mut self, r#type: FunctionType) {
self.r#type = r#type;
}
pub fn len(&self) -> usize {

View File

@ -38,7 +38,29 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
.parse_top_level()
.map_err(|error| DustError::Compile { error, source })?;
Ok(compiler.finish())
let return_type = if compiler
.chunk
.instructions()
.iter()
.last()
.map(|(instruction, _)| {
let should_return = instruction.b_as_boolean();
(instruction.operation(), should_return)
})
== Some((Operation::Return, true))
{
Box::new(compiler.previous_expression_type.clone())
} else {
Box::new(Type::None)
};
let chunk_type = FunctionType {
type_parameters: None,
value_parameters: None,
return_type,
};
Ok(compiler.finish(chunk_type))
}
/// Low-level tool for compiling the input a token at a time while assembling a chunk.
@ -91,9 +113,11 @@ impl<'src> Compiler<'src> {
})
}
pub fn finish(self) -> Chunk {
pub fn finish(mut self, r#type: FunctionType) -> Chunk {
log::info!("End chunk with {} optimizations", self.optimization_count);
self.chunk.set_type(r#type);
self.chunk
}
@ -188,13 +212,14 @@ impl<'src> Compiler<'src> {
let identifier = ConcreteValue::string(identifier);
let identifier_index = self.chunk.push_or_get_constant(identifier);
let local_index = self.chunk.locals().len() as u8;
self.chunk
.locals_mut()
.push(Local::new(identifier_index, r#type, is_mutable, scope));
self.local_definitions.push(register_index);
(self.chunk.locals().len() as u8 - 1, identifier_index)
(local_index, identifier_index)
}
fn allow(&mut self, allowed: Token) -> Result<bool, CompileError> {
@ -953,8 +978,8 @@ impl<'src> Compiler<'src> {
self.previous_expression_type = Type::None;
let mut optimizer = Optimizer::new(self.chunk.instructions_mut());
let optimized = Optimizer::optimize_set_local(&mut optimizer);
let mut optimizer = Optimizer::new(&mut self.chunk);
let optimized = optimizer.optimize_set_local();
if optimized {
self.optimization_count += 1;
@ -1171,7 +1196,7 @@ impl<'src> Compiler<'src> {
);
if self.chunk.len() >= 4 {
let mut optimizer = Optimizer::new(self.chunk.instructions_mut());
let mut optimizer = Optimizer::new(&mut self.chunk);
let optimized = optimizer.optimize_comparison();
if optimized {
@ -1260,10 +1285,14 @@ impl<'src> Compiler<'src> {
}
let end = self.previous_position.1;
let to_register = self.next_register();
let mut to_register = self.next_register();
let argument_count = to_register - start_register;
self.previous_expression_type = Type::Function(function.r#type());
self.previous_expression_type = *function.r#type().return_type;
if let Type::None = self.previous_expression_type {
to_register = 0;
}
self.emit_instruction(
Instruction::call_native(to_register, function, argument_count),
@ -1428,7 +1457,6 @@ impl<'src> Compiler<'src> {
function_compiler.advance()?;
let register = function_compiler.next_register();
let (_, identifier_index) = function_compiler.declare_local(
parameter,
r#type.clone(),
@ -1476,7 +1504,8 @@ impl<'src> Compiler<'src> {
value_parameters,
return_type,
};
let function = ConcreteValue::Function(function_compiler.finish());
let function = ConcreteValue::Function(function_compiler.finish(function_type.clone()));
let constant_index = self.chunk.push_or_get_constant(function);
let function_end = self.current_position.1;
let register = self.next_register();

View File

@ -463,11 +463,11 @@ impl Instruction {
Operation::DefineLocal => {
let to_register = self.a();
let local_index = self.b();
let mutable_display = if self.c_as_boolean() { "mut" } else { "" };
let identifier_display = match chunk.get_identifier(local_index) {
Some(identifier) => identifier.to_string(),
None => "???".to_string(),
};
let mutable_display = if self.c_as_boolean() { "mut" } else { "" };
format!("R{to_register} = L{local_index} {mutable_display} {identifier_display}")
}

View File

@ -1,17 +1,19 @@
//! Tool used by the compiler to optimize a chunk's bytecode.
use crate::{Instruction, Operation, Span};
use crate::{Chunk, Instruction, Operation, Span};
/// An instruction optimizer that mutably borrows instructions from a chunk.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
#[derive(Debug)]
pub struct Optimizer<'a> {
instructions: &'a mut Vec<(Instruction, Span)>,
chunk: &'a mut Chunk,
}
impl<'a> Optimizer<'a> {
/// Creates a new optimizer with a mutable reference to some of a chunk's instructions.
pub fn new(instructions: &'a mut Vec<(Instruction, Span)>) -> Self {
Self { instructions }
pub fn new(instructions: &'a mut Chunk) -> Self {
Self {
chunk: instructions,
}
}
/// Optimizes a comparison operation.
@ -49,14 +51,15 @@ impl<'a> Optimizer<'a> {
log::debug!("Optimizing comparison");
let instructions = self.instructions_mut();
let first_loader_register = {
let first_loader = &mut self.instructions[2].0;
let first_loader = &mut instructions[2].0;
first_loader.set_c_to_boolean(true);
first_loader.a()
};
let second_loader = &mut self.instructions[3].0;
let second_loader = &mut instructions[3].0;
let mut second_loader_new = Instruction::with_operation(second_loader.operation());
second_loader_new.set_a(first_loader_register);
@ -85,22 +88,27 @@ impl<'a> Optimizer<'a> {
return false;
}
log::debug!("Optimizing set local");
self.instructions_mut().pop();
self.instructions.pop();
log::debug!("Optimizing by removing redundant SetLocal");
true
}
fn instructions_mut(&mut self) -> &mut Vec<(Instruction, Span)> {
self.chunk.instructions_mut()
}
fn get_operations<const COUNT: usize>(&self) -> Option<[Operation; COUNT]> {
if self.instructions.len() < COUNT {
if self.chunk.len() < COUNT {
return None;
}
let mut n_operations = [Operation::Return; COUNT];
for (nth, operation) in n_operations.iter_mut().rev().zip(
self.instructions
self.chunk
.instructions()
.iter()
.rev()
.map(|(instruction, _)| instruction.operation()),

View File

@ -8,8 +8,8 @@ use std::{
use crate::{
compile, AbstractValue, AnnotatedError, Chunk, ChunkError, ConcreteValue, DustError,
Instruction, NativeFunction, NativeFunctionError, Operation, Span, Type, ValueError,
ValueOwned, ValueRef,
Instruction, NativeFunction, NativeFunctionError, Operation, Span, ValueError, ValueOwned,
ValueRef,
};
pub fn run(source: &str) -> Result<Option<ConcreteValue>, DustError> {
@ -367,29 +367,23 @@ impl<'a> Vm<'a> {
position: self.current_position,
});
};
let has_return_value = *chunk.r#type().return_type != Type::None;
let mut function_vm = Vm::new(chunk, Some(self));
let first_argument_index = function_register + 1;
let last_argument_index = first_argument_index + argument_count;
for argument_index in first_argument_index..last_argument_index {
let top_of_stack = function_vm.stack.len() as u8;
for (argument_index, argument_register_index) in
(first_argument_index..last_argument_index).enumerate()
{
function_vm.set_register(
top_of_stack,
Register::Pointer(Pointer::ParentStack(argument_index)),
argument_index as u8,
Register::Pointer(Pointer::ParentStack(argument_register_index)),
)?
}
function_vm.run()?;
let return_value = function_vm.run()?;
if has_return_value {
let top_of_stack = function_vm.stack.len() as u8 - 1;
self.set_register(
to_register,
Register::Pointer(Pointer::ParentStack(top_of_stack)),
)?;
if let Some(value) = return_value {
self.set_register(to_register, Register::ConcreteValue(value))?;
}
}
Operation::CallNative => {

View File

@ -8,6 +8,11 @@ fn constant() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(Instruction::load_constant(0, 0, false), Span(0, 2)),
(Instruction::r#return(true), Span(2, 2))
@ -28,6 +33,11 @@ fn empty() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![(Instruction::r#return(false), Span(0, 0))],
vec![],
vec![]
@ -44,6 +54,11 @@ fn parentheses_precedence() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(
*Instruction::add(0, 0, 1)

View File

@ -8,6 +8,11 @@ fn equal() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::equal(true, 0, 1)
@ -36,6 +41,11 @@ fn greater() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::less_equal(false, 0, 1)
@ -64,6 +74,11 @@ fn greater_than_or_equal() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::less(false, 0, 1)
@ -92,6 +107,11 @@ fn less_than() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::less(true, 0, 1)
@ -120,6 +140,11 @@ fn less_than_or_equal() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::less_equal(true, 0, 1)
@ -148,6 +173,11 @@ fn not_equal() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::equal(false, 0, 1)

View File

@ -8,6 +8,11 @@ fn equality_assignment_long() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::equal(true, 0, 0)
@ -38,6 +43,11 @@ fn equality_assignment_short() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean)
},
vec![
(
*Instruction::equal(true, 0, 0)
@ -64,8 +74,8 @@ fn equality_assignment_short() {
fn if_else_assigment_false() {
let source = r#"
let a = if 4 == 3 {
1; 2; 3; 4;
panic()
panic();
0
} else {
1; 2; 3; 4;
42
@ -76,6 +86,11 @@ fn if_else_assigment_false() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(
*Instruction::equal(true, 0, 1)
@ -83,35 +98,33 @@ fn if_else_assigment_false() {
.set_c_is_constant(),
Span(22, 24)
),
(Instruction::jump(6, true), Span(27, 28)),
(Instruction::load_constant(0, 2, false), Span(41, 42)),
(Instruction::load_constant(1, 3, false), Span(44, 45)),
(Instruction::load_constant(2, 1, false), Span(47, 48)),
(Instruction::load_constant(3, 0, false), Span(50, 51)),
(Instruction::jump(3, true), Span(27, 28)),
(
Instruction::call_native(4, NativeFunction::Panic, 0),
Span(65, 72)
Instruction::call_native(0, NativeFunction::Panic, 0),
Span(41, 48)
),
(Instruction::jump(5, true), Span(138, 139)),
(Instruction::load_constant(5, 2, false), Span(102, 103)),
(Instruction::load_constant(6, 3, false), Span(105, 106)),
(Instruction::load_constant(7, 1, false), Span(108, 109)),
(Instruction::load_constant(8, 0, false), Span(111, 112)),
(Instruction::load_constant(9, 4, false), Span(126, 128)),
(Instruction::r#move(9, 4), Span(138, 139)),
(Instruction::define_local(9, 0, false), Span(13, 14)),
(Instruction::get_local(10, 0), Span(148, 149)),
(Instruction::r#return(true), Span(149, 149)),
(Instruction::load_constant(0, 2, false), Span(62, 63)),
(Instruction::jump(5, true), Span(129, 130)),
(Instruction::load_constant(1, 3, false), Span(93, 94)),
(Instruction::load_constant(2, 4, false), Span(96, 97)),
(Instruction::load_constant(3, 1, false), Span(99, 100)),
(Instruction::load_constant(4, 0, false), Span(102, 103)),
(Instruction::load_constant(5, 5, false), Span(117, 119)),
(Instruction::r#move(5, 0), Span(129, 130)),
(Instruction::define_local(5, 0, false), Span(13, 14)),
(Instruction::get_local(6, 0), Span(139, 140)),
(Instruction::r#return(true), Span(140, 140)),
],
vec![
ConcreteValue::Integer(4),
ConcreteValue::Integer(3),
ConcreteValue::Integer(0),
ConcreteValue::Integer(1),
ConcreteValue::Integer(2),
ConcreteValue::Integer(42),
ConcreteValue::string("a")
],
vec![Local::new(5, Type::Integer, false, Scope::default())]
vec![Local::new(6, Type::Integer, false, Scope::default())]
)),
);
@ -125,8 +138,8 @@ fn if_else_assigment_true() {
1; 2; 3; 4;
42
} else {
1; 2; 3; 4;
panic()
panic();
0
};
a"#;
@ -134,6 +147,11 @@ fn if_else_assigment_true() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(
*Instruction::equal(true, 0, 0)
@ -147,19 +165,16 @@ fn if_else_assigment_true() {
(Instruction::load_constant(2, 3, false), Span(47, 48)),
(Instruction::load_constant(3, 0, false), Span(50, 51)),
(Instruction::load_constant(4, 4, false), Span(65, 67)),
(Instruction::jump(5, true), Span(138, 139)),
(Instruction::load_constant(5, 1, false), Span(97, 98)),
(Instruction::load_constant(6, 2, false), Span(100, 101)),
(Instruction::load_constant(7, 3, false), Span(103, 104)),
(Instruction::load_constant(8, 0, false), Span(106, 107)),
(Instruction::jump(2, true), Span(129, 130)),
(
Instruction::call_native(9, NativeFunction::Panic, 0),
Span(121, 128)
Instruction::call_native(0, NativeFunction::Panic, 0),
Span(97, 104)
),
(Instruction::r#move(9, 4), Span(138, 139)),
(Instruction::define_local(9, 0, false), Span(13, 14)),
(Instruction::get_local(10, 0), Span(148, 149)),
(Instruction::r#return(true), Span(149, 149)),
(Instruction::load_constant(5, 5, false), Span(118, 119)),
(Instruction::r#move(5, 4), Span(129, 130)),
(Instruction::define_local(5, 0, false), Span(13, 14)),
(Instruction::get_local(6, 0), Span(139, 140)),
(Instruction::r#return(true), Span(140, 140)),
],
vec![
ConcreteValue::Integer(4),
@ -167,9 +182,10 @@ fn if_else_assigment_true() {
ConcreteValue::Integer(2),
ConcreteValue::Integer(3),
ConcreteValue::Integer(42),
ConcreteValue::Integer(0),
ConcreteValue::string("a")
],
vec![Local::new(5, Type::Integer, false, Scope::default())]
vec![Local::new(6, Type::Integer, false, Scope::default())]
)),
);
@ -189,6 +205,11 @@ fn if_else_complex() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![
(
*Instruction::equal(true, 0, 0)
@ -300,6 +321,11 @@ fn if_else_false() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(
*Instruction::equal(true, 0, 1)
@ -336,6 +362,11 @@ fn if_else_true() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(
*Instruction::equal(true, 0, 0)
@ -368,6 +399,11 @@ fn if_false() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![
(
*Instruction::equal(true, 0, 1)
@ -398,6 +434,11 @@ fn if_true() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![
(
*Instruction::equal(true, 0, 0)

View File

@ -8,6 +8,15 @@ fn function() {
run(source),
Ok(Some(ConcreteValue::Function(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Function(FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),
return_type: Box::new(Type::Integer),
}))
},
vec![
(Instruction::add(2, 0, 1), Span(30, 31)),
(Instruction::r#return(true), Span(35, 35)),
@ -29,6 +38,11 @@ fn function_call() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer)
},
vec![
(Instruction::load_constant(0, 0, false), Span(0, 36)),
(Instruction::load_constant(1, 1, false), Span(36, 37)),
@ -39,6 +53,11 @@ fn function_call() {
vec![
ConcreteValue::Function(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),
return_type: Box::new(Type::Integer)
},
vec![
(Instruction::add(2, 0, 1), Span(30, 31)),
(Instruction::r#return(true), Span(35, 36)),
@ -67,15 +86,24 @@ fn function_declaration() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None)
},
vec![
(Instruction::load_constant(0, 1, false), Span(0, 40)),
(Instruction::load_constant(0, 0, false), Span(0, 40)),
(Instruction::define_local(0, 0, false), Span(3, 6)),
(Instruction::r#return(false), Span(40, 40))
],
vec![
ConcreteValue::string("add"),
ConcreteValue::Function(Chunk::with_data(
Some("add".to_string()),
FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),
return_type: Box::new(Type::Integer)
},
vec![
(Instruction::add(2, 0, 1), Span(35, 36)),
(Instruction::r#return(true), Span(40, 40)),
@ -85,10 +113,11 @@ fn function_declaration() {
Local::new(0, Type::Integer, false, Scope::default()),
Local::new(1, Type::Integer, false, Scope::default())
]
),)
)),
ConcreteValue::string("add"),
],
vec![Local::new(
0,
1,
Type::Function(FunctionType {
type_parameters: None,
value_parameters: Some(vec![(0, Type::Integer), (1, Type::Integer)]),

View File

@ -8,6 +8,14 @@ fn empty_list() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::List {
item_type: Box::new(Type::Any),
length: 0
})
},
vec![
(Instruction::load_list(0, 0), Span(0, 2)),
(Instruction::r#return(true), Span(2, 2)),
@ -28,6 +36,14 @@ fn list() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::List {
item_type: Box::new(Type::Integer),
length: 3
})
},
vec![
(Instruction::load_constant(0, 0, false), Span(1, 2)),
(Instruction::load_constant(1, 1, false), Span(4, 5)),
@ -62,6 +78,14 @@ fn list_with_complex_expression() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::List {
item_type: Box::new(Type::Integer),
length: 3
})
},
vec![
(Instruction::load_constant(0, 0, false), Span(1, 2)),
(
@ -109,6 +133,14 @@ fn list_with_simple_expression() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::List {
item_type: Box::new(Type::Integer),
length: 3
})
},
vec![
(Instruction::load_constant(0, 0, false), Span(1, 2)),
(

View File

@ -8,6 +8,11 @@ fn and() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(Instruction::load_boolean(0, true, false), Span(0, 4)),
(Instruction::test(0, false), Span(5, 7)),
@ -31,6 +36,11 @@ fn or() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(Instruction::load_boolean(0, true, false), Span(0, 4)),
(Instruction::test(0, true), Span(5, 7)),
@ -54,6 +64,11 @@ fn variable_and() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(Instruction::load_boolean(0, true, false), Span(8, 12)),
(Instruction::define_local(0, 0, false), Span(4, 5)),

View File

@ -8,6 +8,11 @@ fn r#while() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 13)),
(Instruction::define_local(0, 0, true), Span(8, 9)),

View File

@ -8,6 +8,11 @@ fn add() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(
*Instruction::add(0, 0, 1)
@ -33,6 +38,11 @@ fn add_assign() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 13)),
(Instruction::define_local(0, 0, true), Span(8, 9)),
@ -92,6 +102,11 @@ fn divide() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(
*Instruction::divide(0, 0, 0)
@ -117,6 +132,11 @@ fn divide_assign() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 13)),
(Instruction::define_local(0, 0, true), Span(8, 9)),
@ -159,6 +179,11 @@ fn math_operator_precedence() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(
*Instruction::add(0, 0, 1)
@ -201,6 +226,11 @@ fn multiply() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(
*Instruction::multiply(0, 0, 1)
@ -226,6 +256,11 @@ fn multiply_assign() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 13)),
(Instruction::define_local(0, 0, true), Span(8, 9)),
@ -272,6 +307,11 @@ fn subtract() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(
*Instruction::subtract(0, 0, 1)
@ -297,6 +337,11 @@ fn subtract_assign() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 14)),
(Instruction::define_local(0, 0, true), Span(8, 9)),

View File

@ -8,14 +8,19 @@ fn panic() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
},
vec![
(Instruction::load_constant(0, 0, false), Span(6, 22)),
(Instruction::load_constant(1, 1, false), Span(24, 26)),
(
Instruction::call_native(2, NativeFunction::Panic, 2),
Instruction::call_native(0, NativeFunction::Panic, 2),
Span(0, 27)
),
(Instruction::r#return(true), Span(27, 27))
(Instruction::r#return(false), Span(27, 27))
],
vec![
ConcreteValue::string("Goodbye world!"),
@ -45,6 +50,11 @@ fn to_string() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::String { length: None }),
},
vec![
(Instruction::load_constant(0, 0, false), Span(10, 12)),
(

View File

@ -30,6 +30,11 @@ fn block_scope() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
},
vec![
(Instruction::load_constant(0, 0, false), Span(17, 18)),
(Instruction::define_local(0, 0, false), Span(13, 14)),
@ -93,6 +98,11 @@ fn multiple_block_scopes() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
},
vec![
(Instruction::load_constant(0, 0, false), Span(17, 18)),
(Instruction::define_local(0, 0, false), Span(13, 14)),

View File

@ -8,6 +8,11 @@ fn negate() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(*Instruction::negate(0, 0).set_b_is_constant(), Span(0, 1)),
(Instruction::r#return(true), Span(5, 5)),
@ -28,6 +33,11 @@ fn not() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Boolean),
},
vec![
(Instruction::load_boolean(0, true, false), Span(1, 5)),
(Instruction::not(1, 0), Span(0, 1)),

View File

@ -8,6 +8,11 @@ fn define_local() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::None),
},
vec![
(Instruction::load_constant(0, 0, false), Span(8, 10)),
(Instruction::define_local(0, 0, false), Span(4, 5)),
@ -46,6 +51,11 @@ fn set_local() {
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::Integer),
},
vec![
(Instruction::load_constant(0, 0, false), Span(12, 14)),
(Instruction::define_local(0, 0, true), Span(8, 9)),