let -> expr
This commit is contained in:
parent
8d61189a03
commit
0e50042bb0
4 changed files with 90 additions and 83 deletions
|
|
@ -169,28 +169,6 @@ impl AsmPass {
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
self.current_line = statement.line();
|
self.current_line = statement.line();
|
||||||
match statement {
|
match statement {
|
||||||
Statement::VarStmt {
|
|
||||||
name, initializer, ..
|
|
||||||
} => {
|
|
||||||
let name = name.lexeme.as_str();
|
|
||||||
let var = symbols.get(name);
|
|
||||||
if let Some(Symbol::Variable { var_type, .. }) = var {
|
|
||||||
let inferred_type = infer_type(initializer, symbols);
|
|
||||||
let calculated_type =
|
|
||||||
calculate_type(var_type, &inferred_type).map_err(|e| self.raise(e))?;
|
|
||||||
if var_type != &Unknown && var_type != &calculated_type {
|
|
||||||
return Err(
|
|
||||||
self.raise(IncompatibleTypes(var_type.clone(), calculated_type))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let name_index = self.chunk.add_var(var_type, name);
|
|
||||||
self.vars.insert(name.to_string(), name_index);
|
|
||||||
self.compile_expression(namespace, initializer, symbols, registry)?;
|
|
||||||
self.emit(Assign(name_index));
|
|
||||||
} else {
|
|
||||||
return Err(self.raise(UndeclaredVariable(name.to_string())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Statement::ExpressionStmt { expression } => {
|
Statement::ExpressionStmt { expression } => {
|
||||||
self.compile_expression(namespace, expression, symbols, registry)?;
|
self.compile_expression(namespace, expression, symbols, registry)?;
|
||||||
}
|
}
|
||||||
|
|
@ -277,6 +255,28 @@ impl AsmPass {
|
||||||
}
|
}
|
||||||
self.chunk.code[goto_addr2] = Op::Goto(self.chunk.code.len());
|
self.chunk.code[goto_addr2] = Op::Goto(self.chunk.code.len());
|
||||||
}
|
}
|
||||||
|
Expression::LetExpression {
|
||||||
|
name, initializer, ..
|
||||||
|
} => {
|
||||||
|
let name = name.lexeme.as_str();
|
||||||
|
let var = symbols.get(name);
|
||||||
|
if let Some(Symbol::Variable { var_type, .. }) = var {
|
||||||
|
let inferred_type = infer_type(initializer, symbols);
|
||||||
|
let calculated_type =
|
||||||
|
calculate_type(var_type, &inferred_type).map_err(|e| self.raise(e))?;
|
||||||
|
if var_type != &Unknown && var_type != &calculated_type {
|
||||||
|
return Err(
|
||||||
|
self.raise(IncompatibleTypes(var_type.clone(), calculated_type))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let name_index = self.chunk.add_var(var_type, name);
|
||||||
|
self.vars.insert(name.to_string(), name_index);
|
||||||
|
self.compile_expression(namespace, initializer, symbols, registry)?;
|
||||||
|
self.emit(Assign(name_index));
|
||||||
|
} else {
|
||||||
|
return Err(self.raise(UndeclaredVariable(name.to_string())));
|
||||||
|
}
|
||||||
|
}
|
||||||
Expression::FunctionCall {
|
Expression::FunctionCall {
|
||||||
name, arguments, ..
|
name, arguments, ..
|
||||||
} => {
|
} => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::builtins::globals::GLOBAL_FUNCTIONS;
|
use crate::builtins::globals::GLOBAL_FUNCTIONS;
|
||||||
use crate::compiler::ast_pass::Expression::{
|
use crate::compiler::ast_pass::Expression::{
|
||||||
Assignment, FieldGet, FunctionCall, IfExpression, ListGet, MapGet, MethodCall, NamedParameter,
|
Assignment, FieldGet, FunctionCall, IfExpression, LetExpression, ListGet, MapGet, MethodCall,
|
||||||
Stop, Variable,
|
NamedParameter, Stop, Variable,
|
||||||
};
|
};
|
||||||
use crate::compiler::tokens::TokenType::{
|
use crate::compiler::tokens::TokenType::{
|
||||||
Bang, Bool, Char, Colon, DateTime, Dot, Else, Eof, Eol, Equal, False, FloatingPoint, Fn, For,
|
Bang, Bool, Char, Colon, DateTime, Dot, Else, Eof, Eol, Equal, False, FloatingPoint, Fn, For,
|
||||||
|
|
@ -123,8 +123,6 @@ impl AstCompiler {
|
||||||
fn declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
fn declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
||||||
if self.match_token(&[Fn]) {
|
if self.match_token(&[Fn]) {
|
||||||
self.function_declaration(symbol_table)
|
self.function_declaration(symbol_table)
|
||||||
} else if self.match_token(&[Let]) {
|
|
||||||
self.let_declaration(symbol_table)
|
|
||||||
} else if self.match_token(&[Object]) {
|
} else if self.match_token(&[Object]) {
|
||||||
self.object_declaration(symbol_table)
|
self.object_declaration(symbol_table)
|
||||||
} else if self.match_token(&[TokenType::Pipe]) {
|
} else if self.match_token(&[TokenType::Pipe]) {
|
||||||
|
|
@ -286,47 +284,6 @@ impl AstCompiler {
|
||||||
Ok(Statement::FunctionStmt { function })
|
Ok(Statement::FunctionStmt { function })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn let_declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
|
||||||
if self.peek().token_type.is_type() {
|
|
||||||
return Err(self.raise(CompilerError::KeywordNotAllowedAsIdentifier(
|
|
||||||
self.peek().token_type.clone(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
let name_token = self.consume(&Identifier, Expected("variable name."))?;
|
|
||||||
|
|
||||||
let declared_type = if self.check(&Colon) {
|
|
||||||
self.advance();
|
|
||||||
Some(self.advance().token_type.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.match_token(&[Equal]) {
|
|
||||||
let initializer = self.expression(symbol_table)?;
|
|
||||||
let declared_type = declared_type.unwrap_or(Unknown);
|
|
||||||
let inferred_type = infer_type(&initializer, symbol_table);
|
|
||||||
let var_type =
|
|
||||||
calculate_type(&declared_type, &inferred_type).map_err(|e| self.raise(e))?;
|
|
||||||
symbol_table.insert(
|
|
||||||
name_token.lexeme.clone(),
|
|
||||||
Symbol::Variable {
|
|
||||||
name: name_token.lexeme.clone(),
|
|
||||||
var_type: var_type.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
self.consume(&Eol, Expected("end of line after initializer."))?;
|
|
||||||
|
|
||||||
Ok(Statement::VarStmt {
|
|
||||||
name: name_token,
|
|
||||||
var_type,
|
|
||||||
initializer,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(self.raise(UninitializedVariable))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
fn statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
||||||
if self.match_token(&[For]) {
|
if self.match_token(&[For]) {
|
||||||
self.for_statement(symbol_table)
|
self.for_statement(symbol_table)
|
||||||
|
|
@ -356,13 +313,56 @@ impl AstCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
fn expr_statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
||||||
let expr = self.expression(symbol_table)?;
|
let expr = self.let_exp(symbol_table)?;
|
||||||
if !self.is_at_end() {
|
if !self.is_at_end() {
|
||||||
self.consume(&Eol, Expected("end of line after expression."))?;
|
self.consume(&Eol, Expected("end of line after expression."))?;
|
||||||
}
|
}
|
||||||
Ok(Statement::ExpressionStmt { expression: expr })
|
Ok(Statement::ExpressionStmt { expression: expr })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn let_exp(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||||
|
if self.match_token(&[Let]) {
|
||||||
|
if self.peek().token_type.is_type() {
|
||||||
|
return Err(self.raise(CompilerError::KeywordNotAllowedAsIdentifier(
|
||||||
|
self.peek().token_type.clone(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
let name_token = self.consume(&Identifier, Expected("variable name."))?;
|
||||||
|
|
||||||
|
let declared_type = if self.check(&Colon) {
|
||||||
|
self.advance();
|
||||||
|
Some(self.advance().token_type.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.match_token(&[Equal]) {
|
||||||
|
let initializer = self.expression(symbol_table)?;
|
||||||
|
let declared_type = declared_type.unwrap_or(Unknown);
|
||||||
|
let inferred_type = infer_type(&initializer, symbol_table);
|
||||||
|
let var_type =
|
||||||
|
calculate_type(&declared_type, &inferred_type).map_err(|e| self.raise(e))?;
|
||||||
|
symbol_table.insert(
|
||||||
|
name_token.lexeme.clone(),
|
||||||
|
Symbol::Variable {
|
||||||
|
name: name_token.lexeme.clone(),
|
||||||
|
var_type: var_type.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(LetExpression {
|
||||||
|
name: name_token,
|
||||||
|
var_type,
|
||||||
|
initializer: Box::new(initializer),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(self.raise(UninitializedVariable))?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.expression(symbol_table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn expression(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
fn expression(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||||
self.or(symbol_table)
|
self.or(symbol_table)
|
||||||
}
|
}
|
||||||
|
|
@ -843,11 +843,6 @@ pub enum Statement {
|
||||||
ExpressionStmt {
|
ExpressionStmt {
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
},
|
},
|
||||||
VarStmt {
|
|
||||||
name: Token,
|
|
||||||
var_type: TokenType,
|
|
||||||
initializer: Expression,
|
|
||||||
},
|
|
||||||
FunctionStmt {
|
FunctionStmt {
|
||||||
function: Function,
|
function: Function,
|
||||||
},
|
},
|
||||||
|
|
@ -870,7 +865,6 @@ impl Statement {
|
||||||
pub fn line(&self) -> usize {
|
pub fn line(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Statement::ExpressionStmt { expression } => expression.line(),
|
Statement::ExpressionStmt { expression } => expression.line(),
|
||||||
Statement::VarStmt { name, .. } => name.line,
|
|
||||||
Statement::FunctionStmt { function, .. } => function.name.line,
|
Statement::FunctionStmt { function, .. } => function.name.line,
|
||||||
Statement::ObjectStmt { name, .. } => name.line,
|
Statement::ObjectStmt { name, .. } => name.line,
|
||||||
Statement::GuardStatement { if_expr, .. } => if_expr.line(),
|
Statement::GuardStatement { if_expr, .. } => if_expr.line(),
|
||||||
|
|
@ -981,6 +975,11 @@ pub enum Expression {
|
||||||
then_branch: Vec<Statement>,
|
then_branch: Vec<Statement>,
|
||||||
else_branch: Option<Vec<Statement>>,
|
else_branch: Option<Vec<Statement>>,
|
||||||
},
|
},
|
||||||
|
LetExpression {
|
||||||
|
name: Token,
|
||||||
|
var_type: TokenType,
|
||||||
|
initializer: Box<Expression>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
|
|
@ -1003,6 +1002,7 @@ impl Expression {
|
||||||
ListGet { .. } => 0,
|
ListGet { .. } => 0,
|
||||||
FieldGet { .. } => 0,
|
FieldGet { .. } => 0,
|
||||||
IfExpression { condition, .. } => condition.line(),
|
IfExpression { condition, .. } => condition.line(),
|
||||||
|
LetExpression { name, .. } => name.line,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -428,7 +428,7 @@ sum
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test_if_expression_else() {
|
||||||
run(r#"
|
run(r#"
|
||||||
let a:i64 = if true:
|
let a:i64 = if true:
|
||||||
42
|
42
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::compiler::ast_pass::{Expression, Parameter, Statement};
|
use crate::compiler::ast_pass::{Expression, Parameter, Statement};
|
||||||
use crate::builtins::lookup;
|
use crate::builtins::lookup;
|
||||||
use crate::errors::CompilerError;
|
use crate::errors::CompilerError;
|
||||||
use crate::errors::CompilerError::IncompatibleTypes;
|
use crate::errors::CompilerError::{IncompatibleTypes, UndeclaredVariable};
|
||||||
use crate::compiler::tokens::TokenType::{
|
use crate::compiler::tokens::TokenType::{
|
||||||
Bool, DateTime, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less,
|
Bool, DateTime, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less,
|
||||||
LessEqual, ListType, MapType, Minus, ObjectType, Plus, SignedInteger, StringType, U32, U64,
|
LessEqual, ListType, MapType, Minus, ObjectType, Plus, SignedInteger, StringType, U32, U64,
|
||||||
|
|
@ -11,6 +11,7 @@ use crate::compiler::tokens::{Token, TokenType};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use crate::compiler::assembly_pass::Op::Assign;
|
||||||
|
|
||||||
pub enum Symbol {
|
pub enum Symbol {
|
||||||
Function {
|
Function {
|
||||||
|
|
@ -40,13 +41,6 @@ fn make_qname(path: &str, name: &Token) -> String {
|
||||||
pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol>) {
|
pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol>) {
|
||||||
for statement in ast {
|
for statement in ast {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::VarStmt { name, var_type, .. } => {
|
|
||||||
let key = make_qname(path, name);
|
|
||||||
symbols.entry(key).or_insert_with(|| Symbol::Variable {
|
|
||||||
name: name.lexeme.to_string(),
|
|
||||||
var_type: var_type.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Statement::FunctionStmt { function } => {
|
Statement::FunctionStmt { function } => {
|
||||||
symbols.insert(
|
symbols.insert(
|
||||||
make_qname(path, &function.name),
|
make_qname(path, &function.name),
|
||||||
|
|
@ -67,6 +61,18 @@ pub fn build(path: &str, ast: &[Statement], symbols: &mut HashMap<String, Symbol
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Statement::ExpressionStmt { expression } => {
|
||||||
|
match expression{
|
||||||
|
Expression::LetExpression { name, var_type, initializer } => {
|
||||||
|
let key = make_qname(path, name);
|
||||||
|
symbols.entry(key).or_insert_with(|| Symbol::Variable {
|
||||||
|
name: name.lexeme.to_string(),
|
||||||
|
var_type: var_type.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ =>{}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,5 +225,6 @@ pub fn infer_type(expr: &Expression, symbols: &HashMap<String, Symbol>) -> Token
|
||||||
Expression::FieldGet { .. } => Unknown,
|
Expression::FieldGet { .. } => Unknown,
|
||||||
Expression::Range { lower, .. } => infer_type(lower, symbols),
|
Expression::Range { lower, .. } => infer_type(lower, symbols),
|
||||||
Expression::IfExpression { .. } => Unknown,
|
Expression::IfExpression { .. } => Unknown,
|
||||||
|
Expression::LetExpression { initializer,.. } => infer_type(initializer, symbols),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue