Skip to content

Commit

Permalink
Adding support for strings
Browse files Browse the repository at this point in the history
  • Loading branch information
patbuc committed Jul 12, 2024
1 parent b08c915 commit 653dedc
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 3 deletions.
13 changes: 12 additions & 1 deletion src/compiler/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::vm::{Block, Value};
use rules::{ParseRule, Precedence};
use std::str::FromStr;

use crate::number;
use crate::{number, string};
#[cfg(feature = "disassemble")]
use tracing_attributes::instrument;

Expand Down Expand Up @@ -68,6 +68,12 @@ impl Parser {
self.emit_constant(number!(value));
}

#[cfg_attr(feature = "disassemble", instrument(skip(self)))]
fn string(&mut self) {
let value = &*self.previous_token.token;
self.emit_string(string!(value.to_string()));
}

#[cfg_attr(feature = "disassemble", instrument(skip(self)))]
fn grouping(&mut self) {
self.expression();
Expand Down Expand Up @@ -184,6 +190,11 @@ impl Parser {
self.current_block().write_constant(value, line)
}

fn emit_string(&mut self, value: Value) {
let line = self.previous_token.line;
self.current_block().write_string(value, line)
}

fn emit_op_code(&mut self, op_code: OpCode) {
let line = self.previous_token.line;
self.current_block().write_op_code(op_code, line);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ lazy_static! {
(TokenType::Less, ParseRule::new(None, Some(Parser::binary), Precedence::Comparison)),
(TokenType::LessEqual, ParseRule::new(None, Some(Parser::binary), Precedence::Comparison)),
(TokenType::Identifier, ParseRule::new(None, None, Precedence::None)),
(TokenType::String, ParseRule::new(None, None, Precedence::None)),
(TokenType::String, ParseRule::new(Some(Parser::string), None, Precedence::None)),
(TokenType::InterpolatedString, ParseRule::new(None, None, Precedence::None)),
(TokenType::Number, ParseRule::new(Some(Parser::number), None, Precedence::None)),
(TokenType::And, ParseRule::new(None, None, Precedence::None)),
Expand Down
12 changes: 12 additions & 0 deletions src/vm/block/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ impl Block {
Block {
name: String::from(name),
constants: Constants::new(),
strings: Constants::new(),
instructions: Vec::new(),
lines: Vec::new(),
}
Expand All @@ -32,6 +33,12 @@ impl Block {
}
}

pub(crate) fn write_string(&mut self, value: Value, line: u32) {
let string_index = self.strings.write_value(value) as u8;
self.write_op_code(OpCode::String, line);
self.write_u8(string_index)
}

pub(crate) fn write_u8(&mut self, value: u8) {
self.instructions.push(value)
}
Expand All @@ -51,6 +58,11 @@ impl Block {
self.constants.read_value(index)
}

#[inline(always)]
pub(in crate::vm) fn read_string(&self, index: usize) -> Value {
self.strings.read_value(index)
}

#[inline(always)]
pub(in crate::vm) fn read_u8(&self, offset: usize) -> u8 {
self.instructions[offset]
Expand Down
1 change: 1 addition & 0 deletions src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct VirtualMachine {
pub(crate) struct Block {
name: String,
constants: Constants,
strings: Constants,
instructions: Vec<u8>,
lines: Vec<Line>,
}
Expand Down
1 change: 1 addition & 0 deletions src/vm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub(crate) enum OpCode {
Greater = 0x0D,
Less = 0x0E,
Not = 0x0F,
String = 0x10,
}

impl OpCode {
Expand Down
17 changes: 16 additions & 1 deletion src/vm/virtual_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,16 @@ impl VirtualMachine {
OpCode::Add => {
let b = self.pop();
let a = self.pop();
self.push(Value::Number(as_number!(a) + as_number!(b)));
match (a, b) {
(Value::Number(a), Value::Number(b)) => self.push(Value::Number(a + b)),
(Value::String(a), Value::String(b)) => {
self.push(Value::String(format!("{a}{b}")))
}
_ => {
self.runtime_error("Operands must be two numbers or two strings");
return Result::RuntimeError;
}
}
}
OpCode::Subtract => {
let b = self.pop();
Expand Down Expand Up @@ -122,6 +131,12 @@ impl VirtualMachine {
let value = self.pop();
self.push(boolean!(is_falsey!(value)));
}
OpCode::String => {
let string_index = block.read_u8(self.ip + 1) as usize;
let string = block.read_string(string_index);
self.push(string);
self.ip += 1;
}
}
self.ip += 1;
}
Expand Down

0 comments on commit 653dedc

Please sign in to comment.