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<()> {
|
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 {
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue