Begin refactoring to avoid mutating locals in the chunk
This commit is contained in:
parent
c343b82873
commit
d82aed1a93
@ -19,7 +19,6 @@ use crate::{Disassembler, Instruction, Operation, Span, Type, Value};
|
||||
#[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Chunk {
|
||||
name: Option<String>,
|
||||
pub is_poisoned: bool,
|
||||
|
||||
instructions: Vec<(Instruction, Span)>,
|
||||
constants: Vec<Value>,
|
||||
@ -33,7 +32,6 @@ impl Chunk {
|
||||
pub fn new(name: Option<String>) -> Self {
|
||||
Self {
|
||||
name,
|
||||
is_poisoned: false,
|
||||
instructions: Vec::new(),
|
||||
constants: Vec::new(),
|
||||
locals: Vec::new(),
|
||||
@ -50,7 +48,6 @@ impl Chunk {
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
is_poisoned: false,
|
||||
instructions,
|
||||
constants,
|
||||
locals,
|
||||
@ -175,14 +172,6 @@ impl Chunk {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_not_poisoned(&self) -> Result<(), ChunkError> {
|
||||
if self.is_poisoned {
|
||||
Err(ChunkError::PoisonedChunk)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_constant_type(&self, constant_index: u8) -> Option<Type> {
|
||||
self.constants
|
||||
.get(constant_index as usize)
|
||||
@ -194,16 +183,6 @@ impl Chunk {
|
||||
}
|
||||
|
||||
pub fn get_register_type(&self, register_index: u8) -> Option<Type> {
|
||||
let local_type_option = self
|
||||
.locals
|
||||
.iter()
|
||||
.find(|local| local.register_index == register_index)
|
||||
.map(|local| local.r#type.clone());
|
||||
|
||||
if let Some(local_type) = local_type_option {
|
||||
return local_type;
|
||||
}
|
||||
|
||||
self.instructions
|
||||
.iter()
|
||||
.enumerate()
|
||||
@ -316,26 +295,16 @@ pub struct Local {
|
||||
|
||||
/// Scope where the variable was declared.
|
||||
pub scope: Scope,
|
||||
|
||||
/// Expected location of a local's value.
|
||||
pub register_index: u8,
|
||||
}
|
||||
|
||||
impl Local {
|
||||
/// Creates a new Local instance.
|
||||
pub fn new(
|
||||
identifier_index: u8,
|
||||
r#type: Option<Type>,
|
||||
mutable: bool,
|
||||
scope: Scope,
|
||||
register_index: u8,
|
||||
) -> Self {
|
||||
pub fn new(identifier_index: u8, r#type: Option<Type>, mutable: bool, scope: Scope) -> Self {
|
||||
Self {
|
||||
identifier_index,
|
||||
r#type,
|
||||
is_mutable: mutable,
|
||||
scope,
|
||||
register_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +48,9 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
||||
pub struct Compiler<'src> {
|
||||
chunk: Chunk,
|
||||
lexer: Lexer<'src>,
|
||||
optimization_count: usize,
|
||||
|
||||
local_definitions: Vec<u8>,
|
||||
optimization_count: usize,
|
||||
previous_is_expression: bool,
|
||||
minimum_register: u8,
|
||||
|
||||
@ -74,6 +75,7 @@ impl<'src> Compiler<'src> {
|
||||
Ok(Compiler {
|
||||
chunk,
|
||||
lexer,
|
||||
local_definitions: Vec::new(),
|
||||
optimization_count: 0,
|
||||
previous_is_expression: false,
|
||||
minimum_register: 0,
|
||||
@ -178,13 +180,10 @@ impl<'src> Compiler<'src> {
|
||||
let identifier = Value::string(identifier);
|
||||
let identifier_index = self.chunk.push_or_get_constant(identifier);
|
||||
|
||||
self.chunk.locals_mut().push(Local::new(
|
||||
identifier_index,
|
||||
r#type,
|
||||
is_mutable,
|
||||
scope,
|
||||
register_index,
|
||||
));
|
||||
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)
|
||||
}
|
||||
@ -505,7 +504,22 @@ impl<'src> Compiler<'src> {
|
||||
let local = self.get_local(local_index)?;
|
||||
is_mutable_local = local.is_mutable;
|
||||
|
||||
local.register_index
|
||||
*self
|
||||
.local_definitions
|
||||
.get(local_index as usize)
|
||||
.ok_or_else(|| {
|
||||
let identifier = self
|
||||
.chunk
|
||||
.constants()
|
||||
.get(local.identifier_index as usize)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
CompileError::UndeclaredVariable {
|
||||
identifier,
|
||||
position: self.current_position,
|
||||
}
|
||||
})?
|
||||
}
|
||||
Operation::LoadConstant => {
|
||||
is_constant = true;
|
||||
@ -821,28 +835,8 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
self.parse_expression()?;
|
||||
|
||||
let (mut previous_instruction, previous_position) =
|
||||
self.chunk.instructions_mut().pop().ok_or_else(|| {
|
||||
CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
}
|
||||
})?;
|
||||
let register = self.next_register() - 1;
|
||||
|
||||
if previous_instruction.operation().is_math() {
|
||||
let register_index = self.get_local(local_index)?.register_index;
|
||||
|
||||
log::trace!("Condensing SET_LOCAL to binary math expression");
|
||||
|
||||
previous_instruction.set_a(register_index);
|
||||
self.emit_instruction(previous_instruction, self.current_position);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let register = self.next_register();
|
||||
|
||||
self.emit_instruction(previous_instruction, previous_position);
|
||||
self.emit_instruction(
|
||||
Instruction::set_local(register, local_index),
|
||||
start_position,
|
||||
@ -1235,13 +1229,12 @@ impl<'src> Compiler<'src> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let register = self.next_register();
|
||||
|
||||
self.expect(Token::Equal)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let (local_index, _) = self.declare_local(identifier, r#type, is_mutable, scope, register);
|
||||
let register = self.next_register().saturating_sub(1);
|
||||
let (local_index, _) = self.declare_local(identifier, r#type, is_mutable, scope, register);
|
||||
|
||||
self.emit_instruction(
|
||||
Instruction::define_local(register, local_index, is_mutable),
|
||||
@ -1294,10 +1287,8 @@ impl<'src> Compiler<'src> {
|
||||
|
||||
function_compiler.advance()?;
|
||||
|
||||
let register = value_parameters
|
||||
.as_ref()
|
||||
.map(|values| values.len() as u8)
|
||||
.unwrap_or(0);
|
||||
let register = function_compiler.next_register();
|
||||
|
||||
let scope = function_compiler.chunk.current_scope();
|
||||
let (_, identifier_index) = function_compiler.declare_local(
|
||||
parameter,
|
||||
|
@ -295,7 +295,6 @@ impl<'a> Disassembler<'a> {
|
||||
identifier_index,
|
||||
r#type,
|
||||
scope,
|
||||
register_index,
|
||||
is_mutable: mutable,
|
||||
},
|
||||
) in self.chunk.locals().iter().enumerate()
|
||||
@ -319,7 +318,7 @@ impl<'a> Disassembler<'a> {
|
||||
})
|
||||
.unwrap_or("unknown".to_string());
|
||||
let local_display = format!(
|
||||
"{index:^3} {identifier_display:10} {type_display:16} {mutable:7} {scope:7} {register_index:8}"
|
||||
"{index:^3} {identifier_display:10} {type_display:16} {mutable:7} {scope:7}"
|
||||
);
|
||||
|
||||
self.push_details(&local_display);
|
||||
|
@ -324,13 +324,14 @@ impl NativeFunction {
|
||||
};
|
||||
|
||||
let first_index = to_register.saturating_sub(argument_count);
|
||||
let arguments = vm.open_nonempty_registers(first_index..to_register, position)?;
|
||||
|
||||
for (index, argument) in arguments.into_iter().enumerate() {
|
||||
for (index, register) in (first_index..to_register).enumerate() {
|
||||
if index != 0 {
|
||||
stdout.write(b" ").map_err(map_err)?;
|
||||
}
|
||||
|
||||
let argument = vm.open_register(register, position)?;
|
||||
|
||||
if let Value::Concrete(ConcreteValue::String(string)) = argument {
|
||||
let bytes = string.as_bytes();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! Virtual machine and errors
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::HashMap,
|
||||
fmt::{self, Display, Formatter},
|
||||
ops::Range,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -12,8 +12,8 @@ use crate::{
|
||||
};
|
||||
|
||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||
let mut chunk = compile(source)?;
|
||||
let mut vm = Vm::new(&mut chunk, None);
|
||||
let chunk = compile(source)?;
|
||||
let mut vm = Vm::new(&chunk, None);
|
||||
|
||||
vm.run()
|
||||
.map(|option| option.cloned())
|
||||
@ -34,8 +34,9 @@ pub fn run_and_display_output(source: &str) {
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Vm<'chunk, 'parent> {
|
||||
ip: usize,
|
||||
chunk: &'chunk mut Chunk,
|
||||
chunk: &'chunk Chunk,
|
||||
stack: Vec<Register>,
|
||||
local_definitions: HashMap<u8, u8>,
|
||||
last_assigned_register: Option<u8>,
|
||||
parent: Option<&'parent Vm<'chunk, 'parent>>,
|
||||
}
|
||||
@ -43,11 +44,12 @@ pub struct Vm<'chunk, 'parent> {
|
||||
impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
const STACK_LIMIT: usize = u16::MAX as usize;
|
||||
|
||||
pub fn new(chunk: &'chunk mut Chunk, parent: Option<&'parent Vm<'chunk, 'parent>>) -> Self {
|
||||
pub fn new(chunk: &'chunk Chunk, parent: Option<&'parent Vm<'chunk, 'parent>>) -> Self {
|
||||
Self {
|
||||
ip: 0,
|
||||
chunk,
|
||||
stack: Vec::new(),
|
||||
local_definitions: HashMap::new(),
|
||||
last_assigned_register: None,
|
||||
parent,
|
||||
}
|
||||
@ -172,24 +174,39 @@ impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
let from_register = instruction.a();
|
||||
let to_local = instruction.b();
|
||||
|
||||
self.define_local(to_local, from_register, position)?;
|
||||
self.define_local(to_local, from_register)?;
|
||||
}
|
||||
Operation::GetLocal => {
|
||||
let to_register = instruction.a();
|
||||
let local_index = instruction.b();
|
||||
let local = self.get_local(local_index, position)?;
|
||||
let local_register = self.local_definitions.get(&local_index).copied().ok_or(
|
||||
VmError::UndefinedLocal {
|
||||
local_index,
|
||||
position,
|
||||
},
|
||||
)?;
|
||||
|
||||
self.set_register(
|
||||
to_register,
|
||||
Register::StackPointer(local.register_index),
|
||||
Register::StackPointer(local_register),
|
||||
position,
|
||||
)?;
|
||||
}
|
||||
Operation::SetLocal => {
|
||||
let register = instruction.a();
|
||||
let local_index = instruction.b();
|
||||
let from_register = instruction.a();
|
||||
let to_local = instruction.b();
|
||||
let local_register = self.local_definitions.get(&to_local).copied().ok_or(
|
||||
VmError::UndefinedLocal {
|
||||
local_index: to_local,
|
||||
position,
|
||||
},
|
||||
)?;
|
||||
|
||||
self.define_local(local_index, register, position)?;
|
||||
self.set_register(
|
||||
local_register,
|
||||
Register::StackPointer(from_register),
|
||||
position,
|
||||
)?;
|
||||
}
|
||||
Operation::Add => {
|
||||
let to_register = instruction.a();
|
||||
@ -401,17 +418,17 @@ impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
let to_register = instruction.a();
|
||||
let function_register = instruction.b();
|
||||
let argument_count = instruction.c();
|
||||
let value = self.open_register(function_register, position)?.clone();
|
||||
let mut function =
|
||||
if let Value::Concrete(ConcreteValue::Function(function)) = value {
|
||||
function
|
||||
} else {
|
||||
return Err(VmError::ExpectedFunction {
|
||||
found: value,
|
||||
position,
|
||||
});
|
||||
};
|
||||
let mut function_vm = Vm::new(function.chunk_mut(), Some(self));
|
||||
let value = self.open_register(function_register, position)?;
|
||||
let function = if let Value::Concrete(ConcreteValue::Function(function)) = value
|
||||
{
|
||||
function
|
||||
} else {
|
||||
return Err(VmError::ExpectedFunction {
|
||||
found: value.clone(),
|
||||
position,
|
||||
});
|
||||
};
|
||||
let mut function_vm = Vm::new(function.chunk(), Some(self));
|
||||
let first_argument_index = function_register + 1;
|
||||
|
||||
for argument_index in
|
||||
@ -527,6 +544,8 @@ impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
position,
|
||||
})?;
|
||||
|
||||
log::trace!("Open R{register_index} to {register}");
|
||||
|
||||
match register {
|
||||
Register::Value(value) => Ok(value),
|
||||
Register::StackPointer(register_index) => self.open_register(*register_index, position),
|
||||
@ -556,67 +575,7 @@ impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_nonempty_registers(
|
||||
&self,
|
||||
register_index_range: Range<u8>,
|
||||
position: Span,
|
||||
) -> Result<Vec<&Value>, VmError> {
|
||||
let mut values = Vec::with_capacity(register_index_range.len());
|
||||
|
||||
for register_index in register_index_range.clone() {
|
||||
let register_index = register_index as usize;
|
||||
let register = self.stack.get(register_index).ok_or_else(|| {
|
||||
VmError::RegisterIndexOutOfBounds {
|
||||
index: register_index,
|
||||
position,
|
||||
}
|
||||
})?;
|
||||
|
||||
let value = match register {
|
||||
Register::Value(value) => value,
|
||||
Register::StackPointer(register_index) => {
|
||||
self.open_register(*register_index, position)?
|
||||
}
|
||||
Register::ConstantPointer(constant_index) => {
|
||||
self.get_constant(*constant_index, position)?
|
||||
}
|
||||
Register::ParentStackPointer(register_index) => {
|
||||
let parent = self
|
||||
.parent
|
||||
.as_ref()
|
||||
.ok_or(VmError::ExpectedParent { position })?;
|
||||
|
||||
parent.open_register(*register_index, position)?
|
||||
}
|
||||
Register::ParentConstantPointer(constant_index) => {
|
||||
let parent = self
|
||||
.parent
|
||||
.as_ref()
|
||||
.ok_or(VmError::ExpectedParent { position })?;
|
||||
|
||||
parent.get_constant(*constant_index, position)?
|
||||
}
|
||||
Register::Empty => continue,
|
||||
};
|
||||
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
if values.is_empty() {
|
||||
Err(VmError::EmptyRegisters {
|
||||
indexes: register_index_range,
|
||||
position,
|
||||
})
|
||||
} else {
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
|
||||
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
|
||||
self.chunk
|
||||
.expect_not_poisoned()
|
||||
.map_err(|error| VmError::Chunk { error, position })?;
|
||||
|
||||
let max_ip = self.chunk.len() - 1;
|
||||
|
||||
if self.ip > max_ip {
|
||||
@ -628,20 +587,10 @@ impl<'chunk, 'parent> Vm<'chunk, 'parent> {
|
||||
self.get_instruction(self.ip - 1, position)
|
||||
}
|
||||
|
||||
fn define_local(
|
||||
&mut self,
|
||||
local_index: u8,
|
||||
register_index: u8,
|
||||
position: Span,
|
||||
) -> Result<(), VmError> {
|
||||
let local = self
|
||||
.chunk
|
||||
.get_local_mut(local_index)
|
||||
.map_err(|error| VmError::Chunk { error, position })?;
|
||||
|
||||
fn define_local(&mut self, local_index: u8, register_index: u8) -> Result<(), VmError> {
|
||||
log::debug!("Define local L{}", local_index);
|
||||
|
||||
local.register_index = register_index;
|
||||
self.local_definitions.insert(local_index, register_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -694,9 +643,11 @@ pub enum VmError {
|
||||
|
||||
// Register errors
|
||||
EmptyRegister { index: usize, position: Span },
|
||||
EmptyRegisters { indexes: Range<u8>, position: Span },
|
||||
RegisterIndexOutOfBounds { index: usize, position: Span },
|
||||
|
||||
// Local errors
|
||||
UndefinedLocal { local_index: u8, position: Span },
|
||||
|
||||
// Execution errors
|
||||
ExpectedBoolean { found: Value, position: Span },
|
||||
ExpectedFunction { found: Value, position: Span },
|
||||
@ -717,7 +668,6 @@ impl AnnotatedError for VmError {
|
||||
match self {
|
||||
Self::Chunk { .. } => "Chunk error",
|
||||
Self::EmptyRegister { .. } => "Empty register",
|
||||
Self::EmptyRegisters { .. } => "Empty registers",
|
||||
Self::ExpectedBoolean { .. } => "Expected boolean",
|
||||
Self::ExpectedFunction { .. } => "Expected function",
|
||||
Self::ExpectedParent { .. } => "Expected parent",
|
||||
@ -725,6 +675,7 @@ impl AnnotatedError for VmError {
|
||||
Self::RegisterIndexOutOfBounds { .. } => "Register index out of bounds",
|
||||
Self::StackOverflow { .. } => "Stack overflow",
|
||||
Self::StackUnderflow { .. } => "Stack underflow",
|
||||
Self::UndefinedLocal { .. } => "Undefined local",
|
||||
Self::Value { .. } => "Value error",
|
||||
}
|
||||
}
|
||||
@ -733,10 +684,6 @@ impl AnnotatedError for VmError {
|
||||
match self {
|
||||
Self::Chunk { error, .. } => Some(error.to_string()),
|
||||
Self::EmptyRegister { index, .. } => Some(format!("Register R{index} is empty")),
|
||||
Self::EmptyRegisters { indexes: range, .. } => Some(format!(
|
||||
"Registers R{} to R{} are empty",
|
||||
range.start, range.end
|
||||
)),
|
||||
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
||||
Self::RegisterIndexOutOfBounds { index, .. } => {
|
||||
Some(format!("Register {index} does not exist"))
|
||||
@ -751,7 +698,6 @@ impl AnnotatedError for VmError {
|
||||
match self {
|
||||
Self::Chunk { position, .. } => *position,
|
||||
Self::EmptyRegister { position, .. } => *position,
|
||||
Self::EmptyRegisters { position, .. } => *position,
|
||||
Self::ExpectedBoolean { position, .. } => *position,
|
||||
Self::ExpectedFunction { position, .. } => *position,
|
||||
Self::ExpectedParent { position } => *position,
|
||||
@ -759,6 +705,7 @@ impl AnnotatedError for VmError {
|
||||
Self::RegisterIndexOutOfBounds { position, .. } => *position,
|
||||
Self::StackOverflow { position } => *position,
|
||||
Self::StackUnderflow { position } => *position,
|
||||
Self::UndefinedLocal { position, .. } => *position,
|
||||
Self::Value { position, .. } => *position,
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ fn equality_assignment_long() {
|
||||
depth: 0,
|
||||
block_index: 0
|
||||
},
|
||||
0
|
||||
)]
|
||||
)),
|
||||
);
|
||||
@ -62,7 +61,7 @@ fn equality_assignment_short() {
|
||||
(Instruction::r#return(true), Span(16, 16)),
|
||||
],
|
||||
vec![Value::integer(4), Value::string("a")],
|
||||
vec![Local::new(1, None, false, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, false, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -120,7 +119,7 @@ fn if_else_assigment_false() {
|
||||
Value::integer(42),
|
||||
Value::string("a")
|
||||
],
|
||||
vec![Local::new(5, None, false, Scope::default(), 0)]
|
||||
vec![Local::new(5, None, false, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -178,7 +177,7 @@ fn if_else_assigment_true() {
|
||||
Value::integer(42),
|
||||
Value::string("a")
|
||||
],
|
||||
vec![Local::new(5, None, false, Scope::default(), 0)]
|
||||
vec![Local::new(5, None, false, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
|
@ -15,8 +15,8 @@ fn function() {
|
||||
],
|
||||
vec![Value::string("a"), Value::string("b"),],
|
||||
vec![
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default(), 0),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default(), 1)
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default()),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default())
|
||||
]
|
||||
),
|
||||
FunctionType {
|
||||
@ -53,8 +53,8 @@ fn function_call() {
|
||||
],
|
||||
vec![Value::string("a"), Value::string("b"),],
|
||||
vec![
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default(), 0),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default(), 1)
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default()),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default())
|
||||
]
|
||||
),
|
||||
FunctionType {
|
||||
@ -97,8 +97,8 @@ fn function_declaration() {
|
||||
],
|
||||
vec![Value::string("a"), Value::string("b")],
|
||||
vec![
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default(), 0),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default(), 1)
|
||||
Local::new(0, Some(Type::Integer), false, Scope::default()),
|
||||
Local::new(1, Some(Type::Integer), false, Scope::default())
|
||||
]
|
||||
),
|
||||
FunctionType {
|
||||
@ -117,8 +117,7 @@ fn function_declaration() {
|
||||
})),
|
||||
false,
|
||||
Scope::default(),
|
||||
0
|
||||
),],
|
||||
)],
|
||||
)),
|
||||
);
|
||||
|
||||
|
@ -67,8 +67,8 @@ fn variable_and() {
|
||||
],
|
||||
vec![Value::string("a"), Value::string("b"),],
|
||||
vec![
|
||||
Local::new(0, None, false, Scope::default(), 0),
|
||||
Local::new(1, None, false, Scope::default(), 1),
|
||||
Local::new(0, None, false, Scope::default()),
|
||||
Local::new(1, None, false, Scope::default()),
|
||||
]
|
||||
))
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ fn r#while() {
|
||||
Value::integer(5),
|
||||
Value::integer(1),
|
||||
],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0),]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
|
@ -41,7 +41,7 @@ fn add_assign() {
|
||||
(Instruction::r#return(true), Span(24, 24))
|
||||
],
|
||||
vec![Value::integer(1), Value::string("a"), Value::integer(2)],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
))
|
||||
);
|
||||
|
||||
@ -124,7 +124,7 @@ fn divide_assign() {
|
||||
(Instruction::r#return(true), Span(24, 24))
|
||||
],
|
||||
vec![Value::integer(2), Value::string("a")],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
))
|
||||
);
|
||||
|
||||
@ -233,7 +233,7 @@ fn multiply_assign() {
|
||||
(Instruction::r#return(true), Span(23, 23))
|
||||
],
|
||||
vec![Value::integer(2), Value::string("a"), Value::integer(3)],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0),]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
))
|
||||
);
|
||||
|
||||
@ -300,7 +300,7 @@ fn subtract_assign() {
|
||||
(Instruction::r#return(true), Span(25, 25)),
|
||||
],
|
||||
vec![Value::integer(42), Value::string("x"), Value::integer(2)],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
|
@ -55,11 +55,11 @@ fn block_scope() {
|
||||
Value::string("e"),
|
||||
],
|
||||
vec![
|
||||
Local::new(1, None, false, Scope::new(0, 0), 0),
|
||||
Local::new(3, None, false, Scope::new(1, 1), 1),
|
||||
Local::new(5, None, false, Scope::new(2, 2), 2),
|
||||
Local::new(7, None, false, Scope::new(1, 1), 3),
|
||||
Local::new(8, None, false, Scope::new(0, 0), 4),
|
||||
Local::new(1, None, false, Scope::new(0, 0)),
|
||||
Local::new(3, None, false, Scope::new(1, 1)),
|
||||
Local::new(5, None, false, Scope::new(2, 2)),
|
||||
Local::new(7, None, false, Scope::new(1, 1)),
|
||||
Local::new(8, None, false, Scope::new(0, 0)),
|
||||
]
|
||||
)),
|
||||
);
|
||||
@ -127,15 +127,15 @@ fn multiple_block_scopes() {
|
||||
Value::string("e"),
|
||||
],
|
||||
vec![
|
||||
Local::new(1, None, false, Scope::new(0, 0), 0),
|
||||
Local::new(3, None, false, Scope::new(1, 1), 1),
|
||||
Local::new(5, None, false, Scope::new(2, 2), 2),
|
||||
Local::new(7, None, false, Scope::new(1, 1), 3),
|
||||
Local::new(8, None, false, Scope::new(0, 0), 4),
|
||||
Local::new(3, None, false, Scope::new(1, 3), 5),
|
||||
Local::new(5, None, false, Scope::new(2, 4), 6),
|
||||
Local::new(7, None, false, Scope::new(1, 3), 7),
|
||||
Local::new(9, None, false, Scope::new(0, 0), 8),
|
||||
Local::new(1, None, false, Scope::new(0, 0)),
|
||||
Local::new(3, None, false, Scope::new(1, 1)),
|
||||
Local::new(5, None, false, Scope::new(2, 2)),
|
||||
Local::new(7, None, false, Scope::new(1, 1)),
|
||||
Local::new(8, None, false, Scope::new(0, 0)),
|
||||
Local::new(3, None, false, Scope::new(1, 3)),
|
||||
Local::new(5, None, false, Scope::new(2, 4)),
|
||||
Local::new(7, None, false, Scope::new(1, 3)),
|
||||
Local::new(9, None, false, Scope::new(0, 0)),
|
||||
]
|
||||
)),
|
||||
);
|
||||
|
@ -14,7 +14,7 @@ fn define_local() {
|
||||
(Instruction::r#return(false), Span(11, 11))
|
||||
],
|
||||
vec![Value::integer(42), Value::string("x")],
|
||||
vec![Local::new(1, None, false, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, false, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -55,7 +55,7 @@ fn set_local() {
|
||||
(Instruction::r#return(true), Span(25, 25)),
|
||||
],
|
||||
vec![Value::integer(41), Value::string("x"), Value::integer(42)],
|
||||
vec![Local::new(1, None, true, Scope::default(), 0)]
|
||||
vec![Local::new(1, None, true, Scope::default())]
|
||||
)),
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user