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 lexer::{lex, LexError, Lexer};
pub use native_function::{NativeFunction, NativeFunctionError}; pub use native_function::{NativeFunction, NativeFunctionError};
pub use operation::Operation; 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 r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict};
pub use token::{Token, TokenKind, TokenOwned}; pub use token::{Token, TokenKind, TokenOwned};
pub use value::{Function, Primitive, Value, ValueError}; 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 lexer = Lexer::new(source);
let mut parser = Parser::new(lexer).map_err(|error| DustError::Parse { error, source })?; let mut parser = Parser::new(lexer).map_err(|error| DustError::Parse { error, source })?;
while !parser.is_eof() { loop {
parser parser
.parse_statement(Allowed { .parse_statement(Allowed {
assignment: true, assignment: true,
@ -25,13 +25,17 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
implicit_return: true, implicit_return: true,
}) })
.map_err(|error| DustError::Parse { error, source })?; .map_err(|error| DustError::Parse { error, source })?;
if parser.is_eof() {
break;
}
} }
Ok(parser.finish()) Ok(parser.finish())
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize)]
pub struct Parser<'src> { struct Parser<'src> {
lexer: Lexer<'src>, lexer: Lexer<'src>,
chunk: Chunk, chunk: Chunk,
@ -1256,6 +1260,10 @@ impl<'src> Parser<'src> {
fn parse_implicit_return(&mut self) -> Result<(), ParseError> { fn parse_implicit_return(&mut self) -> Result<(), ParseError> {
if !self.current_is_expression { if !self.current_is_expression {
if self.is_eof() {
self.emit_instruction(Instruction::r#return(false), self.current_position);
}
return Ok(()); return Ok(());
} }
@ -1273,6 +1281,8 @@ impl<'src> Parser<'src> {
if end_of_statement && !has_semicolon && !returned { if end_of_statement && !has_semicolon && !returned {
self.emit_instruction(Instruction::r#return(true), self.current_position); 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(()) Ok(())

View File

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

View File

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

View File

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

View File

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