feat(tazjin/rlox): Implement global variable access

This also includes a fix for an issue where the identifiers of
variables were pushed onto the stack, which is incorrect.

Change-Id: Id89b388268efad295f29978d767aa4b33c4ded14
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2594
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2021-03-05 22:35:02 +02:00 committed by tazjin
parent 29b2a54705
commit 4162186a19
4 changed files with 48 additions and 6 deletions

View file

@ -145,6 +145,10 @@ fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> {
ParseRule::new(None, Some(Compiler::binary), Precedence::Comparison)
}
TokenKind::Identifier(_) => {
ParseRule::new(Some(Compiler::variable), None, Precedence::None)
}
TokenKind::String(_) => {
ParseRule::new(Some(Compiler::string), None, Precedence::None)
}
@ -238,7 +242,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn number(&mut self) -> LoxResult<()> {
if let TokenKind::Number(num) = self.previous().kind {
self.emit_constant(Value::Number(num));
self.emit_constant(Value::Number(num), true);
return Ok(());
}
@ -330,11 +334,23 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
};
let id = self.strings.intern(val);
self.emit_constant(Value::String(id.into()));
self.emit_constant(Value::String(id.into()), true);
Ok(())
}
fn named_variable(&mut self) -> LoxResult<()> {
let ident = self.identifier_str(Self::previous)?;
let constant_id =
self.emit_constant(Value::String(ident.into()), false);
self.emit_op(OpCode::OpGetGlobal(constant_id));
Ok(())
}
fn variable(&mut self) -> LoxResult<()> {
self.named_variable()
}
fn parse_precedence(&mut self, precedence: Precedence) -> LoxResult<()> {
self.advance();
let rule: ParseRule<T> = rule_for(&self.previous().kind);
@ -385,7 +401,7 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
);
let id = self.identifier_str(Self::previous)?;
Ok(self.emit_constant(Value::String(id.into())))
Ok(self.emit_constant(Value::String(id.into()), false))
}
fn current_chunk(&mut self) -> &mut Chunk {
@ -409,9 +425,13 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
self.current_chunk().add_op(op, line);
}
fn emit_constant(&mut self, val: Value) -> usize {
fn emit_constant(&mut self, val: Value, with_op: bool) -> usize {
let idx = self.chunk.add_constant(val);
self.emit_op(OpCode::OpConstant(idx));
if with_op {
self.emit_op(OpCode::OpConstant(idx));
}
idx
}