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::{
|
use crate::tokens::TokenType::{
|
||||||
Bang, Bool, Char, Colon, Date, Eol, Equal, F32, F64, False, FloatingPoint, Greater,
|
Bang, Bool, Char, Colon, Date, Eol, Equal, F32, F64, False, FloatingPoint, Greater,
|
||||||
GreaterEqual, I32, I64, Identifier, Integer, LeftParen, Less, LessEqual, Let, ListType,
|
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::tokens::{Token, TokenType};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
pub fn compile(tokens: Vec<Token>) -> anyhow::Result<Vec<Statement>> {
|
pub fn compile(tokens: Vec<Token>) -> anyhow::Result<Vec<Statement>> {
|
||||||
let mut compiler = AstCompiler::new(tokens);
|
let mut compiler = AstCompiler::new(tokens);
|
||||||
|
|
@ -16,6 +17,7 @@ struct AstCompiler {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
current: usize,
|
current: usize,
|
||||||
had_error: bool,
|
had_error: bool,
|
||||||
|
vars: Vec<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstCompiler {
|
impl AstCompiler {
|
||||||
|
|
@ -24,6 +26,7 @@ impl AstCompiler {
|
||||||
tokens,
|
tokens,
|
||||||
current: 0,
|
current: 0,
|
||||||
had_error: false,
|
had_error: false,
|
||||||
|
vars: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +47,7 @@ impl AstCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn let_declaration(&mut self) -> anyhow::Result<Statement> {
|
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) {
|
let declared_type = if self.check(Colon) {
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
@ -61,13 +64,18 @@ impl AstCompiler {
|
||||||
let var_type = match calculate_type(declared_type, inferred_type) {
|
let var_type = match calculate_type(declared_type, inferred_type) {
|
||||||
Ok(var_type) => var_type,
|
Ok(var_type) => var_type,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("error at line {}", name.line);
|
println!("error at line {}", name_token.line);
|
||||||
self.had_error = true;
|
self.had_error = true;
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
self.vars.push(Variable {
|
||||||
|
name: name_token.lexeme.to_string(),
|
||||||
|
var_type,
|
||||||
|
line: name_token.line,
|
||||||
|
});
|
||||||
Ok(Statement::VarStmt {
|
Ok(Statement::VarStmt {
|
||||||
name,
|
name: name_token,
|
||||||
var_type,
|
var_type,
|
||||||
initializer,
|
initializer,
|
||||||
})
|
})
|
||||||
|
|
@ -213,7 +221,24 @@ impl AstCompiler {
|
||||||
expression: Box::new(expr),
|
expression: Box::new(expr),
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
declared_type
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
literaltype: TokenType,
|
||||||
value: Value,
|
value: Value,
|
||||||
},
|
},
|
||||||
|
Variable {
|
||||||
|
line: usize,
|
||||||
|
name: String,
|
||||||
|
var_type: TokenType,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn line(&self) -> usize {
|
pub fn line(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary {
|
Self::Binary { line, .. } => *line,
|
||||||
line,
|
Self::Unary { line, .. } => *line,
|
||||||
left,
|
Self::Grouping { line, expression } => *line,
|
||||||
operator,
|
Self::Literal { line, .. } => *line,
|
||||||
right,
|
Self::Variable { line, .. } => *line,
|
||||||
} => *line,
|
|
||||||
Expression::Unary {
|
|
||||||
line,
|
|
||||||
operator,
|
|
||||||
right,
|
|
||||||
} => *line,
|
|
||||||
Expression::Grouping { line, expression } => *line,
|
|
||||||
Expression::Literal {
|
|
||||||
line,
|
|
||||||
literaltype,
|
|
||||||
value,
|
|
||||||
} => *line,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infer_type(&self) -> TokenType {
|
pub fn infer_type(&self) -> TokenType {
|
||||||
match self {
|
match self {
|
||||||
Self::Binary {
|
Self::Binary {
|
||||||
|
|
@ -424,16 +453,9 @@ impl Expression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Grouping { line, expression } => expression.infer_type(),
|
Self::Grouping { line, expression } => expression.infer_type(),
|
||||||
Self::Literal {
|
Self::Literal { literaltype, .. } => literaltype.clone(),
|
||||||
line,
|
Self::Unary { right, .. } => right.infer_type(),
|
||||||
literaltype,
|
Self::Variable { var_type, .. } => var_type.clone(),
|
||||||
value,
|
|
||||||
} => literaltype.clone(),
|
|
||||||
Self::Unary {
|
|
||||||
line,
|
|
||||||
operator,
|
|
||||||
right,
|
|
||||||
} => right.infer_type(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
use crate::ast_compiler::{Expression, Statement};
|
use crate::ast_compiler::{Expression, Statement};
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::tokens::TokenType;
|
use crate::tokens::TokenType;
|
||||||
use crate::value::Value;
|
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> {
|
pub fn compile(ast: Vec<Statement>) -> anyhow::Result<Chunk> {
|
||||||
let compiler = Compiler::new();
|
let compiler = Compiler::new();
|
||||||
|
|
@ -13,6 +20,7 @@ struct Compiler {
|
||||||
chunk: Chunk,
|
chunk: Chunk,
|
||||||
had_error: bool,
|
had_error: bool,
|
||||||
current_line: usize,
|
current_line: usize,
|
||||||
|
vars: HashMap<String, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
|
|
@ -21,6 +29,7 @@ impl Compiler {
|
||||||
chunk: Chunk::new("main"),
|
chunk: Chunk::new("main"),
|
||||||
had_error: false,
|
had_error: false,
|
||||||
current_line: 0,
|
current_line: 0,
|
||||||
|
vars: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,6 +51,7 @@ impl Compiler {
|
||||||
initializer,
|
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.compile_expression(initializer)?;
|
||||||
self.define_variable(var_type, name_index)?
|
self.define_variable(var_type, name_index)?
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +66,10 @@ impl Compiler {
|
||||||
|
|
||||||
fn compile_expression(&mut self, expression: &Expression) -> anyhow::Result<()> {
|
fn compile_expression(&mut self, expression: &Expression) -> anyhow::Result<()> {
|
||||||
match expression {
|
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::Literal { value, .. } => self.emit_constant(value),
|
||||||
Expression::Grouping { expression, .. } => self.compile_expression(expression)?,
|
Expression::Grouping { expression, .. } => self.compile_expression(expression)?,
|
||||||
Expression::Unary {
|
Expression::Unary {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::vm::{
|
||||||
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_MULTIPLY,
|
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_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_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 {
|
pub struct Chunk {
|
||||||
|
|
@ -75,6 +75,7 @@ impl Chunk {
|
||||||
OP_DEFINE => self.constant_inst("DEF", offset),
|
OP_DEFINE => self.constant_inst("DEF", offset),
|
||||||
OP_DEF_STRING => self.constant_inst("DEFSTR", offset),
|
OP_DEF_STRING => self.constant_inst("DEFSTR", offset),
|
||||||
OP_DEF_I32 => self.constant_inst("DEFI32", 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_F32 => self.constant_inst("DEFF32", offset),
|
||||||
OP_DEF_F64 => self.constant_inst("DEFF64", offset),
|
OP_DEF_F64 => self.constant_inst("DEFF64", offset),
|
||||||
OP_DEF_BOOL => self.constant_inst("DEFBOOL", offset),
|
OP_DEF_BOOL => self.constant_inst("DEFBOOL", offset),
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,13 @@ use crudlang::vm::{interpret, Vm};
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
tracing_subscriber::fmt::init();
|
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) {
|
match ast_compiler::compile(tokens) {
|
||||||
Ok(statements) => {
|
Ok(statements) => {
|
||||||
// println!("{:?}", statements);
|
println!("{:?}", statements);
|
||||||
let chunk = compile(statements)?;
|
let chunk = compile(statements)?;
|
||||||
// chunk.disassemble();
|
chunk.disassemble();
|
||||||
interpret(chunk);
|
interpret(chunk);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue