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:
parent
050a2b473c
commit
bdde287d22
2 changed files with 24 additions and 21 deletions
|
@ -222,7 +222,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
}
|
||||
|
||||
fn var_declaration(&mut self) -> LoxResult<()> {
|
||||
let global = self.parse_variable()?;
|
||||
let idx = self.parse_variable()?;
|
||||
|
||||
if self.match_token(&TokenKind::Equal) {
|
||||
self.expression()?;
|
||||
|
@ -231,12 +231,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
}
|
||||
|
||||
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 {
|
||||
self.emit_op(OpCode::OpDefineGlobal(var));
|
||||
self.emit_op(OpCode::OpDefineGlobal(var.expect("should be global")));
|
||||
} else {
|
||||
self.locals.locals.last_mut()
|
||||
.expect("fatal: variable not yet added at definition")
|
||||
|
@ -418,13 +418,13 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn named_variable(&mut self) -> LoxResult<()> {
|
||||
let local_idx = self.resolve_local();
|
||||
fn named_variable(&mut self, name: Token) -> LoxResult<()> {
|
||||
let local_idx = self.resolve_local(&name);
|
||||
|
||||
let ident = if local_idx.is_some() {
|
||||
None
|
||||
} else {
|
||||
Some(self.identifier_constant()?)
|
||||
Some(self.identifier_constant(&name)?)
|
||||
};
|
||||
|
||||
if self.match_token(&TokenKind::Equal) {
|
||||
|
@ -448,7 +448,8 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
}
|
||||
|
||||
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<()> {
|
||||
|
@ -478,9 +479,9 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
|
||||
fn identifier_str(
|
||||
&mut self,
|
||||
token_fn: fn(&Self) -> &Token,
|
||||
token: &Token,
|
||||
) -> LoxResult<InternedStr> {
|
||||
let ident = match &token_fn(self).kind {
|
||||
let ident = match &token.kind {
|
||||
TokenKind::Identifier(ident) => ident.to_string(),
|
||||
_ => {
|
||||
return Err(Error {
|
||||
|
@ -493,15 +494,14 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
Ok(self.strings.intern(ident))
|
||||
}
|
||||
|
||||
fn identifier_constant(&mut self) -> LoxResult<ConstantIdx> {
|
||||
let ident = self.identifier_str(Self::previous)?;
|
||||
fn identifier_constant(&mut self, name: &Token) -> LoxResult<ConstantIdx> {
|
||||
let ident = self.identifier_str(name)?;
|
||||
Ok(self.emit_constant(Value::String(ident.into()), false))
|
||||
}
|
||||
|
||||
fn resolve_local(&mut self) -> Option<StackIdx> {
|
||||
dbg!(&self.locals);
|
||||
fn resolve_local(&self, name: &Token) -> Option<StackIdx> {
|
||||
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 {
|
||||
// TODO(tazjin): *return* err
|
||||
panic!("can't read variable in its own initialiser");
|
||||
|
@ -546,7 +546,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_variable(&mut self) -> LoxResult<ConstantIdx> {
|
||||
fn parse_variable(&mut self) -> LoxResult<Option<ConstantIdx>> {
|
||||
consume!(
|
||||
self,
|
||||
TokenKind::Identifier(_),
|
||||
|
@ -555,11 +555,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
|
|||
|
||||
self.declare_variable()?;
|
||||
if self.locals.scope_depth > 0 {
|
||||
return Ok(ConstantIdx(0)); // TODO(tazjin): grr sentinel
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let id = self.identifier_str(Self::previous)?;
|
||||
Ok(self.emit_constant(Value::String(id.into()), false))
|
||||
let name = self.previous().clone();
|
||||
let id = self.identifier_str(&name)?;
|
||||
Ok(Some(self.emit_constant(Value::String(id.into()), false)))
|
||||
}
|
||||
|
||||
fn current_chunk(&mut self) -> &mut Chunk {
|
||||
|
|
|
@ -138,12 +138,14 @@ fn local_variables() {
|
|||
r#"
|
||||
var a = 10;
|
||||
var b = 5;
|
||||
|
||||
var result = 0;
|
||||
{
|
||||
var b = 10;
|
||||
var c = 2;
|
||||
a * b * c;
|
||||
result = a * b * c;
|
||||
}
|
||||
|
||||
result;
|
||||
"#,
|
||||
200.0,
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue