Refactor how return instruction works; Begin passing tests
This commit is contained in:
parent
5411a1db27
commit
5015cf4cc4
@ -814,24 +814,26 @@ impl<'src> Parser<'src> {
|
|||||||
match self.current_token {
|
match self.current_token {
|
||||||
Token::Let => {
|
Token::Let => {
|
||||||
self.parse_let_statement(true, allow_return)?;
|
self.parse_let_statement(true, allow_return)?;
|
||||||
|
self.allow(TokenKind::Semicolon)?;
|
||||||
}
|
}
|
||||||
Token::LeftCurlyBrace => {
|
Token::LeftCurlyBrace => {
|
||||||
self.parse_block(true, true)?;
|
self.parse_block(true, true)?;
|
||||||
|
self.allow(TokenKind::Semicolon)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
|
if !self.allow(TokenKind::Semicolon)? && self.is_eof() {
|
||||||
|
let register = self.current_register.saturating_sub(1);
|
||||||
|
|
||||||
|
self.emit_instruction(
|
||||||
|
Instruction::r#return(register, register),
|
||||||
|
self.current_position,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.allow(TokenKind::Semicolon)? && self.is_eof() {
|
|
||||||
let register = self.current_register.saturating_sub(1);
|
|
||||||
|
|
||||||
self.emit_instruction(
|
|
||||||
Instruction::r#return(register, register),
|
|
||||||
self.current_position,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,13 +364,11 @@ impl Vm {
|
|||||||
self.ip = new_ip;
|
self.ip = new_ip;
|
||||||
}
|
}
|
||||||
Operation::Return => {
|
Operation::Return => {
|
||||||
let start_register = instruction.a();
|
return if let Some(Some(value)) = self.register_stack.pop() {
|
||||||
let end_register = instruction.b();
|
Ok(Some(value))
|
||||||
let return_value_count = (end_register - start_register).max(1);
|
} else {
|
||||||
|
Ok(None)
|
||||||
if return_value_count == 1 {
|
};
|
||||||
return Ok(Some(self.take(start_register, position)?));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ fn and() {
|
|||||||
(Instruction::test(0, false), Span(5, 7)),
|
(Instruction::test(0, false), Span(5, 7)),
|
||||||
(Instruction::jump(1, true), Span(5, 7)),
|
(Instruction::jump(1, true), Span(5, 7)),
|
||||||
(Instruction::load_boolean(1, false, false), Span(8, 13)),
|
(Instruction::load_boolean(1, false, false), Span(8, 13)),
|
||||||
|
(Instruction::r#return(0, 0), Span(13, 13)),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
vec![]
|
vec![]
|
||||||
@ -95,7 +96,10 @@ fn constant() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse("42"),
|
parse("42"),
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![(Instruction::load_constant(0, 0, false), Span(0, 2)),],
|
vec![
|
||||||
|
(Instruction::load_constant(0, 0, false), Span(0, 2)),
|
||||||
|
(Instruction::r#return(0, 0), Span(2, 2))
|
||||||
|
],
|
||||||
vec![Value::integer(42)],
|
vec![Value::integer(42)],
|
||||||
vec![]
|
vec![]
|
||||||
))
|
))
|
||||||
@ -124,20 +128,23 @@ fn define_local() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn divide() {
|
fn divide() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse("1.0 / 2.0"),
|
parse("2 / 2"),
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![(
|
vec![
|
||||||
*Instruction::divide(0, 0, 1)
|
(
|
||||||
.set_b_is_constant()
|
*Instruction::divide(0, 0, 1)
|
||||||
.set_c_is_constant(),
|
.set_b_is_constant()
|
||||||
Span(2, 3)
|
.set_c_is_constant(),
|
||||||
),],
|
Span(2, 3)
|
||||||
vec![Value::integer(1), Value::integer(2)],
|
),
|
||||||
|
(Instruction::r#return(0, 0), Span(5, 5))
|
||||||
|
],
|
||||||
|
vec![Value::integer(2), Value::integer(2)],
|
||||||
vec![]
|
vec![]
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(run("1 / 2"), Ok(Some(Value::float(0.5))));
|
assert_eq!(run("2 / 2"), Ok(Some(Value::integer(1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user