Introduce asm representation (between ir and vm instructions).
This commit is contained in:
parent
9dfdcd716b
commit
026bc68fa7
@ -2,4 +2,7 @@ use std::core::println
|
||||
|
||||
fn main(args: Array<String>)
|
||||
let hello = 42
|
||||
let world = hello + 16
|
||||
println(hello)
|
||||
println(world)
|
||||
end
|
||||
260
src/asm/assemble_ir.rs
Normal file
260
src/asm/assemble_ir.rs
Normal file
@ -0,0 +1,260 @@
|
||||
use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId};
|
||||
use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
struct AssemblyContext {
|
||||
control_unit_counter: ControlUnitId,
|
||||
control_units: Vec<ControlUnit>,
|
||||
virtual_register_counter: VirtualRegisterId,
|
||||
virtual_registers: HashMap<Rc<str>, VirtualRegisterId>,
|
||||
}
|
||||
|
||||
impl AssemblyContext {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
control_unit_counter: 0,
|
||||
control_units: Vec::new(),
|
||||
virtual_register_counter: 0,
|
||||
virtual_registers: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn next_control_unit_id(&mut self) -> ControlUnitId {
|
||||
let id = self.control_unit_counter;
|
||||
self.control_unit_counter += 1;
|
||||
id
|
||||
}
|
||||
|
||||
pub fn new_control_unit(&mut self) -> ControlUnitId {
|
||||
let new_id = self.next_control_unit_id();
|
||||
self.control_units.push(ControlUnit::new(new_id));
|
||||
new_id
|
||||
}
|
||||
|
||||
pub fn current_control_unit(&mut self) -> &ControlUnit {
|
||||
if self.control_units.is_empty() {
|
||||
self.new_control_unit();
|
||||
}
|
||||
self.control_units.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn current_control_unit_mut(&mut self) -> &mut ControlUnit {
|
||||
if self.control_units.is_empty() {
|
||||
self.new_control_unit();
|
||||
}
|
||||
self.control_units.last_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn into_control_units(self) -> Vec<ControlUnit> {
|
||||
self.control_units
|
||||
}
|
||||
|
||||
pub fn get_virtual_register(&self, name: &str) -> VirtualRegisterId {
|
||||
*self
|
||||
.virtual_registers
|
||||
.get(name)
|
||||
.expect(&format!("Did not set a virtual register for name {}", name))
|
||||
}
|
||||
|
||||
pub fn next_virtual_register(&mut self, name: &str) -> VirtualRegisterId {
|
||||
if self.virtual_registers.contains_key(name) {
|
||||
panic!(
|
||||
"Should not already have a virtual register with name {}",
|
||||
name
|
||||
);
|
||||
}
|
||||
let virtual_register_id = self.virtual_register_counter;
|
||||
self.virtual_register_counter += 1;
|
||||
self.virtual_registers
|
||||
.insert(name.into(), virtual_register_id);
|
||||
virtual_register_id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction {
|
||||
let mut context = AssemblyContext::new();
|
||||
|
||||
// body
|
||||
for statement in ir_function.statements() {
|
||||
assemble_ir_statement(statement, &mut context);
|
||||
}
|
||||
|
||||
AsmFunction::new(ir_function.name().into(), context.into_control_units())
|
||||
}
|
||||
|
||||
fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) {
|
||||
match ir_statement {
|
||||
IrStatement::Allocate(_) => {
|
||||
todo!()
|
||||
}
|
||||
IrStatement::Call(ir_call) => {
|
||||
assemble_ir_call(ir_call, context);
|
||||
}
|
||||
IrStatement::Return(ir_return) => {
|
||||
assemble_ir_return(ir_return, context);
|
||||
}
|
||||
IrStatement::Assign(ir_assign) => {
|
||||
assemble_ir_assign(ir_assign, context);
|
||||
}
|
||||
IrStatement::MakeClosure(_) => {
|
||||
todo!()
|
||||
}
|
||||
IrStatement::BinaryOperation(ir_binary_operation) => {
|
||||
assemble_ir_binary_operation(ir_binary_operation, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) {
|
||||
let source_operand = match ir_assign.rhs() {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
let virtual_register_id = context.get_virtual_register(ir_variable.name());
|
||||
AsmOperand::VirtualRegister(virtual_register_id)
|
||||
}
|
||||
IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
|
||||
name: ir_const_ref.name_owned(),
|
||||
},
|
||||
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
|
||||
};
|
||||
let destination = context.next_virtual_register(ir_assign.lhs().name());
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::Move {
|
||||
source: source_operand,
|
||||
destination,
|
||||
})
|
||||
}
|
||||
|
||||
fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand {
|
||||
match ir_literal {
|
||||
IrLiteral::I8(i) => AsmOperand::I8(*i),
|
||||
IrLiteral::I16(i) => AsmOperand::I16(*i),
|
||||
IrLiteral::I32(i) => AsmOperand::I32(*i),
|
||||
IrLiteral::I64(i) => AsmOperand::I64(*i),
|
||||
IrLiteral::I128(i) => AsmOperand::I128(*i),
|
||||
IrLiteral::ISize(i) => AsmOperand::ISize(*i),
|
||||
IrLiteral::U8(u) => AsmOperand::U8(*u),
|
||||
IrLiteral::U16(u) => AsmOperand::U16(*u),
|
||||
IrLiteral::U32(u) => AsmOperand::U32(*u),
|
||||
IrLiteral::U64(u) => AsmOperand::U64(*u),
|
||||
IrLiteral::U128(u) => AsmOperand::U128(*u),
|
||||
IrLiteral::USize(u) => AsmOperand::USize(*u),
|
||||
IrLiteral::Boolean(b) => AsmOperand::Boolean(*b),
|
||||
IrLiteral::Float(f) => AsmOperand::Float(*f),
|
||||
IrLiteral::Double(d) => AsmOperand::Double(*d),
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
|
||||
// push args
|
||||
for argument in ir_call.arguments() {
|
||||
match argument {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
let variable_register_id = context.get_virtual_register(ir_variable.name());
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::Push {
|
||||
source: AsmOperand::VirtualRegister(variable_register_id),
|
||||
})
|
||||
}
|
||||
IrExpression::ConstRef(ir_const_ref) => context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::Push {
|
||||
source: AsmOperand::Constant {
|
||||
name: ir_const_ref.name_owned(),
|
||||
},
|
||||
}),
|
||||
IrExpression::Literal(ir_literal) => context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::Push {
|
||||
source: ir_literal_to_asm_operand(ir_literal),
|
||||
}),
|
||||
}
|
||||
}
|
||||
// issue call
|
||||
match ir_call.call_type() {
|
||||
IrCallType::Static => {
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::InvokeStatic {
|
||||
fqn: ir_call.function_name_owned(),
|
||||
});
|
||||
}
|
||||
IrCallType::Object => {
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::InvokeObject {
|
||||
fqn: ir_call.function_name_owned(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_ir_return(ir_return: &IrReturn, context: &mut AssemblyContext) {
|
||||
let operand = match ir_return.expression() {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
let variable_virtual_register_id = context.get_virtual_register(ir_variable.name());
|
||||
AsmOperand::VirtualRegister(variable_virtual_register_id)
|
||||
}
|
||||
IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
|
||||
name: ir_const_ref.name_owned(),
|
||||
},
|
||||
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
|
||||
};
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(AsmInstruction::Return { operand });
|
||||
}
|
||||
|
||||
fn assemble_ir_binary_operation(ir_binary_operation: &IrBinaryOperation, context: &mut AssemblyContext) {
|
||||
let left = match ir_binary_operation.left() {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
|
||||
}
|
||||
IrExpression::ConstRef(ir_const_ref) => {
|
||||
unreachable!("Cannot assemble binary operation with a lhs IrConstRef")
|
||||
}
|
||||
IrExpression::Literal(ir_literal) => {
|
||||
ir_literal_to_asm_operand(ir_literal)
|
||||
}
|
||||
};
|
||||
let right = match ir_binary_operation.right() {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
|
||||
},
|
||||
IrExpression::ConstRef(ir_const_ref) => {
|
||||
unreachable!("Cannot assemble binary operation with a rhs IrConstRef")
|
||||
}
|
||||
IrExpression::Literal(ir_literal) => {
|
||||
ir_literal_to_asm_operand(ir_literal)
|
||||
}
|
||||
};
|
||||
let destination = context.next_virtual_register(ir_binary_operation.destination().name());
|
||||
let operator = match ir_binary_operation.operator() {
|
||||
IrBinaryOperator::Add => {
|
||||
AsmBinaryOperator::Add
|
||||
}
|
||||
IrBinaryOperator::Subtract => {
|
||||
AsmBinaryOperator::Subtract
|
||||
}
|
||||
IrBinaryOperator::Multiply => {
|
||||
AsmBinaryOperator::Multiply
|
||||
}
|
||||
IrBinaryOperator::Divide => {
|
||||
AsmBinaryOperator::Divide
|
||||
}
|
||||
IrBinaryOperator::Exponent => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
|
||||
let instruction = AsmInstruction::BinaryOperation {
|
||||
destination,
|
||||
left,
|
||||
right,
|
||||
operator
|
||||
};
|
||||
context.current_control_unit_mut().append_instruction(instruction);
|
||||
}
|
||||
240
src/asm/mod.rs
Normal file
240
src/asm/mod.rs
Normal file
@ -0,0 +1,240 @@
|
||||
pub mod assemble_ir;
|
||||
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type ControlUnitId = usize;
|
||||
|
||||
pub type VirtualRegisterId = u32;
|
||||
|
||||
pub struct AsmFunction {
|
||||
fqn: Rc<str>,
|
||||
control_units: Vec<ControlUnit>,
|
||||
}
|
||||
|
||||
impl AsmFunction {
|
||||
pub fn new(fqn: Rc<str>, control_units: Vec<ControlUnit>) -> Self {
|
||||
Self { fqn, control_units }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AsmFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "fn {}", self.fqn)?;
|
||||
for control_unit in &self.control_units {
|
||||
writeln!(f, " #{}:", control_unit.id)?;
|
||||
for instruction in &control_unit.instructions {
|
||||
writeln!(f, " {}", instruction)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ControlUnit {
|
||||
id: ControlUnitId,
|
||||
successor_ids: Vec<ControlUnitId>,
|
||||
instructions: Vec<AsmInstruction>,
|
||||
}
|
||||
|
||||
impl ControlUnit {
|
||||
pub fn new(id: ControlUnitId) -> Self {
|
||||
Self {
|
||||
id,
|
||||
successor_ids: vec![],
|
||||
instructions: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append_instruction(&mut self, instruction: AsmInstruction) {
|
||||
self.instructions.push(instruction);
|
||||
}
|
||||
|
||||
pub fn append_instructions(&mut self, instructions: Vec<AsmInstruction>) {
|
||||
self.instructions.extend(instructions);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AsmInstruction {
|
||||
Goto {
|
||||
control_unit_id: ControlUnitId,
|
||||
},
|
||||
Move {
|
||||
source: AsmOperand,
|
||||
destination: VirtualRegisterId,
|
||||
},
|
||||
Push {
|
||||
source: AsmOperand,
|
||||
},
|
||||
Pop {
|
||||
destination: VirtualRegisterId,
|
||||
},
|
||||
Allocate {
|
||||
class_name: Rc<str>,
|
||||
destination: VirtualRegisterId,
|
||||
},
|
||||
InvokeStatic {
|
||||
fqn: Rc<str>,
|
||||
},
|
||||
InvokeObject {
|
||||
fqn: Rc<str>,
|
||||
},
|
||||
Return {
|
||||
operand: AsmOperand,
|
||||
},
|
||||
BinaryOperation {
|
||||
destination: VirtualRegisterId,
|
||||
left: AsmOperand,
|
||||
right: AsmOperand,
|
||||
operator: AsmBinaryOperator,
|
||||
},
|
||||
}
|
||||
|
||||
impl Display for AsmInstruction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AsmInstruction::Goto { control_unit_id } => {
|
||||
write!(f, "goto #{}", control_unit_id)
|
||||
}
|
||||
AsmInstruction::Move {
|
||||
source,
|
||||
destination,
|
||||
} => {
|
||||
write!(f, "move vr{}, {}", destination, source)
|
||||
}
|
||||
AsmInstruction::Push { source } => {
|
||||
write!(f, "push {}", source)
|
||||
}
|
||||
AsmInstruction::Pop { destination } => {
|
||||
write!(f, "pop vr{}", destination)
|
||||
}
|
||||
AsmInstruction::Allocate {
|
||||
class_name,
|
||||
destination,
|
||||
} => {
|
||||
write!(f, "allocate r{}, {}", destination, class_name)
|
||||
}
|
||||
AsmInstruction::InvokeStatic { fqn } => {
|
||||
write!(f, "invoke_static {}", fqn)
|
||||
}
|
||||
AsmInstruction::InvokeObject { fqn } => {
|
||||
write!(f, "invoke_object {}", fqn)
|
||||
}
|
||||
AsmInstruction::Return { operand } => {
|
||||
write!(f, "return {}", operand)
|
||||
}
|
||||
AsmInstruction::BinaryOperation {
|
||||
destination,
|
||||
left,
|
||||
right,
|
||||
operator,
|
||||
} => {
|
||||
write!(f, "op{} vr{}, {}, {}", operator, destination, left, right)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AsmOperand {
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I128(i128),
|
||||
ISize(isize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
U128(u128),
|
||||
USize(usize),
|
||||
Float(f32),
|
||||
Double(f64),
|
||||
Boolean(bool),
|
||||
Constant { name: Rc<str> },
|
||||
VirtualRegister(VirtualRegisterId),
|
||||
}
|
||||
|
||||
impl Display for AsmOperand {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AsmOperand::I8(i) => {
|
||||
write!(f, "{}i8", i)
|
||||
}
|
||||
AsmOperand::I16(i) => {
|
||||
write!(f, "{}i16", i)
|
||||
}
|
||||
AsmOperand::I32(i) => {
|
||||
write!(f, "{}i32", i)
|
||||
}
|
||||
AsmOperand::I64(i) => {
|
||||
write!(f, "{}i64", i)
|
||||
}
|
||||
AsmOperand::I128(i) => {
|
||||
write!(f, "{}i128", i)
|
||||
}
|
||||
AsmOperand::ISize(i) => {
|
||||
write!(f, "{}isize", i)
|
||||
}
|
||||
AsmOperand::U8(u) => {
|
||||
write!(f, "{}u8", u)
|
||||
}
|
||||
AsmOperand::U16(u) => {
|
||||
write!(f, "{}u16", u)
|
||||
}
|
||||
AsmOperand::U32(u) => {
|
||||
write!(f, "{}u32", u)
|
||||
}
|
||||
AsmOperand::U64(u) => {
|
||||
write!(f, "{}u64", u)
|
||||
}
|
||||
AsmOperand::U128(u) => {
|
||||
write!(f, "{}u128", u)
|
||||
}
|
||||
AsmOperand::USize(u) => {
|
||||
write!(f, "{}usize", u)
|
||||
}
|
||||
AsmOperand::Float(float) => {
|
||||
write!(f, "{}f32", float)
|
||||
}
|
||||
AsmOperand::Double(d) => {
|
||||
write!(f, "{}f64", d)
|
||||
}
|
||||
AsmOperand::Boolean(b) => {
|
||||
write!(f, "{}", b)
|
||||
}
|
||||
AsmOperand::Constant { name } => {
|
||||
write!(f, "<{}>", name)
|
||||
}
|
||||
AsmOperand::VirtualRegister(id) => {
|
||||
write!(f, "vr{}", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AsmBinaryOperator {
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
}
|
||||
|
||||
impl Display for AsmBinaryOperator {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AsmBinaryOperator::Add => {
|
||||
write!(f, "+")
|
||||
}
|
||||
AsmBinaryOperator::Subtract => {
|
||||
write!(f, "-")
|
||||
}
|
||||
AsmBinaryOperator::Multiply => {
|
||||
write!(f, "*")
|
||||
}
|
||||
AsmBinaryOperator::Divide => {
|
||||
write!(f, "/")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,16 @@
|
||||
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;
|
||||
use deimos::asm::assemble_ir::assemble_ir_function;
|
||||
use deimos::ast::node::CompilationUnit;
|
||||
use deimos::ir::lower_ast::lower_compilation_unit;
|
||||
use deimos::ir::Ir;
|
||||
use deimos::util::indent_writer::IndentWriter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn compile_to_ir(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
||||
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();
|
||||
@ -17,17 +19,17 @@ pub fn compile_to_ir(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn
|
||||
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);
|
||||
let asm_function = assemble_ir_function(ir_function);
|
||||
println!("{}", asm_function);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(compilation_units)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
use crate::ast::node::{
|
||||
CompilationUnit, Expression, Function, FunctionBlockBody, FunctionBody, Literal,
|
||||
ModuleLevelDeclaration, Statement, VariableDeclaration,
|
||||
};
|
||||
use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration};
|
||||
use crate::ir::{
|
||||
Ir, IrAssign, IrConst, IrExpression, IrFunction, IrKind, IrLiteral, IrPrimitiveKind,
|
||||
IrStatement, IrVariable,
|
||||
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression,
|
||||
IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable,
|
||||
};
|
||||
use crate::name_analysis::symbol::{
|
||||
ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
|
||||
};
|
||||
use crate::name_analysis::symbol::{ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use crate::ir::IrStatement::BinaryOperation;
|
||||
|
||||
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
|
||||
let mut result: Vec<Ir> = vec![];
|
||||
@ -66,7 +66,7 @@ impl LocalsTable {
|
||||
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()
|
||||
}
|
||||
@ -146,7 +146,7 @@ fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> I
|
||||
|
||||
fn lower_function_body(
|
||||
function_body: &FunctionBody,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
||||
match function_body {
|
||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||
@ -163,7 +163,7 @@ fn lower_function_body(
|
||||
|
||||
fn lower_function_block_body(
|
||||
body: &FunctionBlockBody,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
||||
let mut statements: Vec<IrStatement> = vec![];
|
||||
let mut consts: Vec<IrConst> = vec![];
|
||||
@ -176,7 +176,7 @@ fn lower_function_block_body(
|
||||
fn lower_statement(
|
||||
statement: &Statement,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> Vec<IrStatement> {
|
||||
match statement {
|
||||
Statement::VariableDeclaration(variable_declaration) => {
|
||||
@ -186,7 +186,7 @@ fn lower_statement(
|
||||
todo!()
|
||||
}
|
||||
Statement::ExpressionStatement(expression_statement) => {
|
||||
todo!()
|
||||
lower_expression_statement(expression_statement, consts_pool, locals_table)
|
||||
}
|
||||
Statement::UseStatement(use_statement) => {
|
||||
todo!()
|
||||
@ -206,7 +206,7 @@ fn lower_statement(
|
||||
fn lower_variable_declaration(
|
||||
variable_declaration: &VariableDeclaration,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> Vec<IrStatement> {
|
||||
let mut result: Vec<IrStatement> = vec![];
|
||||
let expression_t_var = lower_expression(
|
||||
@ -225,11 +225,26 @@ fn lower_variable_declaration(
|
||||
result
|
||||
}
|
||||
|
||||
fn lower_expression_statement(
|
||||
expression_statement: &ExpressionStatement,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> Vec<IrStatement> {
|
||||
let mut result: Vec<IrStatement> = vec![];
|
||||
lower_expression(
|
||||
expression_statement.expression(),
|
||||
&mut result,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
fn lower_expression(
|
||||
expression: &Expression,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
match expression {
|
||||
Expression::Ternary(ternary) => {
|
||||
@ -248,7 +263,7 @@ fn lower_expression(
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive) => {
|
||||
todo!()
|
||||
lower_additive_expression(additive, target, consts_pool, locals_table)
|
||||
}
|
||||
Expression::Multiplicative(multiplicative) => {
|
||||
todo!()
|
||||
@ -257,12 +272,15 @@ fn lower_expression(
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(suffix) => {
|
||||
todo!()
|
||||
lower_suffix_expression(suffix, target, consts_pool, locals_table)
|
||||
}
|
||||
Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table),
|
||||
Expression::Identifier(identifier) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Identifier(identifier_expression) => lower_identifier(
|
||||
identifier_expression.identifier(),
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
),
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!()
|
||||
}
|
||||
@ -275,11 +293,62 @@ fn lower_expression(
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_suffix_expression(
|
||||
suffix_expression: &SuffixExpression,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
let receiver_variable = lower_expression(
|
||||
suffix_expression.expression(),
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
);
|
||||
match suffix_expression.operator() {
|
||||
SuffixOperator::PlusPlus => {
|
||||
let result_var = locals_table.next_t_var();
|
||||
let operation = IrBinaryOperation::new(
|
||||
result_var.clone(),
|
||||
IrExpression::Variable(receiver_variable.into()),
|
||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
||||
IrBinaryOperator::Add,
|
||||
);
|
||||
target.push(IrStatement::BinaryOperation(operation));
|
||||
result_var
|
||||
}
|
||||
SuffixOperator::MinusMinus => {
|
||||
let result_var = locals_table.next_t_var();
|
||||
let operation = IrBinaryOperation::new(
|
||||
result_var.clone(),
|
||||
IrExpression::Variable(receiver_variable.into()),
|
||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
||||
IrBinaryOperator::Subtract,
|
||||
);
|
||||
target.push(IrStatement::BinaryOperation(operation));
|
||||
result_var
|
||||
}
|
||||
SuffixOperator::ObjectIndex(object_index) => {
|
||||
todo!()
|
||||
}
|
||||
SuffixOperator::Call(call) => lower_call(
|
||||
call,
|
||||
suffix_expression.expression(),
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
),
|
||||
SuffixOperator::ObjectProperty(object_property) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_literal(
|
||||
literal: &Literal,
|
||||
statements: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
match literal {
|
||||
Literal::IntLiteral(int_literal) => {
|
||||
@ -313,3 +382,288 @@ fn lower_literal(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_call(
|
||||
call: &Call,
|
||||
receiver: &Expression,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
let fqn = match receiver {
|
||||
Expression::Ternary(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Or(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::And(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Comparison(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Shift(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Multiplicative(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Literal(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Identifier(identifier_expression) => {
|
||||
match identifier_expression.expressible_symbol().unwrap() {
|
||||
ExpressibleSymbol::Class(class_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
function_symbol.borrow().fqn_formatted()
|
||||
}
|
||||
ExpressibleSymbol::ClassMember(class_member_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Closure(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(_) => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
let declared_type = match receiver {
|
||||
Expression::Ternary(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Or(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::And(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Comparison(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Shift(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Multiplicative(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Literal(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Identifier(identifier_expression) => {
|
||||
match identifier_expression.expressible_symbol().unwrap() {
|
||||
ExpressibleSymbol::Class(_) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
match function_symbol.borrow().return_type().expect(&format!(
|
||||
"Expected return type for fn {}",
|
||||
function_symbol.borrow().fqn_formatted()
|
||||
)) {
|
||||
TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol
|
||||
{
|
||||
PrimitiveTypeSymbol::Byte => {
|
||||
IrKind::Primitive(IrPrimitiveKind::I8.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Char => {
|
||||
todo!()
|
||||
}
|
||||
PrimitiveTypeSymbol::Short => {
|
||||
IrKind::Primitive(IrPrimitiveKind::I16.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Int => {
|
||||
IrKind::Primitive(IrPrimitiveKind::I32.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Long => {
|
||||
IrKind::Primitive(IrPrimitiveKind::I64.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Float => {
|
||||
IrKind::Primitive(IrPrimitiveKind::Float.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Double => {
|
||||
IrKind::Primitive(IrPrimitiveKind::Double.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Boolean => {
|
||||
IrKind::Primitive(IrPrimitiveKind::Boolean.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::String => {
|
||||
IrKind::Primitive(IrPrimitiveKind::String.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::TypedArray { inner_type } => {
|
||||
todo!()
|
||||
}
|
||||
PrimitiveTypeSymbol::Any => {
|
||||
IrKind::Primitive(IrPrimitiveKind::Any.into())
|
||||
}
|
||||
PrimitiveTypeSymbol::Void => {
|
||||
IrKind::Primitive(IrPrimitiveKind::Void.into())
|
||||
}
|
||||
},
|
||||
TypeSymbol::Class(class_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
TypeSymbol::Interface(interface_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
TypeSymbol::Generic(generic_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
ExpressibleSymbol::ClassMember(_) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Parameter(_) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Variable(_) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::Fqn(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Closure(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(_) => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
|
||||
let arg_vars = match call {
|
||||
Call::ParenthesesCall(p_call) => {
|
||||
let mut arg_vars: Vec<IrVariable> = vec![];
|
||||
if let Some(expression_list) = p_call.expression_list() {
|
||||
arg_vars.append(&mut lower_expression_list(
|
||||
expression_list,
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
));
|
||||
}
|
||||
if let Some(closure) = p_call.closure() {
|
||||
arg_vars.push(lower_closure(closure, target, consts_pool, locals_table));
|
||||
}
|
||||
arg_vars
|
||||
}
|
||||
Call::ClosureOnlyCall(c_call) => {
|
||||
vec![lower_closure(
|
||||
c_call.closure(),
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
)]
|
||||
}
|
||||
};
|
||||
let arg_expressions = arg_vars
|
||||
.iter()
|
||||
.map(|ir_variable| IrExpression::Variable(ir_variable.clone().into()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let result_var = locals_table.next_t_var();
|
||||
let call = IrCall::new(
|
||||
result_var.name(),
|
||||
declared_type.into(),
|
||||
&fqn,
|
||||
IrCallType::Static,
|
||||
arg_expressions,
|
||||
);
|
||||
target.push(IrStatement::Call(call));
|
||||
result_var
|
||||
}
|
||||
|
||||
fn lower_expression_list(
|
||||
expression_list: &ExpressionList,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> Vec<IrVariable> {
|
||||
let mut results: Vec<IrVariable> = vec![];
|
||||
for expression in expression_list.expressions() {
|
||||
results.push(lower_expression(
|
||||
expression,
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
));
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
fn lower_closure(
|
||||
closure: &Closure,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn lower_identifier(
|
||||
identifier: &Identifier,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
IrVariable::new(identifier.name())
|
||||
}
|
||||
|
||||
fn lower_additive_expression(
|
||||
additive: &AdditiveExpression,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> IrVariable {
|
||||
let left_var = lower_expression(additive.left(), target, consts_pool, locals_table);
|
||||
let right_var = lower_expression(additive.rhs().expression(), target, consts_pool, locals_table);
|
||||
let destination = locals_table.next_t_var();
|
||||
let operator = match additive.rhs().operator() {
|
||||
AdditiveOperator::Add => {
|
||||
IrBinaryOperator::Add
|
||||
}
|
||||
AdditiveOperator::Subtract => {
|
||||
IrBinaryOperator::Subtract
|
||||
}
|
||||
};
|
||||
let operation = IrBinaryOperation::new(
|
||||
destination.clone(),
|
||||
IrExpression::Variable(left_var.into()),
|
||||
IrExpression::Variable(right_var.into()),
|
||||
operator
|
||||
);
|
||||
target.push(IrStatement::BinaryOperation(operation));
|
||||
destination
|
||||
}
|
||||
|
||||
@ -26,6 +26,9 @@ fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) ->
|
||||
IrStatement::MakeClosure(make_closure) => {
|
||||
todo!()
|
||||
}
|
||||
IrStatement::BinaryOperation(binary_operation) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
134
src/ir/mod.rs
134
src/ir/mod.rs
@ -1,5 +1,7 @@
|
||||
use crate::ir::lower_ast::LocalsTable;
|
||||
use crate::util::indent_writer::IndentWriter;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod lower_ast;
|
||||
pub mod lower_ir;
|
||||
@ -102,6 +104,7 @@ pub enum IrPrimitiveKind {
|
||||
String,
|
||||
Closure(Box<IrClosureKind>),
|
||||
Ref(Box<IrKind>),
|
||||
Any,
|
||||
Void,
|
||||
}
|
||||
|
||||
@ -134,6 +137,7 @@ impl IrPrimitiveKind {
|
||||
IrPrimitiveKind::Ref(ref_kind) => {
|
||||
todo!()
|
||||
}
|
||||
IrPrimitiveKind::Any => writer.write("Any"),
|
||||
IrPrimitiveKind::Void => writer.write("Void"),
|
||||
}
|
||||
}
|
||||
@ -262,6 +266,7 @@ pub enum IrStatement {
|
||||
Return(IrReturn),
|
||||
Assign(IrAssign),
|
||||
MakeClosure(IrMakeClosure),
|
||||
BinaryOperation(IrBinaryOperation),
|
||||
}
|
||||
|
||||
impl IrStatement {
|
||||
@ -272,6 +277,7 @@ impl IrStatement {
|
||||
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),
|
||||
IrStatement::BinaryOperation(binary_operation) => binary_operation.pretty_print(writer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -362,6 +368,86 @@ impl IrAllocate {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrBinaryOperation {
|
||||
destination: Box<IrVariable>,
|
||||
left: Box<IrExpression>,
|
||||
right: Box<IrExpression>,
|
||||
operator: IrBinaryOperator,
|
||||
}
|
||||
|
||||
impl IrBinaryOperation {
|
||||
pub fn new(
|
||||
destination: IrVariable,
|
||||
left: IrExpression,
|
||||
right: IrExpression,
|
||||
operator: IrBinaryOperator,
|
||||
) -> Self {
|
||||
Self {
|
||||
destination: destination.into(),
|
||||
left: left.into(),
|
||||
right: right.into(),
|
||||
operator,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destination(&self) -> &IrVariable {
|
||||
&self.destination
|
||||
}
|
||||
|
||||
pub fn left(&self) -> &IrExpression {
|
||||
&self.left
|
||||
}
|
||||
|
||||
pub fn right(&self) -> &IrExpression {
|
||||
&self.right
|
||||
}
|
||||
|
||||
pub fn operator(&self) -> &IrBinaryOperator {
|
||||
&self.operator
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write_indented("")?;
|
||||
self.destination.pretty_print(writer)?;
|
||||
writer.write(" = ")?;
|
||||
self.left.pretty_print(writer)?;
|
||||
writer.write(&format!(" {} ", self.operator))?;
|
||||
self.right.pretty_print(writer)?;
|
||||
writer.writeln("")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrBinaryOperator {
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Exponent,
|
||||
}
|
||||
|
||||
impl Display for IrBinaryOperator {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrBinaryOperator::Add => {
|
||||
write!(f, "+")
|
||||
}
|
||||
IrBinaryOperator::Subtract => {
|
||||
write!(f, "-")
|
||||
}
|
||||
IrBinaryOperator::Multiply => {
|
||||
write!(f, "*")
|
||||
}
|
||||
IrBinaryOperator::Divide => {
|
||||
write!(f, "/")
|
||||
}
|
||||
IrBinaryOperator::Exponent => {
|
||||
write!(f, "^")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrConst {
|
||||
String(IrStringConst),
|
||||
StringArray(IrStringArrayConst),
|
||||
@ -421,10 +507,22 @@ impl IrVariable {
|
||||
}
|
||||
|
||||
pub struct IrConstRef {
|
||||
name: String,
|
||||
name: Rc<str>,
|
||||
}
|
||||
|
||||
impl IrConstRef {
|
||||
pub fn new(name: Rc<str>) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write(&self.name)
|
||||
}
|
||||
@ -473,7 +571,8 @@ impl IrLiteral {
|
||||
pub struct IrCall {
|
||||
result_name: String,
|
||||
declared_type: Box<IrKind>,
|
||||
function_name: String,
|
||||
fqn: Rc<str>,
|
||||
call_type: IrCallType,
|
||||
arguments: Vec<IrExpression>,
|
||||
}
|
||||
|
||||
@ -481,13 +580,15 @@ impl IrCall {
|
||||
pub fn new(
|
||||
result_name: &str,
|
||||
declared_type: Box<IrKind>,
|
||||
function_name: &str,
|
||||
fqn: &str,
|
||||
call_type: IrCallType,
|
||||
arguments: Vec<IrExpression>,
|
||||
) -> Self {
|
||||
Self {
|
||||
result_name: result_name.to_string(),
|
||||
declared_type,
|
||||
function_name: function_name.to_string(),
|
||||
fqn: fqn.into(),
|
||||
call_type,
|
||||
arguments,
|
||||
}
|
||||
}
|
||||
@ -501,7 +602,15 @@ impl IrCall {
|
||||
}
|
||||
|
||||
pub fn function_name(&self) -> &str {
|
||||
&self.function_name
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
pub fn function_name_owned(&self) -> Rc<str> {
|
||||
self.fqn.clone()
|
||||
}
|
||||
|
||||
pub fn call_type(&self) -> &IrCallType {
|
||||
&self.call_type
|
||||
}
|
||||
|
||||
pub fn arguments(&self) -> &[IrExpression] {
|
||||
@ -509,9 +618,9 @@ impl IrCall {
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write_indented(&format!("let {}: ", self.result_name))?;
|
||||
writer.write_indented(&format!("{}: ", self.result_name))?;
|
||||
self.declared_type.pretty_print(writer)?;
|
||||
writer.write(&format!(" = call {}(", self.function_name))?;
|
||||
writer.write(&format!(" = call {}(", self.fqn))?;
|
||||
for (i, argument) in self.arguments.iter().enumerate() {
|
||||
argument.pretty_print(writer)?;
|
||||
if i != self.arguments.len() - 1 {
|
||||
@ -523,6 +632,11 @@ impl IrCall {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrCallType {
|
||||
Static,
|
||||
Object,
|
||||
}
|
||||
|
||||
pub struct IrAssign {
|
||||
lhs: Box<IrVariable>,
|
||||
rhs: Box<IrExpression>,
|
||||
@ -532,11 +646,11 @@ impl IrAssign {
|
||||
pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
|
||||
Self { lhs, rhs }
|
||||
}
|
||||
|
||||
|
||||
pub fn lhs(&self) -> &IrVariable {
|
||||
&self.lhs
|
||||
}
|
||||
|
||||
|
||||
pub fn rhs(&self) -> &IrExpression {
|
||||
&self.rhs
|
||||
}
|
||||
@ -560,7 +674,7 @@ impl IrReturn {
|
||||
Self { expression }
|
||||
}
|
||||
|
||||
pub fn expression(&self) -> &Box<IrExpression> {
|
||||
pub fn expression(&self) -> &IrExpression {
|
||||
&self.expression
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#![allow(warnings)]
|
||||
extern crate core;
|
||||
|
||||
pub mod asm;
|
||||
pub mod ast;
|
||||
pub mod diagnostic;
|
||||
pub mod ir;
|
||||
|
||||
@ -629,7 +629,8 @@ fn na_p2_expression(
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive) => {
|
||||
todo!()
|
||||
na_p2_expression(additive.left_mut(), symbol_table, diagnostics);
|
||||
na_p2_expression(additive.rhs_mut().expression_mut(), symbol_table, diagnostics);
|
||||
}
|
||||
Expression::Multiplicative(multiplicative) => {
|
||||
todo!()
|
||||
|
||||
@ -50,6 +50,10 @@ impl FunctionSymbol {
|
||||
return_type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fqn_formatted(&self) -> String {
|
||||
self.fqn_parts.join("::")
|
||||
}
|
||||
|
||||
pub fn fqn_parts_owned(&self) -> Vec<Rc<str>> {
|
||||
self.fqn_parts.to_vec()
|
||||
|
||||
@ -24,7 +24,7 @@ pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), Symbol
|
||||
true,
|
||||
None,
|
||||
&vec![Rc::new(RefCell::new(println_msg_symbol))],
|
||||
None,
|
||||
Some(TypeSymbol::Primitive(PrimitiveTypeSymbol::Void)),
|
||||
);
|
||||
symbol_table.register_function_symbol(println_symbol);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user