Continue adding type evaluations
This commit is contained in:
parent
960931ce6e
commit
0f3924341f
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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}")
|
||||
}
|
||||
|
@ -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()),
|
||||
|
@ -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 => {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)]),
|
||||
|
@ -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)),
|
||||
(
|
||||
|
@ -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)),
|
||||
|
@ -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)),
|
||||
|
@ -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)),
|
||||
|
@ -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)),
|
||||
(
|
||||
|
@ -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)),
|
||||
|
@ -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)),
|
||||
|
@ -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)),
|
||||
|
Loading…
Reference in New Issue
Block a user