lookup vars

This commit is contained in:
Shautvast 2025-10-26 14:37:21 +01:00
parent 96839158fa
commit d2d7bb2034
4 changed files with 81 additions and 43 deletions

View file

@ -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<Token>) -> anyhow::Result<Vec<Statement>> {
let mut compiler = AstCompiler::new(tokens);
@ -16,6 +17,7 @@ struct AstCompiler {
tokens: Vec<Token>,
current: usize,
had_error: bool,
vars: Vec<Expression>,
}
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<Statement> {
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(),
}
}
}

View file

@ -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<Statement>) -> anyhow::Result<Chunk> {
let compiler = Compiler::new();
@ -13,6 +20,7 @@ struct Compiler {
chunk: Chunk,
had_error: bool,
current_line: usize,
vars: HashMap<String, usize>,
}
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 {

View file

@ -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),

View file

@ -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) => {