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( pub fn with_data(
name: Option<String>, name: Option<String>,
r#type: FunctionType,
instructions: Vec<(Instruction, Span)>, instructions: Vec<(Instruction, Span)>,
constants: Vec<ConcreteValue>, constants: Vec<ConcreteValue>,
locals: Vec<Local>, locals: Vec<Local>,
) -> Self { ) -> Self {
Self { Self {
name, name,
r#type,
instructions, instructions,
constants, constants,
locals, 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() self.name.as_ref()
} }
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub fn r#type(&self) -> &FunctionType { pub fn r#type(&self) -> &FunctionType {
&self.r#type &self.r#type
} }
pub fn set_name(&mut self, name: String) { pub fn set_type(&mut self, r#type: FunctionType) {
self.name = Some(name); self.r#type = r#type;
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {

View File

@ -38,7 +38,29 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
.parse_top_level() .parse_top_level()
.map_err(|error| DustError::Compile { error, source })?; .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. /// 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); log::info!("End chunk with {} optimizations", self.optimization_count);
self.chunk.set_type(r#type);
self.chunk self.chunk
} }
@ -188,13 +212,14 @@ impl<'src> Compiler<'src> {
let identifier = ConcreteValue::string(identifier); let identifier = ConcreteValue::string(identifier);
let identifier_index = self.chunk.push_or_get_constant(identifier); let identifier_index = self.chunk.push_or_get_constant(identifier);
let local_index = self.chunk.locals().len() as u8;
self.chunk self.chunk
.locals_mut() .locals_mut()
.push(Local::new(identifier_index, r#type, is_mutable, scope)); .push(Local::new(identifier_index, r#type, is_mutable, scope));
self.local_definitions.push(register_index); 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> { fn allow(&mut self, allowed: Token) -> Result<bool, CompileError> {
@ -953,8 +978,8 @@ impl<'src> Compiler<'src> {
self.previous_expression_type = Type::None; self.previous_expression_type = Type::None;
let mut optimizer = Optimizer::new(self.chunk.instructions_mut()); let mut optimizer = Optimizer::new(&mut self.chunk);
let optimized = Optimizer::optimize_set_local(&mut optimizer); let optimized = optimizer.optimize_set_local();
if optimized { if optimized {
self.optimization_count += 1; self.optimization_count += 1;
@ -1171,7 +1196,7 @@ impl<'src> Compiler<'src> {
); );
if self.chunk.len() >= 4 { 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(); let optimized = optimizer.optimize_comparison();
if optimized { if optimized {
@ -1260,10 +1285,14 @@ impl<'src> Compiler<'src> {
} }
let end = self.previous_position.1; 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; 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( self.emit_instruction(
Instruction::call_native(to_register, function, argument_count), Instruction::call_native(to_register, function, argument_count),
@ -1428,7 +1457,6 @@ impl<'src> Compiler<'src> {
function_compiler.advance()?; function_compiler.advance()?;
let register = function_compiler.next_register(); let register = function_compiler.next_register();
let (_, identifier_index) = function_compiler.declare_local( let (_, identifier_index) = function_compiler.declare_local(
parameter, parameter,
r#type.clone(), r#type.clone(),
@ -1476,7 +1504,8 @@ impl<'src> Compiler<'src> {
value_parameters, value_parameters,
return_type, 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 constant_index = self.chunk.push_or_get_constant(function);
let function_end = self.current_position.1; let function_end = self.current_position.1;
let register = self.next_register(); let register = self.next_register();

View File

@ -463,11 +463,11 @@ impl Instruction {
Operation::DefineLocal => { Operation::DefineLocal => {
let to_register = self.a(); let to_register = self.a();
let local_index = self.b(); let local_index = self.b();
let mutable_display = if self.c_as_boolean() { "mut" } else { "" };
let identifier_display = match chunk.get_identifier(local_index) { let identifier_display = match chunk.get_identifier(local_index) {
Some(identifier) => identifier.to_string(), Some(identifier) => identifier.to_string(),
None => "???".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}") 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. //! 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. /// An instruction optimizer that mutably borrows instructions from a chunk.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug)]
pub struct Optimizer<'a> { pub struct Optimizer<'a> {
instructions: &'a mut Vec<(Instruction, Span)>, chunk: &'a mut Chunk,
} }
impl<'a> Optimizer<'a> { impl<'a> Optimizer<'a> {
/// Creates a new optimizer with a mutable reference to some of a chunk's instructions. /// 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 { pub fn new(instructions: &'a mut Chunk) -> Self {
Self { instructions } Self {
chunk: instructions,
}
} }
/// Optimizes a comparison operation. /// Optimizes a comparison operation.
@ -49,14 +51,15 @@ impl<'a> Optimizer<'a> {
log::debug!("Optimizing comparison"); log::debug!("Optimizing comparison");
let instructions = self.instructions_mut();
let first_loader_register = { 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.set_c_to_boolean(true);
first_loader.a() 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()); let mut second_loader_new = Instruction::with_operation(second_loader.operation());
second_loader_new.set_a(first_loader_register); second_loader_new.set_a(first_loader_register);
@ -85,22 +88,27 @@ impl<'a> Optimizer<'a> {
return false; return false;
} }
log::debug!("Optimizing set local"); self.instructions_mut().pop();
self.instructions.pop(); log::debug!("Optimizing by removing redundant SetLocal");
true true
} }
fn instructions_mut(&mut self) -> &mut Vec<(Instruction, Span)> {
self.chunk.instructions_mut()
}
fn get_operations<const COUNT: usize>(&self) -> Option<[Operation; COUNT]> { fn get_operations<const COUNT: usize>(&self) -> Option<[Operation; COUNT]> {
if self.instructions.len() < COUNT { if self.chunk.len() < COUNT {
return None; return None;
} }
let mut n_operations = [Operation::Return; COUNT]; let mut n_operations = [Operation::Return; COUNT];
for (nth, operation) in n_operations.iter_mut().rev().zip( for (nth, operation) in n_operations.iter_mut().rev().zip(
self.instructions self.chunk
.instructions()
.iter() .iter()
.rev() .rev()
.map(|(instruction, _)| instruction.operation()), .map(|(instruction, _)| instruction.operation()),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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