diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index caa62ec..c75fd2f 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -40,20 +40,17 @@ impl Chunk { pub fn with_data( name: Option, + r#type: FunctionType, instructions: Vec<(Instruction, Span)>, constants: Vec, locals: Vec, ) -> 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 { diff --git a/dust-lang/src/compiler.rs b/dust-lang/src/compiler.rs index 2b25270..5ef781b 100644 --- a/dust-lang/src/compiler.rs +++ b/dust-lang/src/compiler.rs @@ -38,7 +38,29 @@ pub fn compile(source: &str) -> Result { .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 { @@ -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(); diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index cc35031..1d24efa 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -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}") } diff --git a/dust-lang/src/optimizer.rs b/dust-lang/src/optimizer.rs index c97d4b3..d30432d 100644 --- a/dust-lang/src/optimizer.rs +++ b/dust-lang/src/optimizer.rs @@ -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(&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()), diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index bbb388f..6dab9ba 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -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, 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 => { diff --git a/dust-lang/tests/basic.rs b/dust-lang/tests/basic.rs index fcf79ef..644f81e 100644 --- a/dust-lang/tests/basic.rs +++ b/dust-lang/tests/basic.rs @@ -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) diff --git a/dust-lang/tests/comparison.rs b/dust-lang/tests/comparison.rs index b193a05..7d57034 100644 --- a/dust-lang/tests/comparison.rs +++ b/dust-lang/tests/comparison.rs @@ -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) diff --git a/dust-lang/tests/control_flow.rs b/dust-lang/tests/control_flow.rs index ba7ac72..6c83b86 100644 --- a/dust-lang/tests/control_flow.rs +++ b/dust-lang/tests/control_flow.rs @@ -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) diff --git a/dust-lang/tests/functions.rs b/dust-lang/tests/functions.rs index 408e8a6..26b193c 100644 --- a/dust-lang/tests/functions.rs +++ b/dust-lang/tests/functions.rs @@ -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)]), diff --git a/dust-lang/tests/lists.rs b/dust-lang/tests/lists.rs index 3c38a64..c3aca69 100644 --- a/dust-lang/tests/lists.rs +++ b/dust-lang/tests/lists.rs @@ -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)), ( diff --git a/dust-lang/tests/logic.rs b/dust-lang/tests/logic.rs index e010762..0a5431c 100644 --- a/dust-lang/tests/logic.rs +++ b/dust-lang/tests/logic.rs @@ -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)), diff --git a/dust-lang/tests/loops.rs b/dust-lang/tests/loops.rs index c221343..6ae4183 100644 --- a/dust-lang/tests/loops.rs +++ b/dust-lang/tests/loops.rs @@ -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)), diff --git a/dust-lang/tests/math.rs b/dust-lang/tests/math.rs index 8ed7474..6caa8b7 100644 --- a/dust-lang/tests/math.rs +++ b/dust-lang/tests/math.rs @@ -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)), diff --git a/dust-lang/tests/native_functions.rs b/dust-lang/tests/native_functions.rs index deddfaf..03271c6 100644 --- a/dust-lang/tests/native_functions.rs +++ b/dust-lang/tests/native_functions.rs @@ -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)), ( diff --git a/dust-lang/tests/scopes.rs b/dust-lang/tests/scopes.rs index d1da13a..46ffb85 100644 --- a/dust-lang/tests/scopes.rs +++ b/dust-lang/tests/scopes.rs @@ -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)), diff --git a/dust-lang/tests/unary_operations.rs b/dust-lang/tests/unary_operations.rs index 7a15fe4..18d15c2 100644 --- a/dust-lang/tests/unary_operations.rs +++ b/dust-lang/tests/unary_operations.rs @@ -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)), diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index 78f5d52..90f3a34 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -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)),