Change return to use last_assigned_value; Add scopes tests
This commit is contained in:
parent
004cf73959
commit
e304195661
@ -173,30 +173,19 @@ impl<'src> Parser<'src> {
|
|||||||
second_loader_new.set_a(first_loader.a());
|
second_loader_new.set_a(first_loader.a());
|
||||||
second_loader_new.set_b(second_loader.b());
|
second_loader_new.set_b(second_loader.b());
|
||||||
second_loader_new.set_c(second_loader.c());
|
second_loader_new.set_c(second_loader.c());
|
||||||
|
second_loader_new.set_b_to_boolean(second_loader.b_is_constant());
|
||||||
if second_loader.b_is_constant() {
|
second_loader_new.set_c_to_boolean(second_loader.c_is_constant());
|
||||||
second_loader_new.set_b_is_constant();
|
|
||||||
}
|
|
||||||
|
|
||||||
if second_loader.c_is_constant() {
|
|
||||||
second_loader_new.set_c_is_constant();
|
|
||||||
}
|
|
||||||
|
|
||||||
*second_loader = second_loader_new;
|
*second_loader = second_loader_new;
|
||||||
|
|
||||||
|
let jump = instructions.next().unwrap();
|
||||||
|
|
||||||
|
jump.set_b(jump.b() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_statement_length = 0;
|
self.current_statement_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_statement_instructions(&self) -> impl Iterator<Item = &Instruction> {
|
|
||||||
self.chunk
|
|
||||||
.instructions()
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.take(self.current_statement_length)
|
|
||||||
.map(|(instruction, _)| instruction)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_last_value_operation(&self) -> Option<Operation> {
|
fn get_last_value_operation(&self) -> Option<Operation> {
|
||||||
self.chunk
|
self.chunk
|
||||||
.instructions()
|
.instructions()
|
||||||
|
@ -18,6 +18,7 @@ pub struct Vm {
|
|||||||
ip: usize,
|
ip: usize,
|
||||||
chunk: Chunk,
|
chunk: Chunk,
|
||||||
stack: Vec<Register>,
|
stack: Vec<Register>,
|
||||||
|
last_assigned_register: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
@ -28,6 +29,7 @@ impl Vm {
|
|||||||
ip: 0,
|
ip: 0,
|
||||||
chunk,
|
chunk,
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
|
last_assigned_register: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,14 +389,17 @@ impl Vm {
|
|||||||
Operation::Return => {
|
Operation::Return => {
|
||||||
let should_return_value = instruction.b_as_boolean();
|
let should_return_value = instruction.b_as_boolean();
|
||||||
|
|
||||||
return if should_return_value {
|
if !should_return_value {
|
||||||
let top_of_stack = (self.stack.len() - 1) as u8;
|
return Ok(None);
|
||||||
let value = self.empty(top_of_stack, position)?;
|
}
|
||||||
|
|
||||||
Ok(Some(value))
|
if let Some(register) = self.last_assigned_register {
|
||||||
|
let value = self.empty(register, position)?;
|
||||||
|
|
||||||
|
return Ok(Some(value));
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
return Err(VmError::StackUnderflow { position });
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,6 +409,7 @@ impl Vm {
|
|||||||
|
|
||||||
fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> {
|
fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
let length = self.stack.len();
|
||||||
|
self.last_assigned_register = Some(to_register);
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
@ -450,6 +456,7 @@ impl Vm {
|
|||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
let length = self.stack.len();
|
||||||
|
self.last_assigned_register = Some(to_register);
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
@ -496,6 +503,7 @@ impl Vm {
|
|||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let length = self.stack.len();
|
let length = self.stack.len();
|
||||||
|
self.last_assigned_register = Some(to_register);
|
||||||
let to_register = to_register as usize;
|
let to_register = to_register as usize;
|
||||||
|
|
||||||
if length == Self::STACK_LIMIT {
|
if length == Self::STACK_LIMIT {
|
||||||
|
@ -569,6 +569,76 @@ fn if_else_complex() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn if_else_nested() {
|
||||||
|
let source = r#"
|
||||||
|
if 0 == 1 {
|
||||||
|
if 0 == 2 {
|
||||||
|
1;
|
||||||
|
} else {
|
||||||
|
2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if 0 == 3 {
|
||||||
|
3;
|
||||||
|
} else {
|
||||||
|
4;
|
||||||
|
}
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse(source),
|
||||||
|
Ok(Chunk::with_data(
|
||||||
|
None,
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
*Instruction::equal(true, 0, 1)
|
||||||
|
.set_b_is_constant()
|
||||||
|
.set_c_is_constant(),
|
||||||
|
Span(14, 16)
|
||||||
|
),
|
||||||
|
(Instruction::jump(7), Span(14, 16)),
|
||||||
|
(
|
||||||
|
*Instruction::equal(true, 0, 2)
|
||||||
|
.set_b_is_constant()
|
||||||
|
.set_c_is_constant(),
|
||||||
|
Span(38, 41)
|
||||||
|
),
|
||||||
|
(Instruction::jump(3), Span(38, 41)),
|
||||||
|
(Instruction::load_constant(0, 1, false), Span(61, 62)),
|
||||||
|
(Instruction::jump(11), Span(95, 95)),
|
||||||
|
(
|
||||||
|
*Instruction::equal(true, 0, 3)
|
||||||
|
.set_b_is_constant()
|
||||||
|
.set_c_is_constant(),
|
||||||
|
Span(77, 79)
|
||||||
|
),
|
||||||
|
(Instruction::jump(3), Span(77, 79)),
|
||||||
|
(Instruction::load_constant(0, 2, false), Span(94, 95)),
|
||||||
|
(Instruction::jump(11), Span(95, 95)),
|
||||||
|
(Instruction::load_constant(0, 3, false), Span(114, 115)),
|
||||||
|
(Instruction::jump(11), Span(95, 95)),
|
||||||
|
(Instruction::load_constant(0, 4, false), Span(134, 135)),
|
||||||
|
(Instruction::r#return(true), Span(146, 146)),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
Value::integer(0),
|
||||||
|
Value::integer(1),
|
||||||
|
Value::integer(0),
|
||||||
|
Value::integer(2),
|
||||||
|
Value::integer(1),
|
||||||
|
Value::integer(0),
|
||||||
|
Value::integer(3),
|
||||||
|
Value::integer(3),
|
||||||
|
Value::integer(4)
|
||||||
|
],
|
||||||
|
vec![]
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(run(source), Ok(Some(Value::integer(4))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_else_simple() {
|
fn if_else_simple() {
|
||||||
let source = "if 1 == 1 { 2 } else { 3 }";
|
let source = "if 1 == 1 { 2 } else { 3 }";
|
||||||
|
57
dust-lang/tests/scopes.rs
Normal file
57
dust-lang/tests/scopes.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use dust_lang::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn allow_access_to_parent_scope() {
|
||||||
|
let source = r#"
|
||||||
|
let x = 1;
|
||||||
|
{
|
||||||
|
x
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert_eq!(run(source), Ok(Some(Value::integer(1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn disallow_access_to_child_scope() {
|
||||||
|
// let source = r#"
|
||||||
|
// {
|
||||||
|
// let x = 1;
|
||||||
|
// }
|
||||||
|
// x
|
||||||
|
// "#;
|
||||||
|
|
||||||
|
// assert_eq!(
|
||||||
|
// run(source),
|
||||||
|
// Err(DustError::Parse {
|
||||||
|
// error: ParseError::Chunk(ChunkError::LocalOutOfScope {
|
||||||
|
// identifier: Identifier::new("x"),
|
||||||
|
// position: Span(52, 53)
|
||||||
|
// }),
|
||||||
|
// source
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn disallow_access_to_sibling_scope() {
|
||||||
|
// let source = r#"
|
||||||
|
// {
|
||||||
|
// let x = 1;
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// x
|
||||||
|
// }
|
||||||
|
// "#;
|
||||||
|
|
||||||
|
// assert_eq!(
|
||||||
|
// run(source),
|
||||||
|
// Err(DustError::Parse {
|
||||||
|
// error: ParseError::Chunk(ChunkError::LocalOutOfScope {
|
||||||
|
// identifier: Identifier::new("x"),
|
||||||
|
// position: Span(52, 53)
|
||||||
|
// }),
|
||||||
|
// source
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// }
|
@ -1,11 +1,13 @@
|
|||||||
fn fib (n: int) -> int {
|
fn fib (n: int) -> int {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
0
|
0
|
||||||
} else if n == 1 {
|
} else {
|
||||||
|
if n == 1 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
fib(n - 1) + fib(n - 2)
|
fib(n - 1) + fib(n - 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fib(2)
|
fib(10)
|
||||||
|
Loading…
Reference in New Issue
Block a user