Begin adding function calls
This commit is contained in:
parent
5bbda1a24e
commit
ea0be43199
@ -227,7 +227,7 @@ impl Chunk {
|
||||
r#type,
|
||||
is_mutable,
|
||||
self.scope_depth,
|
||||
Some(register_index),
|
||||
register_index,
|
||||
));
|
||||
|
||||
Ok(starting_length as u8)
|
||||
@ -249,7 +249,7 @@ impl Chunk {
|
||||
|
||||
log::debug!("Define local {}", local.identifier);
|
||||
|
||||
local.register_index = Some(register_index);
|
||||
local.register_index = register_index;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -309,7 +309,7 @@ pub struct Local {
|
||||
pub r#type: Option<Type>,
|
||||
pub is_mutable: bool,
|
||||
pub depth: usize,
|
||||
pub register_index: Option<u8>,
|
||||
pub register_index: u8,
|
||||
}
|
||||
|
||||
impl Local {
|
||||
@ -318,7 +318,7 @@ impl Local {
|
||||
r#type: Option<Type>,
|
||||
mutable: bool,
|
||||
depth: usize,
|
||||
register_index: Option<u8>,
|
||||
register_index: u8,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier,
|
||||
@ -499,17 +499,13 @@ impl<'a> ChunkDisassembler<'a> {
|
||||
},
|
||||
) in self.chunk.locals.iter().enumerate()
|
||||
{
|
||||
let register_display = register_index
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "empty".to_string());
|
||||
let identifier_display = identifier.as_str();
|
||||
let type_display = r#type
|
||||
.as_ref()
|
||||
.map(|r#type| r#type.to_string())
|
||||
.unwrap_or("unknown".to_string());
|
||||
let local_display = format!(
|
||||
"{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_display:8}"
|
||||
"{index:<5} {identifier_display:10} {type_display:8} {mutable:7} {depth:<5} {register_index:8}"
|
||||
);
|
||||
|
||||
push(&local_display, false);
|
||||
@ -541,7 +537,7 @@ impl<'a> ChunkDisassembler<'a> {
|
||||
value_option.as_ref().and_then(|value| match value {
|
||||
Value::Primitive(value_data) => value_data.as_function().map(|function| {
|
||||
function
|
||||
.body
|
||||
.chunk
|
||||
.disassembler("function")
|
||||
.styled(self.styled)
|
||||
.indent(self.indent + 1)
|
||||
|
@ -208,6 +208,15 @@ impl Instruction {
|
||||
instruction
|
||||
}
|
||||
|
||||
pub fn call(function_index: u8, argument_count: u8) -> Instruction {
|
||||
let mut instruction = Instruction(Operation::Call as u32);
|
||||
|
||||
instruction.set_a(function_index);
|
||||
instruction.set_b(argument_count);
|
||||
|
||||
instruction
|
||||
}
|
||||
|
||||
pub fn r#return(should_return_value: bool) -> Instruction {
|
||||
let mut instruction = Instruction(Operation::Return as u32);
|
||||
|
||||
@ -572,6 +581,25 @@ impl Instruction {
|
||||
|
||||
None
|
||||
}
|
||||
Operation::Call => {
|
||||
let function_index = self.a();
|
||||
let argument_count = self.b();
|
||||
let last_argument = function_index + argument_count;
|
||||
|
||||
let mut output = format!("R{function_index}(");
|
||||
|
||||
for register in function_index..last_argument {
|
||||
if register != last_argument - 1 {
|
||||
output.push_str(", ");
|
||||
}
|
||||
|
||||
output.push_str(&format!("R{}", register));
|
||||
}
|
||||
|
||||
output.push(')');
|
||||
|
||||
Some(output)
|
||||
}
|
||||
Operation::Return => None,
|
||||
};
|
||||
|
||||
@ -779,6 +807,15 @@ mod tests {
|
||||
assert!(instruction.c_as_boolean());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call() {
|
||||
let instruction = Instruction::call(4, 1);
|
||||
|
||||
assert_eq!(instruction.operation(), Operation::Call);
|
||||
assert_eq!(instruction.a(), 4);
|
||||
assert_eq!(instruction.b(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn r#return() {
|
||||
let instruction = Instruction::r#return(true);
|
||||
|
@ -28,7 +28,8 @@ const NEGATE: u8 = 0b0001_0010;
|
||||
const NOT: u8 = 0b0001_0011;
|
||||
|
||||
const JUMP: u8 = 0b0001_0100;
|
||||
const RETURN: u8 = 0b0001_0101;
|
||||
const CALL: u8 = 0b0001_0101;
|
||||
const RETURN: u8 = 0b0001_0110;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Operation {
|
||||
@ -68,6 +69,7 @@ pub enum Operation {
|
||||
|
||||
// Control flow
|
||||
Jump = JUMP as isize,
|
||||
Call = CALL as isize,
|
||||
Return = RETURN as isize,
|
||||
}
|
||||
|
||||
@ -119,6 +121,7 @@ impl From<u8> for Operation {
|
||||
NEGATE => Operation::Negate,
|
||||
NOT => Operation::Not,
|
||||
JUMP => Operation::Jump,
|
||||
CALL => Operation::Call,
|
||||
RETURN => Operation::Return,
|
||||
_ => {
|
||||
if cfg!(test) {
|
||||
@ -155,6 +158,7 @@ impl From<Operation> for u8 {
|
||||
Operation::Negate => NEGATE,
|
||||
Operation::Not => NOT,
|
||||
Operation::Jump => JUMP,
|
||||
Operation::Call => CALL,
|
||||
Operation::Return => RETURN,
|
||||
}
|
||||
}
|
||||
@ -184,6 +188,7 @@ impl Display for Operation {
|
||||
Operation::Negate => write!(f, "NEGATE"),
|
||||
Operation::Not => write!(f, "NOT"),
|
||||
Operation::Jump => write!(f, "JUMP"),
|
||||
Operation::Call => write!(f, "CALL"),
|
||||
Operation::Return => write!(f, "RETURN"),
|
||||
}
|
||||
}
|
||||
|
@ -303,14 +303,7 @@ impl<'src> Parser<'src> {
|
||||
|
||||
fn parse_grouped(&mut self, _: Allowed) -> Result<(), ParseError> {
|
||||
self.allow(Token::LeftParenthesis)?;
|
||||
self.parse_statement(
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
Context::None,
|
||||
)?;
|
||||
self.parse_expression()?;
|
||||
self.expect(Token::RightParenthesis)?;
|
||||
|
||||
self.parsed_expression = true;
|
||||
@ -323,14 +316,7 @@ impl<'src> Parser<'src> {
|
||||
let operator_position = self.current_position;
|
||||
|
||||
self.advance()?;
|
||||
self.parse_statement(
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
Context::None,
|
||||
)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let (previous_instruction, previous_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
@ -394,11 +380,7 @@ impl<'src> Parser<'src> {
|
||||
let local = self.chunk.get_local(local_index, self.current_position)?;
|
||||
is_mutable_local = local.is_mutable;
|
||||
|
||||
if let Some(index) = local.register_index {
|
||||
index
|
||||
} else {
|
||||
instruction.a()
|
||||
}
|
||||
local.register_index
|
||||
}
|
||||
Operation::LoadConstant => {
|
||||
is_constant = true;
|
||||
@ -705,25 +687,17 @@ impl<'src> Parser<'src> {
|
||||
});
|
||||
}
|
||||
|
||||
self.parse_statement(
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: true,
|
||||
implicit_return: false,
|
||||
},
|
||||
Context::Assignment,
|
||||
)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let (mut previous_instruction, previous_position) =
|
||||
self.chunk.pop_instruction(self.current_position)?;
|
||||
|
||||
if previous_instruction.operation().is_math() {
|
||||
let previous_register = self
|
||||
let register_index = self
|
||||
.chunk
|
||||
.get_local(local_index, start_position)?
|
||||
.register_index;
|
||||
|
||||
if let Some(register_index) = previous_register {
|
||||
log::trace!("Condensing SET_LOCAL to binary math expression");
|
||||
|
||||
previous_instruction.set_a(register_index);
|
||||
@ -731,7 +705,6 @@ impl<'src> Parser<'src> {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
self.emit_instruction(previous_instruction, previous_position);
|
||||
self.emit_instruction(
|
||||
@ -815,14 +788,7 @@ impl<'src> Parser<'src> {
|
||||
while !self.allow(Token::RightSquareBrace)? && !self.is_eof() {
|
||||
let next_register = self.current_register;
|
||||
|
||||
self.parse_statement(
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
Context::None,
|
||||
)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
if let Operation::LoadConstant = self.chunk.get_last_operation()? {
|
||||
self.increment_register()?;
|
||||
@ -853,21 +819,10 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
|
||||
fn parse_if(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
||||
let length = self.chunk.len();
|
||||
let expression_allowed = Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
};
|
||||
let block_allowed = Allowed {
|
||||
assignment: allowed.assignment,
|
||||
explicit_return: allowed.explicit_return,
|
||||
implicit_return: false,
|
||||
};
|
||||
|
||||
self.advance()?;
|
||||
self.parse_statement(expression_allowed, Context::None)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let length = self.chunk.len();
|
||||
let is_explicit_boolean =
|
||||
matches!(self.previous_token, Token::Boolean(_)) && length == self.chunk.len() - 1;
|
||||
|
||||
@ -878,6 +833,12 @@ impl<'src> Parser<'src> {
|
||||
);
|
||||
}
|
||||
|
||||
let block_allowed = Allowed {
|
||||
assignment: allowed.assignment,
|
||||
explicit_return: allowed.explicit_return,
|
||||
implicit_return: false,
|
||||
};
|
||||
|
||||
if let Token::LeftCurlyBrace = self.current_token {
|
||||
self.parse_block(block_allowed)?;
|
||||
}
|
||||
@ -917,14 +878,7 @@ impl<'src> Parser<'src> {
|
||||
|
||||
let jump_start = self.chunk.len();
|
||||
|
||||
self.parse_statement(
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
Context::None,
|
||||
)?;
|
||||
self.parse_expression()?;
|
||||
self.parse_block(Allowed {
|
||||
assignment: true,
|
||||
explicit_return: allowed.explicit_return,
|
||||
@ -988,6 +942,17 @@ impl<'src> Parser<'src> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_expression(&mut self) -> Result<(), ParseError> {
|
||||
self.parse(
|
||||
Precedence::None,
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_return(&mut self, allowed: Allowed) -> Result<(), ParseError> {
|
||||
let start = self.current_position.0;
|
||||
|
||||
@ -1120,7 +1085,8 @@ impl<'src> Parser<'src> {
|
||||
function_parser.advance()?;
|
||||
|
||||
let end = function_parser.current_position.1;
|
||||
let local_index = function_parser.chunk.declare_local(
|
||||
|
||||
function_parser.chunk.declare_local(
|
||||
parameter,
|
||||
Some(r#type),
|
||||
is_mutable,
|
||||
@ -1128,11 +1094,6 @@ impl<'src> Parser<'src> {
|
||||
Span(start, end),
|
||||
)?;
|
||||
|
||||
function_parser.chunk.define_local(
|
||||
local_index,
|
||||
function_parser.current_register,
|
||||
Span(start, end),
|
||||
)?;
|
||||
function_parser.increment_register()?;
|
||||
function_parser.allow(Token::Comma)?;
|
||||
}
|
||||
@ -1169,6 +1130,46 @@ impl<'src> Parser<'src> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_call(&mut self) -> Result<(), ParseError> {
|
||||
self.advance()?;
|
||||
|
||||
let function_register = self.current_register;
|
||||
let mut argument_count = 0;
|
||||
|
||||
while !self.allow(Token::RightParenthesis)? {
|
||||
if argument_count > 0 {
|
||||
self.expect(Token::Comma)?;
|
||||
}
|
||||
|
||||
let register = self.current_register;
|
||||
|
||||
self.parse(
|
||||
Precedence::None,
|
||||
Allowed {
|
||||
assignment: false,
|
||||
explicit_return: false,
|
||||
implicit_return: false,
|
||||
},
|
||||
)?;
|
||||
|
||||
if self.current_register == register {
|
||||
return Err(ParseError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
});
|
||||
}
|
||||
|
||||
argument_count += 1;
|
||||
}
|
||||
|
||||
self.emit_instruction(
|
||||
Instruction::call(function_register, argument_count),
|
||||
self.current_position,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse(&mut self, precedence: Precedence, allowed: Allowed) -> Result<(), ParseError> {
|
||||
if let Some(prefix_parser) = ParseRule::from(&self.current_token).prefix {
|
||||
log::debug!(
|
||||
@ -1384,8 +1385,8 @@ impl From<&Token<'_>> for ParseRule<'_> {
|
||||
},
|
||||
Token::LeftParenthesis => ParseRule {
|
||||
prefix: Some(Parser::parse_grouped),
|
||||
infix: None,
|
||||
precedence: Precedence::None,
|
||||
infix: Some(Parser::parse_call),
|
||||
precedence: Precedence::Call,
|
||||
},
|
||||
Token::LeftSquareBrace => ParseRule {
|
||||
prefix: Some(Parser::parse_list),
|
||||
|
@ -60,7 +60,7 @@ impl Value {
|
||||
}
|
||||
|
||||
pub fn function(body: Chunk) -> Self {
|
||||
Value::Primitive(Primitive::Function(Function { body }))
|
||||
Value::Primitive(Primitive::Function(Function { chunk: body }))
|
||||
}
|
||||
|
||||
pub fn integer<T: Into<i64>>(into_i64: T) -> Self {
|
||||
@ -286,7 +286,7 @@ impl From<&str> for Value {
|
||||
|
||||
impl Clone for Value {
|
||||
fn clone(&self) -> Self {
|
||||
log::trace!("Cloning value {:?}", self);
|
||||
log::trace!("Cloning value {self}");
|
||||
|
||||
match self {
|
||||
Value::Primitive(data) => Value::Primitive(data.clone()),
|
||||
@ -643,7 +643,7 @@ impl Ord for Primitive {
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Function {
|
||||
pub body: Chunk,
|
||||
pub chunk: Chunk,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -7,7 +7,6 @@ use crate::{
|
||||
|
||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||
let chunk = parse(source)?;
|
||||
|
||||
let mut vm = Vm::new(chunk);
|
||||
|
||||
vm.run()
|
||||
@ -32,10 +31,6 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_chunk(self) -> Chunk {
|
||||
self.chunk
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> Result<Option<Value>, VmError> {
|
||||
// DRY helper to get constant or register values for binary operations
|
||||
fn get_arguments(
|
||||
@ -131,14 +126,7 @@ impl Vm {
|
||||
let to_register = instruction.a();
|
||||
let local_index = instruction.b();
|
||||
let local = self.chunk.get_local(local_index, position)?;
|
||||
let from_register =
|
||||
local
|
||||
.register_index
|
||||
.ok_or_else(|| VmError::UndefinedVariable {
|
||||
identifier: local.identifier.clone(),
|
||||
position,
|
||||
})?;
|
||||
let value = self.take(from_register, to_register, position)?;
|
||||
let value = self.take(local.register_index, to_register, position)?;
|
||||
|
||||
self.set(to_register, value, position)?;
|
||||
}
|
||||
@ -380,11 +368,38 @@ impl Vm {
|
||||
|
||||
self.ip = new_ip;
|
||||
}
|
||||
Operation::Call => {
|
||||
let function_index = instruction.a();
|
||||
let argument_count = instruction.b();
|
||||
let function = if let Value::Primitive(Primitive::Function(function)) =
|
||||
self.get(function_index, position)?.clone()
|
||||
{
|
||||
function
|
||||
} else {
|
||||
todo!()
|
||||
};
|
||||
let mut function_vm = Vm::new(function.chunk);
|
||||
let first_argument_index = function_index + 1;
|
||||
let last_argument_index = first_argument_index + argument_count;
|
||||
|
||||
for argument_index in first_argument_index..=last_argument_index {
|
||||
let argument = self.empty(argument_index, position)?;
|
||||
|
||||
function_vm.stack.push(Register::Value(argument));
|
||||
}
|
||||
|
||||
let return_value = function_vm.run()?;
|
||||
|
||||
if let Some(value) = return_value {
|
||||
self.set(function_index, value, position)?;
|
||||
}
|
||||
}
|
||||
Operation::Return => {
|
||||
let should_return_value = instruction.b_as_boolean();
|
||||
let top_of_stack = (self.stack.len() - 1) as u8;
|
||||
|
||||
return if should_return_value {
|
||||
let value = self.empty(self.stack.len() - 1, position)?;
|
||||
let value = self.empty(top_of_stack, position)?;
|
||||
|
||||
Ok(Some(value))
|
||||
} else {
|
||||
@ -507,7 +522,9 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
fn empty(&mut self, index: usize, position: Span) -> Result<Value, VmError> {
|
||||
fn empty(&mut self, index: u8, position: Span) -> Result<Value, VmError> {
|
||||
let index = index as usize;
|
||||
|
||||
if index >= self.stack.len() {
|
||||
return Err(VmError::RegisterIndexOutOfBounds { position });
|
||||
}
|
||||
@ -517,7 +534,7 @@ impl Vm {
|
||||
match register {
|
||||
Register::Value(value) => Ok(value),
|
||||
Register::Pointer(register_index) => {
|
||||
let value = self.empty(register_index as usize, position)?;
|
||||
let value = self.empty(register_index, position)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ fn add_assign() {
|
||||
(Instruction::r#return(true), Span(24, 24))
|
||||
],
|
||||
vec![Value::integer(1), Value::integer(2)],
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, Some(0))]
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, 0)]
|
||||
))
|
||||
);
|
||||
|
||||
@ -105,11 +105,11 @@ fn block_scope() {
|
||||
Value::integer(1)
|
||||
],
|
||||
vec![
|
||||
Local::new(Identifier::new("a"), None, false, 0, Some(0)),
|
||||
Local::new(Identifier::new("b"), None, false, 1, Some(1)),
|
||||
Local::new(Identifier::new("c"), None, false, 2, Some(2)),
|
||||
Local::new(Identifier::new("d"), None, false, 1, Some(3)),
|
||||
Local::new(Identifier::new("e"), None, false, 0, Some(4)),
|
||||
Local::new(Identifier::new("a"), None, false, 0, 0),
|
||||
Local::new(Identifier::new("b"), None, false, 1, 1),
|
||||
Local::new(Identifier::new("c"), None, false, 2, 2),
|
||||
Local::new(Identifier::new("d"), None, false, 1, 3),
|
||||
Local::new(Identifier::new("e"), None, false, 0, 4),
|
||||
]
|
||||
)),
|
||||
);
|
||||
@ -148,7 +148,7 @@ fn define_local() {
|
||||
(Instruction::define_local(0, 0, false), Span(4, 5)),
|
||||
],
|
||||
vec![Value::integer(42)],
|
||||
vec![Local::new(Identifier::new("x"), None, false, 0, Some(0))]
|
||||
vec![Local::new(Identifier::new("x"), None, false, 0, 0)]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -197,7 +197,7 @@ fn divide_assign() {
|
||||
(Instruction::r#return(true), Span(24, 24))
|
||||
],
|
||||
vec![Value::integer(2), Value::integer(2)],
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, Some(0))]
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, 0)]
|
||||
))
|
||||
);
|
||||
|
||||
@ -261,7 +261,7 @@ fn equality_assignment_long() {
|
||||
(Instruction::r#return(true), Span(44, 44)),
|
||||
],
|
||||
vec![Value::integer(4), Value::integer(4)],
|
||||
vec![Local::new(Identifier::new("a"), None, false, 0, Some(0))]
|
||||
vec![Local::new(Identifier::new("a"), None, false, 0, 0)]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -290,7 +290,7 @@ fn equality_assignment_short() {
|
||||
(Instruction::r#return(true), Span(16, 16)),
|
||||
],
|
||||
vec![Value::integer(4), Value::integer(4)],
|
||||
vec![Local::new(Identifier::new("a"), None, false, 0, Some(0))]
|
||||
vec![Local::new(Identifier::new("a"), None, false, 0, 0)]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -664,7 +664,7 @@ fn multiply_assign() {
|
||||
(Instruction::r#return(true), Span(23, 23))
|
||||
],
|
||||
vec![Value::integer(2), Value::integer(3)],
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, Some(0)),]
|
||||
vec![Local::new(Identifier::new("a"), None, true, 0, 0),]
|
||||
))
|
||||
);
|
||||
|
||||
@ -803,7 +803,7 @@ fn set_local() {
|
||||
(Instruction::r#return(true), Span(25, 25)),
|
||||
],
|
||||
vec![Value::integer(41), Value::integer(42)],
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, Some(0)),]
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, 0)]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -852,7 +852,7 @@ fn subtract_assign() {
|
||||
(Instruction::r#return(true), Span(25, 25)),
|
||||
],
|
||||
vec![Value::integer(42), Value::integer(2)],
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, Some(0)),]
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, 0)]
|
||||
)),
|
||||
);
|
||||
|
||||
@ -879,8 +879,8 @@ fn variable_and() {
|
||||
],
|
||||
vec![],
|
||||
vec![
|
||||
Local::new(Identifier::new("a"), None, false, 0, Some(0)),
|
||||
Local::new(Identifier::new("b"), None, false, 0, Some(1)),
|
||||
Local::new(Identifier::new("a"), None, false, 0, 0),
|
||||
Local::new(Identifier::new("b"), None, false, 0, 1),
|
||||
]
|
||||
))
|
||||
);
|
||||
@ -909,7 +909,7 @@ fn r#while() {
|
||||
(Instruction::r#return(true), Span(42, 42)),
|
||||
],
|
||||
vec![Value::integer(0), Value::integer(5), Value::integer(1),],
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, Some(0)),]
|
||||
vec![Local::new(Identifier::new("x"), None, true, 0, 0),]
|
||||
)),
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user