diff --git a/src/ast/expression/expression_node.rs b/src/ast/expression/expression_node.rs index 41d20d0..0e92105 100644 --- a/src/ast/expression/expression_node.rs +++ b/src/ast/expression/expression_node.rs @@ -8,6 +8,7 @@ pub enum ExpressionNode { BinaryExpr(BinaryExpr), GroupingExpr(GroupingExpr), Literal(Literal), + Variable(VariableExpr), UnaryExpr(UnaryExpr), } @@ -16,7 +17,12 @@ macro_rules! all_variants { { use match_any::match_any; use $crate::ast::expression::expression_node::*; - match_any!($expr, ExpressionNode::BinaryExpr($val_name) | ExpressionNode::GroupingExpr($val_name) | ExpressionNode::Literal($val_name) | ExpressionNode::UnaryExpr($val_name) => $expr_arm) + match_any!($expr, + ExpressionNode::BinaryExpr($val_name) | + ExpressionNode::GroupingExpr($val_name) | + ExpressionNode::Literal($val_name) | + ExpressionNode::Variable($val_name) | + ExpressionNode::UnaryExpr($val_name) => $expr_arm) } }; } @@ -176,6 +182,22 @@ impl Debug for UnaryExpr { } } +pub struct VariableExpr { + pub var_name: String, +} + +impl Debug for VariableExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(variable({}))", self.var_name) + } +} + +impl VariableExpr { + pub fn new(var_name: String) -> Self { + Self { var_name } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/ast/expression/expression_parser.rs b/src/ast/expression/expression_parser.rs index 3059434..3ae84db 100644 --- a/src/ast/expression/expression_parser.rs +++ b/src/ast/expression/expression_parser.rs @@ -116,6 +116,7 @@ impl<'a, T: Iterator>> Parser<'a, T> { None => return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace)), } } + TokenType::Identifier(var_name) => VariableExpr::new(var_name).into(), a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))), }; Ok(node) diff --git a/src/interpreter/ast_walker/expression_interpreter.rs b/src/interpreter/ast_walker/expression_interpreter.rs index e3a0892..f467c0d 100644 --- a/src/interpreter/ast_walker/expression_interpreter.rs +++ b/src/interpreter/ast_walker/expression_interpreter.rs @@ -1,23 +1,24 @@ use super::Interpret; use super::{types::Value, RuntimeError}; use crate::ast::expression::expression_node; +use crate::interpreter::world::World; impl Interpret for expression_node::ExpressionNode { - fn interpret(&self) -> Result { - expression_node::all_variants!(self, n => n.interpret()) + fn interpret(&self, w: &mut World) -> Result { + expression_node::all_variants!(self, n => n.interpret(w)) } } impl Interpret for expression_node::Literal { - fn interpret(&self) -> Result { + fn interpret(&self, _: &mut World) -> Result { Ok(self.clone().into()) } } impl Interpret for expression_node::BinaryExpr { - fn interpret(&self) -> Result { - let left_val = self.left.interpret().expect("expected lval"); - let right_val = self.right.interpret().expect("expected rval"); + fn interpret(&self, w: &mut World) -> Result { + let left_val = self.left.interpret(w).expect("expected lval"); + let right_val = self.right.interpret(w).expect("expected rval"); match self.operator { expression_node::Operator::BangEqual => Ok((left_val != right_val).into()), expression_node::Operator::Less => Ok((left_val < right_val).into()), @@ -31,8 +32,8 @@ impl Interpret for expression_node::BinaryExpr { } impl Interpret for expression_node::UnaryExpr { - fn interpret(&self) -> Result { - let val = self.right.interpret()?; + fn interpret(&self, w: &mut World) -> Result { + let val = self.right.interpret(w)?; match self.operator { expression_node::UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())), expression_node::UnaryOperator::Minus => match val { @@ -45,7 +46,16 @@ impl Interpret for expression_node::UnaryExpr { } impl Interpret for expression_node::GroupingExpr { - fn interpret(&self) -> Result { - self.0.interpret() + fn interpret(&self, w: &mut World) -> Result { + self.0.interpret(w) + } +} + +impl Interpret for expression_node::VariableExpr { + fn interpret(&self, world: &mut World) -> Result { + match world.get_var(&self.var_name) { + Some(v) => Ok(v.clone()), + None => Err(RuntimeError), + } } } diff --git a/src/interpreter/ast_walker/mod.rs b/src/interpreter/ast_walker/mod.rs index 912b791..2a2ef22 100644 --- a/src/interpreter/ast_walker/mod.rs +++ b/src/interpreter/ast_walker/mod.rs @@ -1,8 +1,8 @@ mod expression_interpreter; mod statement_interpreter; -use super::types::Value; pub use super::{error::RuntimeError, types}; +use super::{types::Value, world::World}; pub trait Interpret { - fn interpret(&self) -> Result; + fn interpret(&self, world: &mut World) -> Result; } diff --git a/src/interpreter/ast_walker/statement_interpreter.rs b/src/interpreter/ast_walker/statement_interpreter.rs index 777003b..a348ad3 100644 --- a/src/interpreter/ast_walker/statement_interpreter.rs +++ b/src/interpreter/ast_walker/statement_interpreter.rs @@ -1,30 +1,33 @@ use super::Interpret; use super::{types::Value, RuntimeError}; use crate::ast::statement::statement_node; +use crate::interpreter::world::World; impl Interpret for statement_node::Statement { - fn interpret(&self) -> Result { - statement_node::all_variants!(self, n => n.interpret()) + fn interpret(&self, w: &mut World) -> Result { + statement_node::all_variants!(self, n => n.interpret(w)) } } impl Interpret for statement_node::PrintStatement { - fn interpret(&self) -> Result { - let res = self.0.interpret()?; + fn interpret(&self, w: &mut World) -> Result { + let res = self.0.interpret(w)?; println!("{:?}", res); Ok(res) } } impl Interpret for statement_node::ExpressionStatement { - fn interpret(&self) -> Result { - self.0.interpret() + fn interpret(&self, w: &mut World) -> Result { + self.0.interpret(w) } } impl Interpret for statement_node::VariableAssignmentStatement { - fn interpret(&self) -> Result { - let expr_val = self.node.interpret()?; + fn interpret(&self, w: &mut World) -> Result { + let expr_val = self.node.interpret(w)?; + // Clone for now, later this will use a GC and won't need to clone + w.set_var(self.var_name.clone(), expr_val.clone()); Ok(expr_val) } } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index d2e9cfb..6057071 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -1,3 +1,4 @@ pub mod ast_walker; pub mod error; pub mod types; +pub mod world; diff --git a/src/interpreter/types.rs b/src/interpreter/types.rs index 60d5861..a942eb3 100644 --- a/src/interpreter/types.rs +++ b/src/interpreter/types.rs @@ -1,7 +1,7 @@ use crate::ast::expression::expression_node; use from_variants::FromVariants; -#[derive(Debug, PartialEq, PartialOrd, FromVariants)] +#[derive(Debug, PartialEq, PartialOrd, Clone, FromVariants)] pub enum Value { Int(i32), Float(f32), diff --git a/src/interpreter/world.rs b/src/interpreter/world.rs new file mode 100644 index 0000000..a3ed8d7 --- /dev/null +++ b/src/interpreter/world.rs @@ -0,0 +1,35 @@ +use std::collections::HashMap; + +use crate::ast::statement::statement_node::Statement; + +use super::{ + ast_walker::{Interpret, RuntimeError}, + types::Value, +}; + +#[derive(Default)] +pub struct World { + variables: HashMap, +} + +impl World { + pub fn set_var(&mut self, name: String, v: Value) -> Option { + self.variables.insert(name, v) + } + pub fn get_var(&mut self, name: &str) -> Option<&Value> { + self.variables.get(name) + } +} + +impl World { + pub fn new() -> Self { + Self::default() + } + pub fn exec(&mut self, nodes: Vec) -> Result { + let mut last_res = Value::Nil; + for statement in nodes { + last_res = statement.interpret(self)?; + } + Ok(last_res) + } +} diff --git a/src/lib.rs b/src/lib.rs index d29df90..fa41e31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ use ast::parser::ParseAllResult; use ast::statement::statement_node::Statement; use interpreter::ast_walker::{Interpret, RuntimeError}; use interpreter::types::Value; +use interpreter::world::World; use lexer::{token::Token, Lexer, LexingError}; pub fn lex<'a, 'b>( @@ -25,8 +26,9 @@ pub fn parse(tokens: Vec) -> ParseAllResult { pub fn exec(nodes: Vec) -> Result { let mut last_res = Value::Nil; + let mut world = World::new(); for statement in nodes { - last_res = statement.interpret()?; + last_res = statement.interpret(&mut world)?; } Ok(last_res) } diff --git a/src/main.rs b/src/main.rs index 26f1f54..2bd191f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use clap::Parser; -use crftng_intrprtrs::{exec, lex, parse}; +use crftng_intrprtrs::interpreter::world::World; +use crftng_intrprtrs::{lex, parse}; use std::path::PathBuf; use std::{fs, io}; use tracing::Level; @@ -16,7 +17,7 @@ struct Args { no_run: bool, } -fn run(code: &str, args: &Args) { +fn run(code: &str, args: &Args, world: &mut World) { let src_file = args.file.as_ref().map(|f| f.to_string_lossy().to_string()); let tokens = match lex(code, src_file.as_deref()) { Ok(v) => v, @@ -44,19 +45,20 @@ fn run(code: &str, args: &Args) { } if !args.no_run { - println!("{:?}", exec(ast)); + println!("{:?}", world.exec(ast)); } } fn run_file(args: &Args) -> Result<(), io::Error> { let src = fs::read_to_string(args.file.as_ref().unwrap())?; - run(&src, args); + run(&src, args, &mut World::new()); Ok(()) } fn run_repl(args: &Args) { assert!(args.file.is_none()); + let mut world = World::new(); let mut line_buf = String::new(); loop { match io::stdin().read_line(&mut line_buf) { @@ -68,7 +70,7 @@ fn run_repl(args: &Args) { let line = line_buf.trim(); if !line.is_empty() { - run(&line_buf, args); + run(&line_buf, args, &mut world); line_buf.clear(); } } diff --git a/test.lox b/test.lox index 99adf23..0093aa0 100644 --- a/test.lox +++ b/test.lox @@ -1,6 +1,2 @@ -12 == 1; -print 1; -print 1.90 == 1.90; -print 1.90; -print 2; -nil; +asdf = 1; +print asdf;