1
0

Add new implicit return for end of file

This commit is contained in:
Jeff 2024-11-01 09:55:15 -04:00
parent 7e4f6654a4
commit ae6d3d7a82
6 changed files with 37 additions and 31 deletions

View File

@ -20,7 +20,7 @@ pub use instruction::Instruction;
pub use lexer::{lex, LexError, Lexer};
pub use native_function::{NativeFunction, NativeFunctionError};
pub use operation::Operation;
pub use parser::{parse, ParseError, Parser};
pub use parser::{parse, ParseError};
pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict};
pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Function, Primitive, Value, ValueError};

View File

@ -17,7 +17,7 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
let lexer = Lexer::new(source);
let mut parser = Parser::new(lexer).map_err(|error| DustError::Parse { error, source })?;
while !parser.is_eof() {
loop {
parser
.parse_statement(Allowed {
assignment: true,
@ -25,13 +25,17 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
implicit_return: true,
})
.map_err(|error| DustError::Parse { error, source })?;
if parser.is_eof() {
break;
}
}
Ok(parser.finish())
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize)]
pub struct Parser<'src> {
struct Parser<'src> {
lexer: Lexer<'src>,
chunk: Chunk,
@ -1256,6 +1260,10 @@ impl<'src> Parser<'src> {
fn parse_implicit_return(&mut self) -> Result<(), ParseError> {
if !self.current_is_expression {
if self.is_eof() {
self.emit_instruction(Instruction::r#return(false), self.current_position);
}
return Ok(());
}
@ -1273,6 +1281,8 @@ impl<'src> Parser<'src> {
if end_of_statement && !has_semicolon && !returned {
self.emit_instruction(Instruction::r#return(true), self.current_position);
} else if self.is_eof() {
self.emit_instruction(Instruction::r#return(false), self.current_position);
}
Ok(())

View File

@ -92,7 +92,7 @@ impl Vm {
self.set(to_register, value, position)?;
if jump {
self.jump_to_ip(self.ip + 1);
self.ip += 1;
}
}
Operation::LoadConstant => {
@ -103,7 +103,7 @@ impl Vm {
self.set_constant(to_register, from_constant, position)?;
if jump {
self.jump_to_ip(self.ip + 1);
self.ip += 1
}
}
Operation::LoadList => {
@ -252,7 +252,7 @@ impl Vm {
self.ip - jump_distance as usize
};
self.jump_to_ip(new_ip);
self.ip = new_ip;
}
}
Operation::Less => {
@ -288,7 +288,7 @@ impl Vm {
self.ip - jump_distance as usize
};
self.jump_to_ip(new_ip);
self.ip = new_ip;
}
}
Operation::LessEqual => {
@ -325,7 +325,7 @@ impl Vm {
self.ip - jump_distance as usize
};
self.jump_to_ip(new_ip);
self.ip = new_ip;
}
}
Operation::Negate => {
@ -360,8 +360,7 @@ impl Vm {
} else {
self.ip - jump_distance as usize - 1
};
self.jump_to_ip(new_ip);
self.ip = new_ip;
}
Operation::Call => {
let to_register = instruction.a();
@ -429,24 +428,6 @@ impl Vm {
Ok(None)
}
fn jump_to_ip(&mut self, new_ip: usize) {
let final_index = self.chunk.len() - 1;
if new_ip > final_index {
let last_operation = self
.chunk
.instructions()
.last()
.map(|(instruction, _)| instruction.operation());
if let Some(Operation::Return) = last_operation {
self.ip = final_index;
}
} else {
self.ip = new_ip;
}
}
fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> {
let length = self.stack.len();
self.last_assigned_register = Some(to_register);
@ -632,6 +613,10 @@ impl Vm {
}
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
if self.ip >= self.chunk.len() {
self.ip = self.chunk.len() - 1;
}
let current = self.chunk.get_instruction(self.ip, position)?;
self.ip += 1;

View File

@ -308,7 +308,7 @@ fn if_else_true() {
}
#[test]
fn if_expression_false() {
fn if_false() {
let source = "if 1 == 2 { 2 }";
assert_eq!(
@ -324,6 +324,7 @@ fn if_expression_false() {
),
(Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 13)),
(Instruction::r#return(false), Span(15, 15))
],
vec![Value::integer(1), Value::integer(2), Value::integer(2)],
vec![]
@ -334,7 +335,7 @@ fn if_expression_false() {
}
#[test]
fn if_expression_true() {
fn if_true() {
let source = "if 1 == 1 { 2 }";
assert_eq!(
@ -350,6 +351,7 @@ fn if_expression_true() {
),
(Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 13)),
(Instruction::r#return(false), Span(15, 15))
],
vec![Value::integer(1), Value::integer(1), Value::integer(2)],
vec![]

View File

@ -77,6 +77,7 @@ fn block_scope() {
(Instruction::define_local(3, 3, false), Span(125, 126)),
(Instruction::load_constant(4, 4, false), Span(158, 159)),
(Instruction::define_local(4, 4, false), Span(154, 155)),
(Instruction::r#return(false), Span(165, 165))
],
vec![
Value::integer(0),
@ -129,6 +130,7 @@ fn define_local() {
vec![
(Instruction::load_constant(0, 0, false), Span(8, 10)),
(Instruction::define_local(0, 0, false), Span(4, 5)),
(Instruction::r#return(false), Span(11, 11))
],
vec![Value::integer(42)],
vec![Local::new(Identifier::new("x"), None, false, 0, 0)]
@ -195,7 +197,12 @@ fn empty() {
assert_eq!(
parse(source),
Ok(Chunk::with_data(None, vec![], vec![], vec![]))
Ok(Chunk::with_data(
None,
vec![(Instruction::r#return(false), Span(0, 0))],
vec![],
vec![]
))
);
assert_eq!(run(source), Ok(None));
}
@ -262,6 +269,7 @@ fn function_declaration() {
vec![
(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![Value::function(
Chunk::with_data(

View File

@ -15,6 +15,7 @@ fn panic() {
Instruction::call_native(2, NativeFunction::Panic, 2),
Span(0, 27)
),
(Instruction::r#return(false), Span(27, 27))
],
vec![Value::string("Goodbye world!"), Value::integer(42)],
vec![]