restructuring things
This commit is contained in:
parent
0e50042bb0
commit
d1658bbec6
3 changed files with 132 additions and 116 deletions
|
|
@ -5,7 +5,7 @@ use crate::compiler::assembly_pass::Op::{
|
||||||
Dup, Equal, Get, Goto, GotoIf, GotoIfNot, Greater, GreaterEqual, Less, LessEqual, ListGet,
|
Dup, Equal, Get, Goto, GotoIf, GotoIfNot, Greater, GreaterEqual, Less, LessEqual, ListGet,
|
||||||
Multiply, Negate, Not, NotEqual, Or, Pop, Print, Return, Shr, Subtract,
|
Multiply, Negate, Not, NotEqual, Or, Pop, Print, Return, Shr, Subtract,
|
||||||
};
|
};
|
||||||
use crate::compiler::ast_pass::Expression::{IfExpression, NamedParameter};
|
use crate::compiler::ast_pass::Expression::{IfElseExpression, IfExpression, NamedParameter};
|
||||||
use crate::compiler::ast_pass::{Expression, Function, Parameter, Statement};
|
use crate::compiler::ast_pass::{Expression, Function, Parameter, Statement};
|
||||||
use crate::compiler::tokens::TokenType;
|
use crate::compiler::tokens::TokenType;
|
||||||
use crate::compiler::tokens::TokenType::Unknown;
|
use crate::compiler::tokens::TokenType::Unknown;
|
||||||
|
|
@ -186,38 +186,6 @@ impl AsmPass {
|
||||||
Statement::GuardStatement { .. } => {
|
Statement::GuardStatement { .. } => {
|
||||||
unimplemented!("guard statement")
|
unimplemented!("guard statement")
|
||||||
}
|
}
|
||||||
Statement::ForStatement {
|
|
||||||
loop_var,
|
|
||||||
range,
|
|
||||||
body,
|
|
||||||
} => {
|
|
||||||
// 1. step var index
|
|
||||||
let step_const_index = self.emit_constant(Value::I64(1));
|
|
||||||
// 2. range expression
|
|
||||||
self.compile_expression(namespace, range, symbols, registry)?;
|
|
||||||
//save the constants for lower and upper bounds of the range
|
|
||||||
let start_index = self.chunk.constants.len() - 1;
|
|
||||||
let end_index = self.chunk.constants.len() - 2;
|
|
||||||
|
|
||||||
let name = loop_var.lexeme.as_str();
|
|
||||||
let loop_var_name_index = self.chunk.add_var(&loop_var.token_type, name);
|
|
||||||
self.vars.insert(name.to_string(), loop_var_name_index);
|
|
||||||
|
|
||||||
// 3. start index
|
|
||||||
self.emit(Constant(start_index));
|
|
||||||
self.emit(Assign(loop_var_name_index));
|
|
||||||
|
|
||||||
let return_addr = self.chunk.code.len();
|
|
||||||
self.compile_statements(body, symbols, registry, namespace)?;
|
|
||||||
self.emit(Get(loop_var_name_index));
|
|
||||||
self.emit(Constant(step_const_index));
|
|
||||||
self.emit(Add);
|
|
||||||
self.emit(Assign(loop_var_name_index));
|
|
||||||
self.emit(Constant(end_index));
|
|
||||||
self.emit(Get(loop_var_name_index));
|
|
||||||
self.emit(GreaterEqual);
|
|
||||||
self.emit(GotoIf(return_addr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -233,6 +201,22 @@ impl AsmPass {
|
||||||
IfExpression {
|
IfExpression {
|
||||||
condition,
|
condition,
|
||||||
then_branch,
|
then_branch,
|
||||||
|
} => {
|
||||||
|
self.compile_expression(namespace, condition, symbols, registry)?;
|
||||||
|
|
||||||
|
self.emit(Dup);
|
||||||
|
self.emit(GotoIfNot(0)); // placeholder
|
||||||
|
let goto_addr1 = self.chunk.code.len() - 1;
|
||||||
|
self.emit(Pop);
|
||||||
|
self.compile_statements(then_branch, symbols, registry, namespace)?;
|
||||||
|
self.emit(Goto(0));
|
||||||
|
let goto_addr2 = self.chunk.code.len() - 1; // placeholder
|
||||||
|
self.chunk.code[goto_addr1] = GotoIfNot(self.chunk.code.len());
|
||||||
|
self.chunk.code[goto_addr2] = Op::Goto(self.chunk.code.len());
|
||||||
|
}
|
||||||
|
IfElseExpression {
|
||||||
|
condition,
|
||||||
|
then_branch,
|
||||||
else_branch,
|
else_branch,
|
||||||
} => {
|
} => {
|
||||||
self.compile_expression(namespace, condition, symbols, registry)?;
|
self.compile_expression(namespace, condition, symbols, registry)?;
|
||||||
|
|
@ -455,6 +439,38 @@ impl AsmPass {
|
||||||
self.compile_expression(namespace, upper, symbols, registry)?;
|
self.compile_expression(namespace, upper, symbols, registry)?;
|
||||||
self.compile_expression(namespace, lower, symbols, registry)?;
|
self.compile_expression(namespace, lower, symbols, registry)?;
|
||||||
}
|
}
|
||||||
|
Expression::ForStatement {
|
||||||
|
loop_var,
|
||||||
|
range,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
// 1. step var index
|
||||||
|
let step_const_index = self.emit_constant(Value::I64(1));
|
||||||
|
// 2. range expression
|
||||||
|
self.compile_expression(namespace, range, symbols, registry)?;
|
||||||
|
//save the constants for lower and upper bounds of the range
|
||||||
|
let start_index = self.chunk.constants.len() - 1;
|
||||||
|
let end_index = self.chunk.constants.len() - 2;
|
||||||
|
|
||||||
|
let name = loop_var.lexeme.as_str();
|
||||||
|
let loop_var_name_index = self.chunk.add_var(&loop_var.token_type, name);
|
||||||
|
self.vars.insert(name.to_string(), loop_var_name_index);
|
||||||
|
|
||||||
|
// 3. start index
|
||||||
|
self.emit(Constant(start_index));
|
||||||
|
self.emit(Assign(loop_var_name_index));
|
||||||
|
|
||||||
|
let return_addr = self.chunk.code.len();
|
||||||
|
self.compile_statements(body, symbols, registry, namespace)?;
|
||||||
|
self.emit(Get(loop_var_name_index));
|
||||||
|
self.emit(Constant(step_const_index));
|
||||||
|
self.emit(Add);
|
||||||
|
self.emit(Assign(loop_var_name_index));
|
||||||
|
self.emit(Constant(end_index));
|
||||||
|
self.emit(Get(loop_var_name_index));
|
||||||
|
self.emit(GreaterEqual);
|
||||||
|
self.emit(GotoIf(return_addr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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, LetExpression, ListGet, MapGet, MethodCall,
|
Assignment, FieldGet, FunctionCall, IfElseExpression, IfExpression, LetExpression, ListGet,
|
||||||
NamedParameter, Stop, Variable,
|
MapGet, MethodCall, 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,
|
||||||
|
|
@ -128,7 +128,7 @@ impl AstCompiler {
|
||||||
} else if self.match_token(&[TokenType::Pipe]) {
|
} else if self.match_token(&[TokenType::Pipe]) {
|
||||||
self.guard_declaration(symbol_table)
|
self.guard_declaration(symbol_table)
|
||||||
} else {
|
} else {
|
||||||
self.statement(symbol_table)
|
self.expr_statement(symbol_table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,15 +284,26 @@ impl AstCompiler {
|
||||||
Ok(Statement::FunctionStmt { function })
|
Ok(Statement::FunctionStmt { function })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
fn inc_indent(&mut self) {
|
||||||
if self.match_token(&[For]) {
|
self.indent.push(self.indent.last().unwrap() + 1);
|
||||||
self.for_statement(symbol_table)
|
|
||||||
} else {
|
|
||||||
self.expr_statement(symbol_table)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
fn expr_statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
||||||
|
let expr = if self.match_token(&[For]) {
|
||||||
|
self.for_expression(symbol_table)?
|
||||||
|
} else if self.match_token(&[Let]) {
|
||||||
|
let expr = self.let_exp(symbol_table)?;
|
||||||
|
if !self.is_at_end() {
|
||||||
|
self.consume(&Eol, Expected("end of line after expression."))?;
|
||||||
|
}
|
||||||
|
expr
|
||||||
|
} else {
|
||||||
|
self.expression(symbol_table)?
|
||||||
|
};
|
||||||
|
Ok(Statement::ExpressionStmt { expression: expr })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn for_expression(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||||
let loop_var = self.consume(&Identifier, Expected("loop variable name."))?;
|
let loop_var = self.consume(&Identifier, Expected("loop variable name."))?;
|
||||||
self.consume(&In, Expected("'in' after loop variable name."))?;
|
self.consume(&In, Expected("'in' after loop variable name."))?;
|
||||||
let range = self.expression(symbol_table)?;
|
let range = self.expression(symbol_table)?;
|
||||||
|
|
@ -301,65 +312,49 @@ impl AstCompiler {
|
||||||
self.inc_indent();
|
self.inc_indent();
|
||||||
let body = self.compile(symbol_table)?;
|
let body = self.compile(symbol_table)?;
|
||||||
|
|
||||||
Ok(Statement::ForStatement {
|
Ok(Expression::ForStatement {
|
||||||
loop_var,
|
loop_var,
|
||||||
range,
|
range: Box::new(range),
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inc_indent(&mut self) {
|
|
||||||
self.indent.push(self.indent.last().unwrap() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expr_statement(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
|
|
||||||
let expr = self.let_exp(symbol_table)?;
|
|
||||||
if !self.is_at_end() {
|
|
||||||
self.consume(&Eol, Expected("end of line after expression."))?;
|
|
||||||
}
|
|
||||||
Ok(Statement::ExpressionStmt { expression: expr })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn let_exp(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
fn let_exp(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||||
if self.match_token(&[Let]) {
|
if self.peek().token_type.is_type() {
|
||||||
if self.peek().token_type.is_type() {
|
return Err(self.raise(CompilerError::KeywordNotAllowedAsIdentifier(
|
||||||
return Err(self.raise(CompilerError::KeywordNotAllowedAsIdentifier(
|
self.peek().token_type.clone(),
|
||||||
self.peek().token_type.clone(),
|
)));
|
||||||
)));
|
}
|
||||||
}
|
let name_token = self.consume(&Identifier, Expected("variable name."))?;
|
||||||
let name_token = self.consume(&Identifier, Expected("variable name."))?;
|
|
||||||
|
|
||||||
let declared_type = if self.check(&Colon) {
|
let declared_type = if self.check(&Colon) {
|
||||||
self.advance();
|
self.advance();
|
||||||
Some(self.advance().token_type.clone())
|
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 {
|
} else {
|
||||||
self.expression(symbol_table)
|
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))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -499,20 +494,23 @@ impl AstCompiler {
|
||||||
self.inc_indent();
|
self.inc_indent();
|
||||||
let then_branch = self.compile(symbol_table)?;
|
let then_branch = self.compile(symbol_table)?;
|
||||||
|
|
||||||
let else_branch = if self.check(&Else) {
|
if self.check(&Else) {
|
||||||
self.consume(&Else, Expected("'else' after if condition."))?;
|
self.consume(&Else, Expected("'else' after if condition."))?;
|
||||||
self.consume(&Colon, Expected("':' after 'else'."))?;
|
self.consume(&Colon, Expected("':' after 'else'."))?;
|
||||||
|
|
||||||
self.inc_indent();
|
self.inc_indent();
|
||||||
Some(self.compile(symbol_table)?)
|
|
||||||
|
Ok(IfElseExpression {
|
||||||
|
condition: Box::new(condition),
|
||||||
|
then_branch,
|
||||||
|
else_branch: Some(self.compile(symbol_table)?),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(IfExpression {
|
||||||
};
|
condition: Box::new(condition),
|
||||||
Ok(IfExpression {
|
then_branch,
|
||||||
condition: Box::new(condition),
|
})
|
||||||
then_branch,
|
}
|
||||||
else_branch,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
self.get(symbol_table)
|
self.get(symbol_table)
|
||||||
}
|
}
|
||||||
|
|
@ -854,11 +852,6 @@ pub enum Statement {
|
||||||
if_expr: Expression,
|
if_expr: Expression,
|
||||||
then_expr: Expression,
|
then_expr: Expression,
|
||||||
},
|
},
|
||||||
ForStatement {
|
|
||||||
loop_var: Token,
|
|
||||||
range: Expression,
|
|
||||||
body: Vec<Statement>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
|
|
@ -868,7 +861,6 @@ impl Statement {
|
||||||
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(),
|
||||||
Statement::ForStatement { loop_var, .. } => loop_var.line,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -973,6 +965,10 @@ pub enum Expression {
|
||||||
IfExpression {
|
IfExpression {
|
||||||
condition: Box<Expression>,
|
condition: Box<Expression>,
|
||||||
then_branch: Vec<Statement>,
|
then_branch: Vec<Statement>,
|
||||||
|
},
|
||||||
|
IfElseExpression {
|
||||||
|
condition: Box<Expression>,
|
||||||
|
then_branch: Vec<Statement>,
|
||||||
else_branch: Option<Vec<Statement>>,
|
else_branch: Option<Vec<Statement>>,
|
||||||
},
|
},
|
||||||
LetExpression {
|
LetExpression {
|
||||||
|
|
@ -980,6 +976,11 @@ pub enum Expression {
|
||||||
var_type: TokenType,
|
var_type: TokenType,
|
||||||
initializer: Box<Expression>,
|
initializer: Box<Expression>,
|
||||||
},
|
},
|
||||||
|
ForStatement {
|
||||||
|
loop_var: Token,
|
||||||
|
range: Box<Expression>,
|
||||||
|
body: Vec<Statement>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
|
|
@ -1002,7 +1003,9 @@ impl Expression {
|
||||||
ListGet { .. } => 0,
|
ListGet { .. } => 0,
|
||||||
FieldGet { .. } => 0,
|
FieldGet { .. } => 0,
|
||||||
IfExpression { condition, .. } => condition.line(),
|
IfExpression { condition, .. } => condition.line(),
|
||||||
|
IfElseExpression { condition, .. } => condition.line(),
|
||||||
LetExpression { name, .. } => name.line,
|
LetExpression { name, .. } => name.line,
|
||||||
|
Expression::ForStatement { loop_var, .. } => loop_var.line,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@ 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, UndeclaredVariable};
|
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, LessEqual, ListType, MapType, Minus, ObjectType, Plus, SignedInteger, StringType, U32, U64, Unknown, UnsignedInteger, Void};
|
||||||
Bool, DateTime, F32, F64, FloatingPoint, Greater, GreaterEqual, I32, I64, Integer, Less,
|
|
||||||
LessEqual, ListType, MapType, Minus, ObjectType, Plus, SignedInteger, StringType, U32, U64,
|
|
||||||
Unknown, UnsignedInteger,
|
|
||||||
};
|
|
||||||
use crate::compiler::tokens::{Token, TokenType};
|
use crate::compiler::tokens::{Token, TokenType};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -218,13 +214,14 @@ pub fn infer_type(expr: &Expression, symbols: &HashMap<String, Symbol>) -> Token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Stop { .. } => Unknown,
|
Expression::Stop { .. } => Unknown,
|
||||||
// Expression::PathMatch { .. } => Unknown,
|
|
||||||
Expression::NamedParameter { .. } => Unknown,
|
Expression::NamedParameter { .. } => Unknown,
|
||||||
Expression::ListGet { .. } => Unknown,
|
Expression::ListGet { .. } => Unknown,
|
||||||
Expression::MapGet { .. } => Unknown,
|
Expression::MapGet { .. } => Unknown,
|
||||||
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),
|
Expression::IfElseExpression { .. } => Unknown,
|
||||||
|
Expression::LetExpression { .. } => Void,
|
||||||
|
Expression::ForStatement { .. } => Void,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue