and more conciseness with a few aliases
This commit is contained in:
parent
daef6a59ed
commit
e079451f0a
3 changed files with 54 additions and 52 deletions
|
|
@ -16,10 +16,7 @@ use crate::tokens::{Token, TokenType};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use crate::{Expr, Stmt, SymbolTable};
|
||||||
type SymbolTable = HashMap<String, Symbol>;
|
|
||||||
type Expr = Result<Expression, CompilerErrorAtLine>;
|
|
||||||
type Stmt = Result<Statement, CompilerErrorAtLine>;
|
|
||||||
|
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
path: Option<&str>,
|
path: Option<&str>,
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,28 @@ use crate::symbol_builder::{Symbol, calculate_type, infer_type};
|
||||||
use crate::tokens::TokenType;
|
use crate::tokens::TokenType;
|
||||||
use crate::tokens::TokenType::Unknown;
|
use crate::tokens::TokenType::Unknown;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::{OP_ADD, OP_AND, OP_ASSIGN, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CALL_BUILTIN, OP_CONSTANT, OP_DEF_LIST, OP_DEF_MAP, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_LIST_GET, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT};
|
use crate::vm::{
|
||||||
|
OP_ADD, OP_AND, OP_ASSIGN, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CALL_BUILTIN,
|
||||||
|
OP_CONSTANT, OP_DEF_LIST, OP_DEF_MAP, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER,
|
||||||
|
OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_LIST_GET, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR,
|
||||||
|
OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||||
|
};
|
||||||
|
use crate::{Registry, SymbolTable};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
qualified_name: Option<&str>,
|
qualified_name: Option<&str>,
|
||||||
ast: &Vec<Statement>,
|
ast: &Vec<Statement>,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
compile_in_namespace(ast, qualified_name, symbols, registry)
|
compile_in_namespace(ast, qualified_name, symbols, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_function(
|
pub(crate) fn compile_function(
|
||||||
function: &Function,
|
function: &Function,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
) -> Result<Chunk, CompilerErrorAtLine> {
|
) -> Result<Chunk, CompilerErrorAtLine> {
|
||||||
let fn_name = &function.name.lexeme;
|
let fn_name = &function.name.lexeme;
|
||||||
|
|
@ -40,8 +46,8 @@ pub(crate) fn compile_function(
|
||||||
pub(crate) fn compile_in_namespace(
|
pub(crate) fn compile_in_namespace(
|
||||||
ast: &Vec<Statement>,
|
ast: &Vec<Statement>,
|
||||||
namespace: Option<&str>,
|
namespace: Option<&str>,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
let name = namespace.unwrap_or("main");
|
let name = namespace.unwrap_or("main");
|
||||||
let compiler = Compiler::new(name);
|
let compiler = Compiler::new(name);
|
||||||
|
|
@ -75,8 +81,8 @@ impl Compiler {
|
||||||
fn compile(
|
fn compile(
|
||||||
mut self,
|
mut self,
|
||||||
ast: &Vec<Statement>,
|
ast: &Vec<Statement>,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
) -> Result<Chunk, CompilerErrorAtLine> {
|
) -> Result<Chunk, CompilerErrorAtLine> {
|
||||||
for statement in ast {
|
for statement in ast {
|
||||||
|
|
@ -87,11 +93,15 @@ impl Compiler {
|
||||||
Ok(self.chunk)
|
Ok(self.chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn raise(&self, error: CompilerError) -> CompilerErrorAtLine {
|
||||||
|
CompilerErrorAtLine::raise(error, self.current_line)
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_statement(
|
fn compile_statement(
|
||||||
&mut self,
|
&mut self,
|
||||||
statement: &Statement,
|
statement: &Statement,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
self.current_line = statement.line();
|
self.current_line = statement.line();
|
||||||
|
|
@ -103,23 +113,20 @@ impl Compiler {
|
||||||
let var = symbols.get(name);
|
let var = symbols.get(name);
|
||||||
if let Some(Symbol::Variable { var_type, .. }) = var {
|
if let Some(Symbol::Variable { var_type, .. }) = var {
|
||||||
let inferred_type = infer_type(initializer, symbols);
|
let inferred_type = infer_type(initializer, symbols);
|
||||||
let calculated_type = calculate_type(var_type, &inferred_type)
|
let calculated_type =
|
||||||
.map_err(|e| CompilerErrorAtLine::raise(e, statement.line()))?;
|
calculate_type(var_type, &inferred_type).map_err(|e| self.raise(e))?;
|
||||||
if var_type != &Unknown && var_type != &calculated_type {
|
if var_type != &Unknown && var_type != &calculated_type {
|
||||||
return Err(CompilerErrorAtLine::raise(
|
return Err(self.raise(CompilerError::IncompatibleTypes(
|
||||||
CompilerError::IncompatibleTypes(var_type.clone(), calculated_type),
|
var_type.clone(),
|
||||||
statement.line(),
|
calculated_type,
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
let name_index = self.chunk.add_var(var_type, name);
|
let name_index = self.chunk.add_var(var_type, name);
|
||||||
self.vars.insert(name.to_string(), name_index);
|
self.vars.insert(name.to_string(), name_index);
|
||||||
self.compile_expression(namespace, initializer, symbols, registry)?;
|
self.compile_expression(namespace, initializer, symbols, registry)?;
|
||||||
self.emit_bytes(OP_ASSIGN, name_index as u16);
|
self.emit_bytes(OP_ASSIGN, name_index as u16);
|
||||||
} else {
|
} else {
|
||||||
return Err(CompilerErrorAtLine::raise(
|
return Err(self.raise(CompilerError::UndeclaredVariable(name.to_string())));
|
||||||
CompilerError::UndeclaredVariable(name.to_string()),
|
|
||||||
statement.line(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::PrintStmt { value } => {
|
Statement::PrintStmt { value } => {
|
||||||
|
|
@ -151,8 +158,8 @@ impl Compiler {
|
||||||
&mut self,
|
&mut self,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
expression: &Expression,
|
expression: &Expression,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
match expression {
|
match expression {
|
||||||
Expression::FunctionCall {
|
Expression::FunctionCall {
|
||||||
|
|
@ -181,10 +188,7 @@ impl Compiler {
|
||||||
self.emit_byte(arguments.len() as u16);
|
self.emit_byte(arguments.len() as u16);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompilerErrorAtLine::raise(
|
return Err(self.raise(CompilerError::FunctionNotFound(name.to_string())));
|
||||||
CompilerError::FunctionNotFound(name.to_string()),
|
|
||||||
0,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,10 +206,10 @@ impl Compiler {
|
||||||
.find_constant(&receiver_type)
|
.find_constant(&receiver_type)
|
||||||
.unwrap_or_else(|| self.chunk.add_constant(Value::String(receiver_type)));
|
.unwrap_or_else(|| self.chunk.add_constant(Value::String(receiver_type)));
|
||||||
|
|
||||||
let name_index = self
|
let name_index = self.chunk.find_constant(&method_name).unwrap_or_else(|| {
|
||||||
.chunk
|
self.chunk
|
||||||
.find_constant(&method_name)
|
.add_constant(Value::String(method_name.to_string()))
|
||||||
.unwrap_or_else(|| self.chunk.add_constant(Value::String(method_name.to_string())));
|
});
|
||||||
//TODO lookup parameters for builtin
|
//TODO lookup parameters for builtin
|
||||||
self.get_arguments_in_order(namespace, symbols, registry, arguments, &vec![])?;
|
self.get_arguments_in_order(namespace, symbols, registry, arguments, &vec![])?;
|
||||||
self.emit_byte(OP_CALL_BUILTIN);
|
self.emit_byte(OP_CALL_BUILTIN);
|
||||||
|
|
@ -218,10 +222,7 @@ impl Compiler {
|
||||||
if let Some(name_index) = name_index {
|
if let Some(name_index) = name_index {
|
||||||
self.emit_bytes(OP_GET, *name_index as u16);
|
self.emit_bytes(OP_GET, *name_index as u16);
|
||||||
} else {
|
} else {
|
||||||
return Err(CompilerErrorAtLine::raise(
|
return Err(self.raise(CompilerError::UndeclaredVariable(name.to_string())));
|
||||||
CompilerError::UndeclaredVariable(name.to_string()),
|
|
||||||
*line,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Literal { value, .. } => {
|
Expression::Literal { value, .. } => {
|
||||||
|
|
@ -305,8 +306,8 @@ impl Compiler {
|
||||||
fn get_arguments_in_order(
|
fn get_arguments_in_order(
|
||||||
&mut self,
|
&mut self,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
symbols: &HashMap<String, Symbol>,
|
symbols: &SymbolTable,
|
||||||
registry: &mut HashMap<String, Chunk>,
|
registry: &mut Registry,
|
||||||
arguments: &Vec<Expression>,
|
arguments: &Vec<Expression>,
|
||||||
parameters: &Vec<Parameter>,
|
parameters: &Vec<Parameter>,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
|
|
@ -316,13 +317,10 @@ impl Compiler {
|
||||||
if name.lexeme == parameter.name.lexeme {
|
if name.lexeme == parameter.name.lexeme {
|
||||||
let value_type = infer_type(value, symbols);
|
let value_type = infer_type(value, symbols);
|
||||||
if parameter.var_type != value_type {
|
if parameter.var_type != value_type {
|
||||||
return Err(CompilerErrorAtLine::raise(
|
return Err(self.raise(CompilerError::IncompatibleTypes(
|
||||||
CompilerError::IncompatibleTypes(
|
|
||||||
parameter.var_type.clone(),
|
parameter.var_type.clone(),
|
||||||
value_type,
|
value_type,
|
||||||
),
|
)));
|
||||||
argument.line(),
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
self.compile_expression(namespace, argument, symbols, registry)?;
|
self.compile_expression(namespace, argument, symbols, registry)?;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
11
src/lib.rs
11
src/lib.rs
|
|
@ -1,7 +1,9 @@
|
||||||
|
use crate::ast_compiler::{Expression, Statement};
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::errors::CrudLangError;
|
|
||||||
use crate::errors::CrudLangError::Platform;
|
use crate::errors::CrudLangError::Platform;
|
||||||
|
use crate::errors::{CompilerErrorAtLine, CrudLangError};
|
||||||
use crate::scanner::scan;
|
use crate::scanner::scan;
|
||||||
|
use crate::symbol_builder::Symbol;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::interpret;
|
use crate::vm::interpret;
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
|
|
@ -11,6 +13,7 @@ use std::sync::Arc;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub mod ast_compiler;
|
pub mod ast_compiler;
|
||||||
|
mod builtins;
|
||||||
pub mod bytecode_compiler;
|
pub mod bytecode_compiler;
|
||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
mod compiler_tests;
|
mod compiler_tests;
|
||||||
|
|
@ -23,7 +26,11 @@ mod symbol_builder;
|
||||||
mod tokens;
|
mod tokens;
|
||||||
mod value;
|
mod value;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
mod builtins;
|
|
||||||
|
pub(crate) type SymbolTable = HashMap<String, Symbol>;
|
||||||
|
pub(crate) type Expr = Result<Expression, CompilerErrorAtLine>;
|
||||||
|
pub(crate) type Stmt = Result<Statement, CompilerErrorAtLine>;
|
||||||
|
pub(crate) type Registry = HashMap<String, Chunk>;
|
||||||
|
|
||||||
pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, Chunk>, CrudLangError> {
|
pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, Chunk>, CrudLangError> {
|
||||||
let mut registry = HashMap::new();
|
let mut registry = HashMap::new();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue