lookup vars
This commit is contained in:
parent
96839158fa
commit
d2d7bb2034
4 changed files with 81 additions and 43 deletions
|
|
@ -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 {
|
||||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +51,7 @@ impl Compiler {
|
|||
initializer,
|
||||
} => {
|
||||
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)?
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue