Modest implementation of lowering to IR and Instruction code.
This commit is contained in:
parent
f21128fd68
commit
9dfdcd716b
5
examples/hello_42.dm
Normal file
5
examples/hello_42.dm
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use std::core::println
|
||||||
|
|
||||||
|
fn main(args: Array<String>)
|
||||||
|
let hello = 42
|
||||||
|
end
|
||||||
33
src/bin/dmc/ir.rs
Normal file
33
src/bin/dmc/ir.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
use deimos::ast::node::CompilationUnit;
|
||||||
|
use deimos::ir::Ir;
|
||||||
|
use deimos::ir::lower_ast::lower_compilation_unit;
|
||||||
|
use deimos::ir::lower_ir::lower_ir_function;
|
||||||
|
use deimos::util::indent_writer::IndentWriter;
|
||||||
|
use crate::name_analysis::name_analysis;
|
||||||
|
|
||||||
|
pub fn compile_to_ir(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
||||||
|
let compilation_units = name_analysis(&paths)?;
|
||||||
|
|
||||||
|
for compilation_unit in &compilation_units {
|
||||||
|
let cu_irs = lower_compilation_unit(compilation_unit);
|
||||||
|
let mut out = String::new();
|
||||||
|
let mut indent_writer = IndentWriter::new(0, " ", &mut out);
|
||||||
|
for ir in &cu_irs {
|
||||||
|
ir.pretty_print(&mut indent_writer)?;
|
||||||
|
}
|
||||||
|
println!("{}", &out);
|
||||||
|
|
||||||
|
for ir in &cu_irs {
|
||||||
|
match ir {
|
||||||
|
Ir::Function(ir_function) => {
|
||||||
|
let instructions = lower_ir_function(ir_function);
|
||||||
|
println!("{:#?}", instructions);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(compilation_units)
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
mod ir;
|
||||||
mod name_analysis;
|
mod name_analysis;
|
||||||
mod p3;
|
mod p3;
|
||||||
// mod unparse;
|
// mod unparse;
|
||||||
@ -8,6 +9,7 @@ use crate::name_analysis::name_analysis;
|
|||||||
use crate::p3::pretty_print_parse;
|
use crate::p3::pretty_print_parse;
|
||||||
// use crate::unparse::unparse;
|
// use crate::unparse::unparse;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use crate::ir::compile_to_ir;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(name = "dmc")]
|
#[command(name = "dmc")]
|
||||||
@ -29,6 +31,9 @@ enum Commands {
|
|||||||
NameAnalysis {
|
NameAnalysis {
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
},
|
},
|
||||||
|
Ir {
|
||||||
|
paths: Vec<PathBuf>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -50,6 +55,12 @@ fn main() {
|
|||||||
eprintln!("{}", e)
|
eprintln!("{}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Commands::Ir { paths } => {
|
||||||
|
let result = compile_to_ir(&paths);
|
||||||
|
if let Err(e) = result {
|
||||||
|
eprintln!("{}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use pest::Parser;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use deimos::ast::node::CompilationUnit;
|
||||||
|
|
||||||
struct ParseErrors {
|
struct ParseErrors {
|
||||||
errors: Vec<pest::error::Error<Rule>>,
|
errors: Vec<pest::error::Error<Rule>>,
|
||||||
@ -33,7 +34,7 @@ impl Display for ParseErrors {
|
|||||||
|
|
||||||
impl std::error::Error for ParseErrors {}
|
impl std::error::Error for ParseErrors {}
|
||||||
|
|
||||||
pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn name_analysis(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
||||||
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
|
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let src = std::fs::read_to_string(path).unwrap();
|
let src = std::fs::read_to_string(path).unwrap();
|
||||||
@ -79,5 +80,5 @@ pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(compilation_units)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ fn main() {
|
|||||||
// return 0
|
// return 0
|
||||||
MoveImmediate {
|
MoveImmediate {
|
||||||
destination_register: 2,
|
destination_register: 2,
|
||||||
immediate: Immediate::Int(0),
|
immediate: Immediate::I32(0),
|
||||||
},
|
},
|
||||||
SetReturnValue { source_register: 2 },
|
SetReturnValue { source_register: 2 },
|
||||||
Return, // explicit, not needed
|
Return, // explicit, not needed
|
||||||
@ -106,7 +106,7 @@ fn main() {
|
|||||||
let foo_function_instructions = vec![
|
let foo_function_instructions = vec![
|
||||||
MoveImmediate {
|
MoveImmediate {
|
||||||
destination_register: 0,
|
destination_register: 0,
|
||||||
immediate: Immediate::Int(42),
|
immediate: Immediate::I32(42),
|
||||||
},
|
},
|
||||||
SetReturnValue { source_register: 0 },
|
SetReturnValue { source_register: 0 },
|
||||||
Return, // explicit, not needed
|
Return, // explicit, not needed
|
||||||
|
|||||||
315
src/ir/lower_ast.rs
Normal file
315
src/ir/lower_ast.rs
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
use crate::ast::node::{
|
||||||
|
CompilationUnit, Expression, Function, FunctionBlockBody, FunctionBody, Literal,
|
||||||
|
ModuleLevelDeclaration, Statement, VariableDeclaration,
|
||||||
|
};
|
||||||
|
use crate::ir::{
|
||||||
|
Ir, IrAssign, IrConst, IrExpression, IrFunction, IrKind, IrLiteral, IrPrimitiveKind,
|
||||||
|
IrStatement, IrVariable,
|
||||||
|
};
|
||||||
|
use crate::name_analysis::symbol::{ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
|
||||||
|
let mut result: Vec<Ir> = vec![];
|
||||||
|
for declaration in compilation_unit.module_level_declarations() {
|
||||||
|
result.append(&mut lower_module_level_declaration(declaration));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec<Ir> {
|
||||||
|
match declaration {
|
||||||
|
ModuleLevelDeclaration::Module(module) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ModuleLevelDeclaration::Interface(interface) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ModuleLevelDeclaration::Class(class) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ModuleLevelDeclaration::Function(function) => lower_function(function),
|
||||||
|
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LocalsTable {
|
||||||
|
t_count: usize,
|
||||||
|
stack_slot_count: usize,
|
||||||
|
stack_slots: HashMap<IrVariable, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalsTable {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
t_count: 0,
|
||||||
|
stack_slot_count: 0,
|
||||||
|
stack_slots: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_t_var(&mut self) -> IrVariable {
|
||||||
|
let t_num = self.t_count;
|
||||||
|
self.t_count += 1;
|
||||||
|
let t_name = format!("__t{}", t_num);
|
||||||
|
let t_var = IrVariable::new(&t_name);
|
||||||
|
self.register_stack_local(&t_var);
|
||||||
|
t_var
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_stack_local(&mut self, ir_variable: &IrVariable) {
|
||||||
|
let stack_slot = self.stack_slot_count;
|
||||||
|
self.stack_slot_count += 1;
|
||||||
|
self.stack_slots.insert(ir_variable.clone(), stack_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize {
|
||||||
|
*self.stack_slots.get(ir_variable).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_function(function: &Function) -> Vec<Ir> {
|
||||||
|
let function_symbol = function.function_symbol().unwrap().borrow();
|
||||||
|
let name = function_symbol.fqn_parts_owned().join("::");
|
||||||
|
let parameters = lower_parameter_symbols(function_symbol.parameter_symbols());
|
||||||
|
let return_type = lower_type_symbol(function_symbol.return_type().unwrap());
|
||||||
|
|
||||||
|
let mut locals_table = LocalsTable::new();
|
||||||
|
let (statements, consts) = lower_function_body(function.function_body(), &mut locals_table);
|
||||||
|
|
||||||
|
let mut result: Vec<Ir> = vec![];
|
||||||
|
result.push(Ir::Function(Box::new(IrFunction::new(
|
||||||
|
name,
|
||||||
|
parameters,
|
||||||
|
Box::new(return_type),
|
||||||
|
statements,
|
||||||
|
Box::new(locals_table),
|
||||||
|
))));
|
||||||
|
result.append(
|
||||||
|
&mut consts
|
||||||
|
.into_iter()
|
||||||
|
.map(|constant| Ir::Const(Box::new(constant)))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_parameter_symbols(parameter_symbols: &[Rc<RefCell<ParameterSymbol>>]) -> Vec<IrKind> {
|
||||||
|
parameter_symbols
|
||||||
|
.iter()
|
||||||
|
.map(|parameter_symbol_rc| parameter_symbol_rc.borrow())
|
||||||
|
.map(|parameter_symbol| lower_type_symbol(parameter_symbol.type_symbol().unwrap()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
|
||||||
|
match type_symbol {
|
||||||
|
TypeSymbol::Primitive(primitive_type_symbol) => {
|
||||||
|
lower_primitive_type_symbol(primitive_type_symbol)
|
||||||
|
}
|
||||||
|
TypeSymbol::Class(class_type_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
TypeSymbol::Interface(interface_type_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
TypeSymbol::Generic(generic_type_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
|
||||||
|
IrKind::Primitive(Box::new(match primitive_type_symbol {
|
||||||
|
PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8,
|
||||||
|
PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8,
|
||||||
|
PrimitiveTypeSymbol::Short => IrPrimitiveKind::I16,
|
||||||
|
PrimitiveTypeSymbol::Int => IrPrimitiveKind::I32,
|
||||||
|
PrimitiveTypeSymbol::Long => IrPrimitiveKind::I64,
|
||||||
|
PrimitiveTypeSymbol::Float => IrPrimitiveKind::Float,
|
||||||
|
PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double,
|
||||||
|
PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean,
|
||||||
|
PrimitiveTypeSymbol::String => IrPrimitiveKind::String,
|
||||||
|
PrimitiveTypeSymbol::TypedArray { inner_type } => {
|
||||||
|
IrPrimitiveKind::Array(Box::new(lower_type_symbol(inner_type.as_ref().unwrap())))
|
||||||
|
}
|
||||||
|
PrimitiveTypeSymbol::Any => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_function_body(
|
||||||
|
function_body: &FunctionBody,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
||||||
|
match function_body {
|
||||||
|
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionEqualsBody(equals_body) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
FunctionBody::FunctionBlockBody(block_body) => {
|
||||||
|
lower_function_block_body(block_body, locals_table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_function_block_body(
|
||||||
|
body: &FunctionBlockBody,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
||||||
|
let mut statements: Vec<IrStatement> = vec![];
|
||||||
|
let mut consts: Vec<IrConst> = vec![];
|
||||||
|
for statement in body.statements() {
|
||||||
|
statements.append(&mut lower_statement(statement, &mut consts, locals_table));
|
||||||
|
}
|
||||||
|
(statements, consts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_statement(
|
||||||
|
statement: &Statement,
|
||||||
|
consts_pool: &mut Vec<IrConst>,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> Vec<IrStatement> {
|
||||||
|
match statement {
|
||||||
|
Statement::VariableDeclaration(variable_declaration) => {
|
||||||
|
lower_variable_declaration(variable_declaration, consts_pool, locals_table)
|
||||||
|
}
|
||||||
|
Statement::AssignmentStatement(assignment_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Statement::ExpressionStatement(expression_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Statement::UseStatement(use_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Statement::IfStatement(if_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Statement::WhileStatement(while_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Statement::ForStatement(for_statement) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_variable_declaration(
|
||||||
|
variable_declaration: &VariableDeclaration,
|
||||||
|
consts_pool: &mut Vec<IrConst>,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> Vec<IrStatement> {
|
||||||
|
let mut result: Vec<IrStatement> = vec![];
|
||||||
|
let expression_t_var = lower_expression(
|
||||||
|
variable_declaration.expression().unwrap(),
|
||||||
|
&mut result,
|
||||||
|
consts_pool,
|
||||||
|
locals_table,
|
||||||
|
);
|
||||||
|
let target = IrVariable::new(variable_declaration.identifier().name());
|
||||||
|
locals_table.register_stack_local(&target);
|
||||||
|
let assign_stmt = IrAssign::new(
|
||||||
|
Box::new(target),
|
||||||
|
Box::new(IrExpression::Variable(Box::new(expression_t_var))),
|
||||||
|
);
|
||||||
|
result.push(IrStatement::Assign(assign_stmt));
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_expression(
|
||||||
|
expression: &Expression,
|
||||||
|
target: &mut Vec<IrStatement>,
|
||||||
|
consts_pool: &mut Vec<IrConst>,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> IrVariable {
|
||||||
|
match expression {
|
||||||
|
Expression::Ternary(ternary) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Or(or) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::And(and) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Comparison(comparison) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Shift(shift) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Additive(additive) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Multiplicative(multiplicative) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Prefix(prefix) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Suffix(suffix) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table),
|
||||||
|
Expression::Identifier(identifier) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Fqn(fqn) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::Closure(closure) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Expression::List(list) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_literal(
|
||||||
|
literal: &Literal,
|
||||||
|
statements: &mut Vec<IrStatement>,
|
||||||
|
consts_pool: &mut Vec<IrConst>,
|
||||||
|
locals_table: &mut LocalsTable
|
||||||
|
) -> IrVariable {
|
||||||
|
match literal {
|
||||||
|
Literal::IntLiteral(int_literal) => {
|
||||||
|
let t_var = locals_table.next_t_var();
|
||||||
|
let assign_stmt = IrAssign::new(
|
||||||
|
Box::new(t_var.clone()),
|
||||||
|
Box::new(IrExpression::Literal(Box::new(IrLiteral::I32(
|
||||||
|
*int_literal,
|
||||||
|
)))),
|
||||||
|
);
|
||||||
|
statements.push(IrStatement::Assign(assign_stmt));
|
||||||
|
t_var
|
||||||
|
}
|
||||||
|
Literal::LongLiteral(long_literal) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Literal::DoubleLiteral(double_literal) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Literal::SingleQuoteString(sq_string) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Literal::DString(d_string) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Literal::BacktickString(b_string) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
Literal::BooleanLiteral(boolean_literal) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
src/ir/lower_ir.rs
Normal file
131
src/ir/lower_ir.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use crate::ir::lower_ast::LocalsTable;
|
||||||
|
use crate::ir::{IrAllocable, IrAllocate, IrAssign, IrCall, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
|
||||||
|
use crate::vm::instruction::{Immediate, Instruction, Location};
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn lower_ir_function(ir_function: &IrFunction) -> Vec<Instruction> {
|
||||||
|
let mut instructions: Vec<Instruction> = vec![];
|
||||||
|
for statement in ir_function.statements() {
|
||||||
|
instructions.append(&mut lower_ir_statement(
|
||||||
|
statement,
|
||||||
|
ir_function.locals_table(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) -> Vec<Instruction> {
|
||||||
|
match ir_statement {
|
||||||
|
IrStatement::Allocate(allocate) => lower_ir_allocate(allocate),
|
||||||
|
IrStatement::Call(call) => lower_ir_call(call, locals_table),
|
||||||
|
IrStatement::Return(ir_return) => lower_return(ir_return, locals_table),
|
||||||
|
IrStatement::Assign(assign) => {
|
||||||
|
lower_ir_assign(assign, locals_table)
|
||||||
|
}
|
||||||
|
IrStatement::MakeClosure(make_closure) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_ir_allocate(ir_allocate: &IrAllocate) -> Vec<Instruction> {
|
||||||
|
let allocate_instruction = match ir_allocate.kind_to_alloc() {
|
||||||
|
IrAllocable::Struct(struct_kind) => Instruction::AllocateObject {
|
||||||
|
implementation_name: Rc::new(struct_kind.name().to_string()),
|
||||||
|
destination_register: 0,
|
||||||
|
},
|
||||||
|
IrAllocable::Array(array_kind) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let push_instruction = Instruction::Push { source_register: 0 };
|
||||||
|
vec![allocate_instruction, push_instruction]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_ir_call(ir_call: &IrCall, locals_table: &LocalsTable) -> Vec<Instruction> {
|
||||||
|
let mut instructions: Vec<Instruction> = vec![];
|
||||||
|
// push args
|
||||||
|
for argument in ir_call.arguments() {
|
||||||
|
lower_ir_expression(argument, &mut instructions, locals_table);
|
||||||
|
}
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_ir_expression(
|
||||||
|
ir_expression: &IrExpression,
|
||||||
|
instructions: &mut Vec<Instruction>,
|
||||||
|
locals_table: &LocalsTable,
|
||||||
|
) {
|
||||||
|
match ir_expression {
|
||||||
|
IrExpression::Variable(variable) => instructions.append(&mut vec![
|
||||||
|
Instruction::Copy {
|
||||||
|
source: Location::FramePointer {
|
||||||
|
offset: locals_table.get_stack_slot(variable) as isize,
|
||||||
|
},
|
||||||
|
destination: Location::Register(0),
|
||||||
|
},
|
||||||
|
Instruction::Push { source_register: 0 },
|
||||||
|
]),
|
||||||
|
IrExpression::ConstRef(const_ref) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
IrExpression::Literal(literal) => {
|
||||||
|
let immediate = match literal.deref() {
|
||||||
|
IrLiteral::I8(v) => Immediate::I8(*v),
|
||||||
|
IrLiteral::I16(v) => Immediate::I16(*v),
|
||||||
|
IrLiteral::I32(v) => Immediate::I32(*v),
|
||||||
|
IrLiteral::I64(v) => Immediate::I64(*v),
|
||||||
|
IrLiteral::I128(v) => Immediate::I128(*v),
|
||||||
|
IrLiteral::ISize(v) => Immediate::ISize(*v),
|
||||||
|
IrLiteral::U8(v) => Immediate::U8(*v),
|
||||||
|
IrLiteral::U16(v) => Immediate::U16(*v),
|
||||||
|
IrLiteral::U32(v) => Immediate::U32(*v),
|
||||||
|
IrLiteral::U64(v) => Immediate::U64(*v),
|
||||||
|
IrLiteral::U128(v) => Immediate::U128(*v),
|
||||||
|
IrLiteral::USize(v) => Immediate::USize(*v),
|
||||||
|
IrLiteral::Boolean(v) => Immediate::Boolean(*v),
|
||||||
|
IrLiteral::Float(v) => Immediate::Float(*v),
|
||||||
|
IrLiteral::Double(v) => Immediate::Double(*v),
|
||||||
|
};
|
||||||
|
instructions.append(&mut vec![
|
||||||
|
Instruction::MoveImmediate {
|
||||||
|
destination_register: 0,
|
||||||
|
immediate,
|
||||||
|
},
|
||||||
|
Instruction::Push { source_register: 0 },
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_return(ir_return: &IrReturn, locals_table: &LocalsTable) -> Vec<Instruction> {
|
||||||
|
let mut instructions: Vec<Instruction> = vec![];
|
||||||
|
lower_ir_expression(ir_return.expression(), &mut instructions, locals_table);
|
||||||
|
instructions.append(&mut vec![
|
||||||
|
Instruction::Pop {
|
||||||
|
destination_register: Some(0),
|
||||||
|
},
|
||||||
|
Instruction::PopFrame,
|
||||||
|
Instruction::Push { source_register: 0 },
|
||||||
|
Instruction::Return,
|
||||||
|
]);
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_ir_assign(ir_assign: &IrAssign, locals_table: &LocalsTable) -> Vec<Instruction> {
|
||||||
|
let mut instructions: Vec<Instruction> = vec![];
|
||||||
|
lower_ir_expression(ir_assign.rhs(), &mut instructions, locals_table);
|
||||||
|
instructions.append(&mut vec![
|
||||||
|
Instruction::Pop {
|
||||||
|
destination_register: Some(0),
|
||||||
|
},
|
||||||
|
Instruction::Copy {
|
||||||
|
source: Location::Register(0),
|
||||||
|
destination: Location::FramePointer {
|
||||||
|
offset: locals_table.get_stack_slot(ir_assign.lhs()) as isize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
instructions
|
||||||
|
}
|
||||||
579
src/ir/mod.rs
579
src/ir/mod.rs
@ -1,29 +1,88 @@
|
|||||||
pub enum DvmIr {
|
use crate::ir::lower_ast::LocalsTable;
|
||||||
Struct(Box<DvmIrStruct>),
|
use crate::util::indent_writer::IndentWriter;
|
||||||
Function(DvmIrFunction),
|
|
||||||
Const(DvmIrConst),
|
pub mod lower_ast;
|
||||||
|
pub mod lower_ir;
|
||||||
|
|
||||||
|
pub enum Ir {
|
||||||
|
Struct(Box<IrStruct>),
|
||||||
|
Function(Box<IrFunction>),
|
||||||
|
PlatformFunction(Box<IrPlatformFunction>),
|
||||||
|
Const(Box<IrConst>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStruct {
|
impl Ir {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Ir::Struct(ir_struct) => ir_struct.pretty_print(writer),
|
||||||
|
Ir::Function(ir_function) => ir_function.pretty_print(writer),
|
||||||
|
Ir::PlatformFunction(ir_platform_function) => ir_platform_function.pretty_print(writer),
|
||||||
|
Ir::Const(ir_const) => ir_const.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrStruct {
|
||||||
name: String,
|
name: String,
|
||||||
kind: Box<DvmIrKind>,
|
|
||||||
is_public: bool,
|
is_public: bool,
|
||||||
members: Vec<Box<DvmIrStructMember>>
|
members: Vec<IrStructMember>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStructMember {
|
impl IrStruct {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
if self.is_public {
|
||||||
|
writer.writeln(&format!("pub struct {} {{", self.name))?;
|
||||||
|
} else {
|
||||||
|
writer.writeln(&format!("struct {} {{", self.name))?;
|
||||||
|
}
|
||||||
|
writer.increase_indent();
|
||||||
|
for member in &self.members {
|
||||||
|
member.pretty_print(writer)?;
|
||||||
|
writer.write("\n")?;
|
||||||
|
}
|
||||||
|
writer.decrease_indent();
|
||||||
|
writer.writeln("}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrStructMember {
|
||||||
name: String,
|
name: String,
|
||||||
kind: Box<DvmIrKind>,
|
kind: Box<IrKind>,
|
||||||
is_public: bool,
|
is_public: bool,
|
||||||
is_mut: bool,
|
is_mut: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrKind {
|
impl IrStructMember {
|
||||||
Primitive(Box<DvmIrPrimitiveKind>),
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
Struct(Box<DvmIrStructKind>),
|
if self.is_public {
|
||||||
|
writer.write("pub ")?;
|
||||||
|
}
|
||||||
|
if self.is_mut {
|
||||||
|
writer.write("mut ")?;
|
||||||
|
}
|
||||||
|
writer.write(&self.name)?;
|
||||||
|
writer.write(": ")?;
|
||||||
|
self.kind.pretty_print(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrPrimitiveKind {
|
pub enum IrKind {
|
||||||
|
Primitive(Box<IrPrimitiveKind>),
|
||||||
|
Struct(Box<IrStructKind>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrKind {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrKind::Primitive(primitive) => primitive.pretty_print(writer),
|
||||||
|
IrKind::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum IrPrimitiveKind {
|
||||||
I8,
|
I8,
|
||||||
I16,
|
I16,
|
||||||
I32,
|
I32,
|
||||||
@ -36,97 +95,342 @@ pub enum DvmIrPrimitiveKind {
|
|||||||
U64,
|
U64,
|
||||||
U128,
|
U128,
|
||||||
USize,
|
USize,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
Boolean,
|
Boolean,
|
||||||
Array(Box<DvmIrKind>),
|
Array(Box<IrKind>),
|
||||||
String,
|
String,
|
||||||
Closure(Box<DvmIrClosureKind>),
|
Closure(Box<IrClosureKind>),
|
||||||
Ref(Box<DvmIrKind>),
|
Ref(Box<IrKind>),
|
||||||
Void,
|
Void,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStructKind {
|
impl IrPrimitiveKind {
|
||||||
|
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrPrimitiveKind::I8 => writer.write("i8"),
|
||||||
|
IrPrimitiveKind::I16 => writer.write("i16"),
|
||||||
|
IrPrimitiveKind::I32 => writer.write("i32"),
|
||||||
|
IrPrimitiveKind::I64 => writer.write("i64"),
|
||||||
|
IrPrimitiveKind::I128 => writer.write("i128"),
|
||||||
|
IrPrimitiveKind::ISize => writer.write("isize"),
|
||||||
|
IrPrimitiveKind::U8 => writer.write("u8"),
|
||||||
|
IrPrimitiveKind::U16 => writer.write("u16"),
|
||||||
|
IrPrimitiveKind::U32 => writer.write("u32"),
|
||||||
|
IrPrimitiveKind::U64 => writer.write("u64"),
|
||||||
|
IrPrimitiveKind::U128 => writer.write("u128"),
|
||||||
|
IrPrimitiveKind::USize => writer.write("usize"),
|
||||||
|
IrPrimitiveKind::Float => writer.write("f32"),
|
||||||
|
IrPrimitiveKind::Double => writer.write("f64"),
|
||||||
|
IrPrimitiveKind::Boolean => writer.write("boolean"),
|
||||||
|
IrPrimitiveKind::Array(kind) => {
|
||||||
|
writer.write("Array<")?;
|
||||||
|
kind.pretty_print(writer)?;
|
||||||
|
writer.write(">")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
IrPrimitiveKind::String => writer.write("String"),
|
||||||
|
IrPrimitiveKind::Closure(closure_kind) => writer.write("Closure"),
|
||||||
|
IrPrimitiveKind::Ref(ref_kind) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
IrPrimitiveKind::Void => writer.write("Void"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrStructKind {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrClosureKind {
|
impl IrStructKind {
|
||||||
captures_name: String,
|
pub fn new(name: &str) -> Self {
|
||||||
parameters: Vec<Box<DvmIrKind>>,
|
Self {
|
||||||
return_type: Box<DvmIrKind>,
|
name: name.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write(&self.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrFunction {
|
pub struct IrClosureKind {
|
||||||
|
captures_struct_name: String,
|
||||||
|
parameters: Vec<IrKind>,
|
||||||
|
return_type: Box<IrKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrFunction {
|
||||||
name: String,
|
name: String,
|
||||||
parameters: Vec<Box<DvmIrKind>>,
|
parameters: Vec<IrKind>,
|
||||||
return_type: Box<DvmIrKind>,
|
return_type: Box<IrKind>,
|
||||||
statements: Vec<Box<DvmIrStatement>>,
|
statements: Vec<IrStatement>,
|
||||||
|
locals_table: Box<LocalsTable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrStatement {
|
impl IrFunction {
|
||||||
Alloc(DvmIrAlloc),
|
pub fn new(
|
||||||
Call(DvmIrCallStmt),
|
name: String,
|
||||||
Ret(DvmIrRet),
|
parameters: Vec<IrKind>,
|
||||||
Assign(DvmIrAssign),
|
return_type: Box<IrKind>,
|
||||||
MakeClosure(DvmIrMakeClosure),
|
statements: Vec<IrStatement>,
|
||||||
Drop(DvmIrDrop),
|
locals_table: Box<LocalsTable>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
parameters,
|
||||||
|
return_type,
|
||||||
|
statements,
|
||||||
|
locals_table,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameters(&self) -> &[IrKind] {
|
||||||
|
&self.parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> &IrKind {
|
||||||
|
&self.return_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn statements(&self) -> &[IrStatement] {
|
||||||
|
&self.statements
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn locals_table(&self) -> &LocalsTable {
|
||||||
|
&self.locals_table
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write("fn ")?;
|
||||||
|
writer.write(&self.name)?;
|
||||||
|
writer.write("(")?;
|
||||||
|
for (i, parameter) in self.parameters.iter().enumerate() {
|
||||||
|
parameter.pretty_print(writer)?;
|
||||||
|
if i != self.parameters.len() - 1 {
|
||||||
|
writer.write(", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write(") -> ")?;
|
||||||
|
self.return_type.pretty_print(writer)?;
|
||||||
|
writer.write(" {\n")?;
|
||||||
|
writer.increase_indent();
|
||||||
|
for statement in &self.statements {
|
||||||
|
statement.pretty_print(writer)?;
|
||||||
|
}
|
||||||
|
writer.decrease_indent();
|
||||||
|
writer.writeln("}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrAllocable {
|
pub struct IrPlatformFunction {
|
||||||
Struct(Box<DvmIrStructKind>),
|
name: String,
|
||||||
Array(Box<DvmIrArrayKind>),
|
parameters: Vec<IrKind>,
|
||||||
|
return_type: Box<IrKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrArrayKind {
|
impl IrPlatformFunction {
|
||||||
StaticSize(Box<DvmIrStaticArrayKind>),
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
DynamicSize(Box<DvmIrDynamicArrayKind>)
|
writer.write("platform fn ")?;
|
||||||
|
writer.write(&self.name)?;
|
||||||
|
writer.write("(")?;
|
||||||
|
for (i, parameter) in self.parameters.iter().enumerate() {
|
||||||
|
parameter.pretty_print(writer)?;
|
||||||
|
if i != self.parameters.len() - 1 {
|
||||||
|
writer.write(", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write(") -> ")?;
|
||||||
|
self.return_type.pretty_print(writer)?;
|
||||||
|
writer.write("\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStaticArrayKind {
|
pub enum IrStatement {
|
||||||
inner_kind: Box<DvmIrKind>,
|
Allocate(IrAllocate),
|
||||||
|
Call(IrCall),
|
||||||
|
Return(IrReturn),
|
||||||
|
Assign(IrAssign),
|
||||||
|
MakeClosure(IrMakeClosure),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrStatement {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrStatement::Allocate(allocate) => allocate.pretty_print(writer),
|
||||||
|
IrStatement::Call(call) => call.pretty_print(writer),
|
||||||
|
IrStatement::Return(ir_return) => ir_return.pretty_print(writer),
|
||||||
|
IrStatement::Assign(assign) => assign.pretty_print(writer),
|
||||||
|
IrStatement::MakeClosure(make_closure) => make_closure.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum IrAllocable {
|
||||||
|
Struct(Box<IrStructKind>),
|
||||||
|
Array(Box<IrArrayKind>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrAllocable {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrAllocable::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
||||||
|
IrAllocable::Array(array_kind) => array_kind.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum IrArrayKind {
|
||||||
|
StaticSize(Box<IrStaticArrayKind>),
|
||||||
|
DynamicSize(Box<IrDynamicArrayKind>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrArrayKind {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrArrayKind::StaticSize(static_array_kind) => static_array_kind.pretty_print(writer),
|
||||||
|
IrArrayKind::DynamicSize(dynamic_array_kind) => dynamic_array_kind.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrStaticArrayKind {
|
||||||
|
inner_kind: Box<IrKind>,
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrDynamicArrayKind {
|
impl IrStaticArrayKind {
|
||||||
inner_kind: Box<DvmIrKind>,
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
size_expr: Box<DvmIrExpr>
|
writer.write("[")?;
|
||||||
|
self.inner_kind.pretty_print(writer)?;
|
||||||
|
writer.write(&format!("; {}]", self.size))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrAlloc {
|
pub struct IrDynamicArrayKind {
|
||||||
declared_kind: Box<DvmIrAllocable>,
|
inner_kind: Box<IrKind>,
|
||||||
|
size_expr: Box<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrDynamicArrayKind {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write("[")?;
|
||||||
|
self.inner_kind.pretty_print(writer)?;
|
||||||
|
writer.write("; ")?;
|
||||||
|
self.size_expr.pretty_print(writer)?;
|
||||||
|
writer.write("]")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrAllocate {
|
||||||
name: String,
|
name: String,
|
||||||
kind_to_alloc: Box<DvmIrAllocable>,
|
declared_kind: Box<IrAllocable>,
|
||||||
|
kind_to_alloc: Box<IrAllocable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrConst {
|
impl IrAllocate {
|
||||||
String(DvmIrStringConst),
|
pub fn name(&self) -> &str {
|
||||||
StringArray(DvmIrStringArrayConst),
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_kind(&self) -> &IrAllocable {
|
||||||
|
&self.declared_kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind_to_alloc(&self) -> &IrAllocable {
|
||||||
|
&self.kind_to_alloc
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write_indented(&format!("let {}: ", self.name))?;
|
||||||
|
self.declared_kind.pretty_print(writer)?;
|
||||||
|
writer.write(" = alloc")?;
|
||||||
|
self.kind_to_alloc.pretty_print(writer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStringConst {
|
pub enum IrConst {
|
||||||
|
String(IrStringConst),
|
||||||
|
StringArray(IrStringArrayConst),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrConst {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrStringConst {
|
||||||
name: String,
|
name: String,
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrStringArrayConst {
|
pub struct IrStringArrayConst {
|
||||||
name: String,
|
name: String,
|
||||||
value: Vec<String>,
|
value: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrExpr {
|
pub enum IrExpression {
|
||||||
Call(Box<DvmIrCallExpr>),
|
Variable(Box<IrVariable>),
|
||||||
Variable(Box<DvmIrVariable>),
|
ConstRef(Box<IrConstRef>),
|
||||||
ConstRef(Box<DvmIrConstRef>),
|
Literal(Box<IrLiteral>),
|
||||||
Literal(Box<DvmIrLiteral>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrVariable {
|
impl IrExpression {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IrExpression::Variable(variable) => variable.pretty_print(writer),
|
||||||
|
IrExpression::ConstRef(const_ref) => const_ref.pretty_print(writer),
|
||||||
|
IrExpression::Literal(literal) => literal.pretty_print(writer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||||
|
pub struct IrVariable {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrConstRef {
|
impl IrVariable {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write(&self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrConstRef {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrLiteral {
|
impl IrConstRef {
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write(&self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum IrLiteral {
|
||||||
I8(i8),
|
I8(i8),
|
||||||
I16(i16),
|
I16(i16),
|
||||||
I32(i32),
|
I32(i32),
|
||||||
@ -140,60 +444,145 @@ pub enum DvmIrLiteral {
|
|||||||
U128(u128),
|
U128(u128),
|
||||||
USize(usize),
|
USize(usize),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
Float(f32),
|
||||||
|
Double(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrCallStmt {
|
impl IrLiteral {
|
||||||
declared_type: Box<DvmIrKind>,
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
name: String,
|
match self {
|
||||||
call_expr: Box<DvmIrCallExpr>,
|
IrLiteral::I8(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::I16(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::I32(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::I64(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::I128(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::ISize(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::U8(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::U16(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::U32(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::U64(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::U128(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::USize(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::Boolean(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::Float(v) => writer.write(&format!("{}", v)),
|
||||||
|
IrLiteral::Double(v) => writer.write(&format!("{}", v)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrCallExpr {
|
pub struct IrCall {
|
||||||
name: String,
|
result_name: String,
|
||||||
arguments: Vec<Box<DvmIrExpr>>,
|
declared_type: Box<IrKind>,
|
||||||
|
function_name: String,
|
||||||
|
arguments: Vec<IrExpression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrAssign {
|
impl IrCall {
|
||||||
lhs: Box<DvmIrAssignLhs>,
|
pub fn new(
|
||||||
rhs: Box<DvmIrExpr>
|
result_name: &str,
|
||||||
|
declared_type: Box<IrKind>,
|
||||||
|
function_name: &str,
|
||||||
|
arguments: Vec<IrExpression>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
result_name: result_name.to_string(),
|
||||||
|
declared_type,
|
||||||
|
function_name: function_name.to_string(),
|
||||||
|
arguments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn result_name(&self) -> &str {
|
||||||
|
&self.result_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_type(&self) -> &IrKind {
|
||||||
|
&self.declared_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_name(&self) -> &str {
|
||||||
|
&self.function_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arguments(&self) -> &[IrExpression] {
|
||||||
|
&self.arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write_indented(&format!("let {}: ", self.result_name))?;
|
||||||
|
self.declared_type.pretty_print(writer)?;
|
||||||
|
writer.write(&format!(" = call {}(", self.function_name))?;
|
||||||
|
for (i, argument) in self.arguments.iter().enumerate() {
|
||||||
|
argument.pretty_print(writer)?;
|
||||||
|
if i != self.arguments.len() - 1 {
|
||||||
|
writer.write(", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write(")\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrAssignLhs {
|
pub struct IrAssign {
|
||||||
base: Box<DvmIrVariable>,
|
lhs: Box<IrVariable>,
|
||||||
suffixes: Vec<Box<DvmIrAssignLhsSuffix>>
|
rhs: Box<IrExpression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DvmIrAssignLhsSuffix {
|
impl IrAssign {
|
||||||
Index(DvmIrAssignLhsIndex),
|
pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
|
||||||
Property(DvmIrAssignLhsProperty)
|
Self { lhs, rhs }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lhs(&self) -> &IrVariable {
|
||||||
|
&self.lhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rhs(&self) -> &IrExpression {
|
||||||
|
&self.rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write_indented("")?;
|
||||||
|
self.lhs.pretty_print(writer)?;
|
||||||
|
writer.write(" = ")?;
|
||||||
|
self.rhs.pretty_print(writer)?;
|
||||||
|
writer.write("\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrAssignLhsIndex {
|
pub struct IrReturn {
|
||||||
expr: Box<DvmIrExpr>,
|
expression: Box<IrExpression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrAssignLhsProperty {
|
impl IrReturn {
|
||||||
name: String,
|
pub fn new(expression: Box<IrExpression>) -> Self {
|
||||||
|
Self { expression }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expression(&self) -> &Box<IrExpression> {
|
||||||
|
&self.expression
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
writer.write_indented("return ")?;
|
||||||
|
self.expression.pretty_print(writer)?;
|
||||||
|
writer.write("\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrRet {
|
pub struct IrMakeClosure {
|
||||||
value: Box<DvmIrReturnable>
|
captures_kind: Option<Box<IrStructKind>>,
|
||||||
}
|
parameters: Vec<IrKind>,
|
||||||
|
return_type: Box<IrKind>,
|
||||||
pub enum DvmIrReturnable {
|
|
||||||
Variable(DvmIrVariable),
|
|
||||||
Literal(DvmIrLiteral)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DvmIrMakeClosure {
|
|
||||||
captures_kind: Option<Box<DvmIrStructKind>>,
|
|
||||||
parameters: Vec<Box<DvmIrKind>>,
|
|
||||||
return_type: Box<DvmIrKind>,
|
|
||||||
name: String,
|
name: String,
|
||||||
fn_name: String,
|
fn_name: String,
|
||||||
captures_variable: Box<DvmIrVariable>,
|
captures_variable: Box<IrVariable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DvmIrDrop {
|
impl IrMakeClosure {
|
||||||
variable: Box<DvmIrVariable>,
|
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -79,6 +79,10 @@ impl FunctionSymbol {
|
|||||||
self.parameters = parameter_symbols;
|
self.parameters = parameter_symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> Option<&TypeSymbol> {
|
||||||
|
self.return_type.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
|
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
|
||||||
self.return_type = Some(type_symbol);
|
self.return_type = Some(type_symbol);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ pub enum Instruction {
|
|||||||
Pop {
|
Pop {
|
||||||
destination_register: Option<usize>,
|
destination_register: Option<usize>,
|
||||||
},
|
},
|
||||||
|
PopFrame,
|
||||||
AllocateObject {
|
AllocateObject {
|
||||||
implementation_name: Rc<String>,
|
implementation_name: Rc<String>,
|
||||||
destination_register: usize,
|
destination_register: usize,
|
||||||
@ -117,12 +118,21 @@ pub enum Instruction {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Immediate {
|
pub enum Immediate {
|
||||||
Byte(u8),
|
I8(i8),
|
||||||
Int(i32),
|
I16(i16),
|
||||||
Long(i64),
|
I32(i32),
|
||||||
Double(f64),
|
I64(i64),
|
||||||
Usize(usize),
|
I128(i128),
|
||||||
|
ISize(isize),
|
||||||
|
U8(u8),
|
||||||
|
U16(u16),
|
||||||
|
U32(u32),
|
||||||
|
U64(u64),
|
||||||
|
U128(u128),
|
||||||
|
USize(usize),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
Float(f32),
|
||||||
|
Double(f64),
|
||||||
Constant(DvmConstant),
|
Constant(DvmConstant),
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
@ -130,10 +140,10 @@ pub enum Immediate {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Location {
|
pub enum Location {
|
||||||
Register(usize),
|
Register(usize),
|
||||||
StackFrameBase {
|
FramePointer {
|
||||||
offset: isize,
|
offset: isize,
|
||||||
},
|
},
|
||||||
StackTop {
|
StackPointer {
|
||||||
offset: isize,
|
offset: isize,
|
||||||
},
|
},
|
||||||
Field {
|
Field {
|
||||||
|
|||||||
@ -224,7 +224,7 @@ fn compute_index_with_offset(
|
|||||||
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
||||||
match source {
|
match source {
|
||||||
Location::Register(register) => state.registers[*register].clone(),
|
Location::Register(register) => state.registers[*register].clone(),
|
||||||
Location::StackFrameBase { offset } => {
|
Location::FramePointer { offset } => {
|
||||||
let index = if offset.is_negative() {
|
let index = if offset.is_negative() {
|
||||||
state.frame_base_index - offset.unsigned_abs()
|
state.frame_base_index - offset.unsigned_abs()
|
||||||
} else {
|
} else {
|
||||||
@ -232,7 +232,7 @@ fn copy_from_source(state: &DvmState, source: &Location) -> DvmValue {
|
|||||||
};
|
};
|
||||||
state.stack[index].clone()
|
state.stack[index].clone()
|
||||||
}
|
}
|
||||||
Location::StackTop { offset } => {
|
Location::StackPointer { offset } => {
|
||||||
if *offset >= 0 {
|
if *offset >= 0 {
|
||||||
dvm_panic!(
|
dvm_panic!(
|
||||||
state,
|
state,
|
||||||
@ -272,7 +272,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
|
|||||||
Location::Register(register) => {
|
Location::Register(register) => {
|
||||||
state.registers[*register] = value;
|
state.registers[*register] = value;
|
||||||
}
|
}
|
||||||
Location::StackFrameBase { offset } => {
|
Location::FramePointer { offset } => {
|
||||||
let index = if offset.is_negative() {
|
let index = if offset.is_negative() {
|
||||||
state.frame_base_index - offset.unsigned_abs()
|
state.frame_base_index - offset.unsigned_abs()
|
||||||
} else {
|
} else {
|
||||||
@ -280,7 +280,7 @@ fn write_to_destination(state: &mut DvmState, destination: &Location, value: Dvm
|
|||||||
};
|
};
|
||||||
state.stack[index] = value;
|
state.stack[index] = value;
|
||||||
}
|
}
|
||||||
Location::StackTop { offset } => {
|
Location::StackPointer { offset } => {
|
||||||
if *offset >= 0 {
|
if *offset >= 0 {
|
||||||
dvm_panic!(
|
dvm_panic!(
|
||||||
state,
|
state,
|
||||||
@ -344,14 +344,7 @@ fn constant_to_value(constant: &DvmConstant) -> DvmValue {
|
|||||||
|
|
||||||
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
fn immediate_to_value(immediate: &Immediate) -> DvmValue {
|
||||||
match immediate {
|
match immediate {
|
||||||
Immediate::Byte(b) => DvmValue::Byte(*b),
|
_ => todo!()
|
||||||
Immediate::Int(i) => DvmValue::Int(*i),
|
|
||||||
Immediate::Long(l) => DvmValue::Long(*l),
|
|
||||||
Immediate::Double(d) => DvmValue::Double(*d),
|
|
||||||
Immediate::Usize(s) => DvmValue::USize(*s),
|
|
||||||
Immediate::Boolean(b) => DvmValue::Boolean(*b),
|
|
||||||
Immediate::Constant(c) => constant_to_value(c),
|
|
||||||
Immediate::Empty => DvmValue::Empty,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,6 +404,7 @@ pub fn run(instructions: &[Instruction], state: &mut DvmState, context: &DvmCont
|
|||||||
state.registers[*register_index] = value;
|
state.registers[*register_index] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PopFrame => {}
|
||||||
AllocateObject {
|
AllocateObject {
|
||||||
implementation_name,
|
implementation_name,
|
||||||
destination_register,
|
destination_register,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user