From d2d7bb2034cbebefe674dd27ac9c2b2504b88e22 Mon Sep 17 00:00:00 2001 From: Shautvast Date: Sun, 26 Oct 2025 14:37:21 +0100 Subject: [PATCH] lookup vars --- src/ast_compiler.rs | 94 +++++++++++++++++++++++++--------------- src/bytecode_compiler.rs | 20 +++++++-- src/chunk.rs | 3 +- src/main.rs | 7 +-- 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/src/ast_compiler.rs b/src/ast_compiler.rs index 35eb85d..75e62ae 100644 --- a/src/ast_compiler.rs +++ b/src/ast_compiler.rs @@ -1,11 +1,12 @@ -use log::debug; +use crate::ast_compiler::Expression::Variable; use crate::tokens::TokenType::{ Bang, Bool, Char, Colon, Date, Eol, Equal, F32, F64, False, FloatingPoint, Greater, GreaterEqual, I32, I64, Identifier, Integer, LeftParen, Less, LessEqual, Let, ListType, - MapType, Minus, Object, Plus, Print, RightParen, Slash, Star, String, Text, True, U32, U64, + MapType, Minus, Object, Plus, Print, RightParen, Slash, Star, Text, True, U32, U64, }; use crate::tokens::{Token, TokenType}; use crate::value::Value; +use log::debug; pub fn compile(tokens: Vec) -> anyhow::Result> { let mut compiler = AstCompiler::new(tokens); @@ -16,6 +17,7 @@ struct AstCompiler { tokens: Vec, current: usize, had_error: bool, + vars: Vec, } impl AstCompiler { @@ -24,6 +26,7 @@ impl AstCompiler { tokens, current: 0, had_error: false, + vars: vec![], } } @@ -44,7 +47,7 @@ impl AstCompiler { } fn let_declaration(&mut self) -> anyhow::Result { - let name = self.consume(Identifier, "Expect variable name.")?; + let name_token = self.consume(Identifier, "Expect variable name.")?; let declared_type = if self.check(Colon) { self.advance(); @@ -61,13 +64,18 @@ impl AstCompiler { let var_type = match calculate_type(declared_type, inferred_type) { Ok(var_type) => var_type, Err(e) => { - println!("error at line {}", name.line); + println!("error at line {}", name_token.line); self.had_error = true; return Err(e); } }; + self.vars.push(Variable { + name: name_token.lexeme.to_string(), + var_type, + line: name_token.line, + }); Ok(Statement::VarStmt { - name, + name: name_token, var_type, initializer, }) @@ -213,7 +221,24 @@ impl AstCompiler { expression: Box::new(expr), } } else { - unimplemented!() + let token = self.advance().clone(); + let (var_name, var_type) = self + .vars + .iter() + .filter_map(|e| { + if let Variable { name, var_type, .. } = e { + Some((name, var_type)) + } else { + None + } + }) + .find(|e| e.0 == &token.lexeme) + .ok_or_else(|| return anyhow::anyhow!("Unknown variable: {}", token.lexeme))?; + Variable { + name: var_name.to_string(), + var_type: var_type.clone(), + line: token.line, + } }) } @@ -290,7 +315,17 @@ fn calculate_type( declared_type } } else { - inferred_type + match inferred_type{ + Integer => I64, + FloatingPoint => F64, + Text => Text, + Bool => Bool, + Date => Date, + ListType => ListType, + MapType => MapType, + Object => Object, + _ => panic!("Unexpected type"), + } }) } @@ -345,30 +380,24 @@ pub enum Expression { literaltype: TokenType, value: Value, }, + Variable { + line: usize, + name: String, + var_type: TokenType, + }, } impl Expression { pub fn line(&self) -> usize { match self { - Expression::Binary { - line, - left, - operator, - right, - } => *line, - Expression::Unary { - line, - operator, - right, - } => *line, - Expression::Grouping { line, expression } => *line, - Expression::Literal { - line, - literaltype, - value, - } => *line, + Self::Binary { line, .. } => *line, + Self::Unary { line, .. } => *line, + Self::Grouping { line, expression } => *line, + Self::Literal { line, .. } => *line, + Self::Variable { line, .. } => *line, } } + pub fn infer_type(&self) -> TokenType { match self { Self::Binary { @@ -390,7 +419,7 @@ impl Expression { if let Plus = operator.token_type { // includes string concatenation with numbers // followed by type coercion to 64 bits for numeric types - debug!("coerce {} : {}",left_type,right_type); + debug!("coerce {} : {}", left_type, right_type); match (left_type, right_type) { (_, Text) => Text, (Text, _) => Text, @@ -409,7 +438,7 @@ impl Expression { // so if my thinking is wrong or incomplete it will panic } else { // type coercion to 64 bits for numeric types - debug!("coerce {} : {}",left_type,right_type); + debug!("coerce {} : {}", left_type, right_type); match (left_type, right_type) { (FloatingPoint, _) => F64, (Integer, FloatingPoint) => F64, @@ -424,16 +453,9 @@ impl Expression { } } Self::Grouping { line, expression } => expression.infer_type(), - Self::Literal { - line, - literaltype, - value, - } => literaltype.clone(), - Self::Unary { - line, - operator, - right, - } => right.infer_type(), + Self::Literal { literaltype, .. } => literaltype.clone(), + Self::Unary { right, .. } => right.infer_type(), + Self::Variable { var_type, .. } => var_type.clone(), } } } diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index 4548183..9d6f07d 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -1,8 +1,15 @@ +use std::collections::HashMap; use crate::ast_compiler::{Expression, Statement}; use crate::chunk::Chunk; use crate::tokens::TokenType; use crate::value::Value; -use crate::vm::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR, OP_DEF_DATE, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT, OP_DEF_F32, OP_GET, OP_PRINT}; +use crate::vm::{ + OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR, OP_DEF_DATE, + OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, + OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, + OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, + OP_SUBTRACT, +}; pub fn compile(ast: Vec) -> anyhow::Result { let compiler = Compiler::new(); @@ -13,6 +20,7 @@ struct Compiler { chunk: Chunk, had_error: bool, current_line: usize, + vars: HashMap, } impl Compiler { @@ -21,6 +29,7 @@ impl Compiler { chunk: Chunk::new("main"), had_error: false, current_line: 0, + vars: HashMap::new(), } } @@ -41,11 +50,12 @@ impl Compiler { var_type, initializer, } => { - let name_index= self.chunk.add_constant(Value::String(name.lexeme.clone())); + let name_index = self.chunk.add_constant(Value::String(name.lexeme.clone())); + self.vars.insert(name.lexeme.clone(),name_index); self.compile_expression(initializer)?; self.define_variable(var_type, name_index)? } - Statement::Print {value} => { + Statement::Print { value } => { self.compile_expression(value)?; self.emit_byte(OP_PRINT); } @@ -56,6 +66,10 @@ impl Compiler { fn compile_expression(&mut self, expression: &Expression) -> anyhow::Result<()> { match expression { + Expression::Variable {name, ..} => { + let name_index = self.vars.get(name).unwrap(); + self.emit_bytes(OP_GET, *name_index as u16); + } Expression::Literal { value, .. } => self.emit_constant(value), Expression::Grouping { expression, .. } => self.compile_expression(expression)?, Expression::Unary { diff --git a/src/chunk.rs b/src/chunk.rs index 3aeda47..9100a3c 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -4,7 +4,7 @@ use crate::vm::{ OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_MULTIPLY, OP_NEGATE, OP_RETURN, OP_SUBTRACT, OP_NOT, OP_SHL, OP_SHR, OP_LESS, OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, OP_EQUAL, OP_PRINT, OP_POP, OP_DEFINE, OP_GET,OP_DEF_STRING, - OP_DEF_I32, OP_DEF_BOOL, OP_DEF_F32, OP_DEF_F64, + OP_DEF_I32, OP_DEF_I64, OP_DEF_F32, OP_DEF_F64, OP_DEF_BOOL }; pub struct Chunk { @@ -75,6 +75,7 @@ impl Chunk { OP_DEFINE => self.constant_inst("DEF", offset), OP_DEF_STRING => self.constant_inst("DEFSTR", offset), OP_DEF_I32 => self.constant_inst("DEFI32", offset), + OP_DEF_I64 => self.constant_inst("DEFI64", offset), OP_DEF_F32 => self.constant_inst("DEFF32", offset), OP_DEF_F64 => self.constant_inst("DEFF64", offset), OP_DEF_BOOL => self.constant_inst("DEFBOOL", offset), diff --git a/src/main.rs b/src/main.rs index 5f59d6e..b6d4f8f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,12 +6,13 @@ use crudlang::vm::{interpret, Vm}; fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); - let tokens = scan(r#"let a = ((1+2)*3.0)*4"#); + let tokens = scan(r#"let a = 42 +print a"#); match ast_compiler::compile(tokens) { Ok(statements) => { - // println!("{:?}", statements); + println!("{:?}", statements); let chunk = compile(statements)?; - // chunk.disassemble(); + chunk.disassemble(); interpret(chunk); } Err(e) => {