refactor(tazjin/rlox): Remove use of sentinel values

The C code from which this is translated uses sentinel values for
various things, this commit replaces them with standard Rust types
instead (amongst a bunch of other small improvements).

Change-Id: I892811a7afebb5a0f3b825824fc493ab0b399e44
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3735
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
Vincent Ambo 2021-10-20 14:31:07 +02:00 committed by tazjin
parent 050a2b473c
commit bdde287d22
2 changed files with 24 additions and 21 deletions

View file

@ -222,7 +222,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
} }
fn var_declaration(&mut self) -> LoxResult<()> { fn var_declaration(&mut self) -> LoxResult<()> {
let global = self.parse_variable()?; let idx = self.parse_variable()?;
if self.match_token(&TokenKind::Equal) { if self.match_token(&TokenKind::Equal) {
self.expression()?; self.expression()?;
@ -231,12 +231,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
} }
self.expect_semicolon("expect ';' after variable declaration")?; self.expect_semicolon("expect ';' after variable declaration")?;
self.define_variable(global) self.define_variable(idx)
} }
fn define_variable(&mut self, var: ConstantIdx) -> LoxResult<()> { fn define_variable(&mut self, var: Option<ConstantIdx>) -> LoxResult<()> {
if self.locals.scope_depth == 0 { if self.locals.scope_depth == 0 {
self.emit_op(OpCode::OpDefineGlobal(var)); self.emit_op(OpCode::OpDefineGlobal(var.expect("should be global")));
} else { } else {
self.locals.locals.last_mut() self.locals.locals.last_mut()
.expect("fatal: variable not yet added at definition") .expect("fatal: variable not yet added at definition")
@ -418,13 +418,13 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
Ok(()) Ok(())
} }
fn named_variable(&mut self) -> LoxResult<()> { fn named_variable(&mut self, name: Token) -> LoxResult<()> {
let local_idx = self.resolve_local(); let local_idx = self.resolve_local(&name);
let ident = if local_idx.is_some() { let ident = if local_idx.is_some() {
None None
} else { } else {
Some(self.identifier_constant()?) Some(self.identifier_constant(&name)?)
}; };
if self.match_token(&TokenKind::Equal) { if self.match_token(&TokenKind::Equal) {
@ -448,7 +448,8 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
} }
fn variable(&mut self) -> LoxResult<()> { fn variable(&mut self) -> LoxResult<()> {
self.named_variable() let name = self.previous().clone();
self.named_variable(name)
} }
fn parse_precedence(&mut self, precedence: Precedence) -> LoxResult<()> { fn parse_precedence(&mut self, precedence: Precedence) -> LoxResult<()> {
@ -478,9 +479,9 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn identifier_str( fn identifier_str(
&mut self, &mut self,
token_fn: fn(&Self) -> &Token, token: &Token,
) -> LoxResult<InternedStr> { ) -> LoxResult<InternedStr> {
let ident = match &token_fn(self).kind { let ident = match &token.kind {
TokenKind::Identifier(ident) => ident.to_string(), TokenKind::Identifier(ident) => ident.to_string(),
_ => { _ => {
return Err(Error { return Err(Error {
@ -493,15 +494,14 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
Ok(self.strings.intern(ident)) Ok(self.strings.intern(ident))
} }
fn identifier_constant(&mut self) -> LoxResult<ConstantIdx> { fn identifier_constant(&mut self, name: &Token) -> LoxResult<ConstantIdx> {
let ident = self.identifier_str(Self::previous)?; let ident = self.identifier_str(name)?;
Ok(self.emit_constant(Value::String(ident.into()), false)) Ok(self.emit_constant(Value::String(ident.into()), false))
} }
fn resolve_local(&mut self) -> Option<StackIdx> { fn resolve_local(&self, name: &Token) -> Option<StackIdx> {
dbg!(&self.locals);
for (idx, local) in self.locals.locals.iter().enumerate().rev() { for (idx, local) in self.locals.locals.iter().enumerate().rev() {
if self.previous().lexeme == local.name.lexeme { if name.lexeme == local.name.lexeme {
if let Depth::Unitialised = local.depth { if let Depth::Unitialised = local.depth {
// TODO(tazjin): *return* err // TODO(tazjin): *return* err
panic!("can't read variable in its own initialiser"); panic!("can't read variable in its own initialiser");
@ -546,7 +546,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
Ok(()) Ok(())
} }
fn parse_variable(&mut self) -> LoxResult<ConstantIdx> { fn parse_variable(&mut self) -> LoxResult<Option<ConstantIdx>> {
consume!( consume!(
self, self,
TokenKind::Identifier(_), TokenKind::Identifier(_),
@ -555,11 +555,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
self.declare_variable()?; self.declare_variable()?;
if self.locals.scope_depth > 0 { if self.locals.scope_depth > 0 {
return Ok(ConstantIdx(0)); // TODO(tazjin): grr sentinel return Ok(None);
} }
let id = self.identifier_str(Self::previous)?; let name = self.previous().clone();
Ok(self.emit_constant(Value::String(id.into()), false)) let id = self.identifier_str(&name)?;
Ok(Some(self.emit_constant(Value::String(id.into()), false)))
} }
fn current_chunk(&mut self) -> &mut Chunk { fn current_chunk(&mut self) -> &mut Chunk {

View file

@ -138,12 +138,14 @@ fn local_variables() {
r#" r#"
var a = 10; var a = 10;
var b = 5; var b = 5;
var result = 0;
{ {
var b = 10; var b = 10;
var c = 2; var c = 2;
a * b * c; result = a * b * c;
} }
result;
"#, "#,
200.0, 200.0,
); );