Rewrite pretty_print as Display impl; tweaking ir.
This commit is contained in:
parent
f656d0d4d4
commit
70aea0ba6f
@ -1,7 +1,12 @@
|
||||
use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId};
|
||||
use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
|
||||
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 {
|
||||
@ -81,7 +86,7 @@ pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction {
|
||||
assemble_ir_statement(statement, &mut context);
|
||||
}
|
||||
|
||||
AsmFunction::new(ir_function.name().into(), context.into_control_units())
|
||||
AsmFunction::new(ir_function.fqn().into(), context.into_control_units())
|
||||
}
|
||||
|
||||
fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) {
|
||||
@ -113,9 +118,6 @@ fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) {
|
||||
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());
|
||||
@ -144,6 +146,7 @@ fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand {
|
||||
IrLiteral::Boolean(b) => AsmOperand::Boolean(*b),
|
||||
IrLiteral::Float(f) => AsmOperand::Float(*f),
|
||||
IrLiteral::Double(d) => AsmOperand::Double(*d),
|
||||
IrLiteral::String(s) => AsmOperand::String(s.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,13 +162,6 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
|
||||
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 {
|
||||
@ -189,72 +185,60 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
|
||||
fqn: ir_call.function_name_owned(),
|
||||
})
|
||||
}
|
||||
IrCallType::PlatformStatic => {}
|
||||
IrCallType::PlatformObject => {}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
let operand = ir_return.expression().map(|expression| {
|
||||
match expression {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
let variable_virtual_register_id = context.get_virtual_register(ir_variable.name());
|
||||
AsmOperand::VirtualRegister(variable_virtual_register_id)
|
||||
}
|
||||
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
|
||||
}
|
||||
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) {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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::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
|
||||
operator,
|
||||
};
|
||||
context.current_control_unit_mut().append_instruction(instruction);
|
||||
}
|
||||
context
|
||||
.current_control_unit_mut()
|
||||
.append_instruction(instruction);
|
||||
}
|
||||
|
||||
@ -79,8 +79,14 @@ pub enum AsmInstruction {
|
||||
InvokeObject {
|
||||
fqn: Rc<str>,
|
||||
},
|
||||
InvokePlatformStatic {
|
||||
fqn: Rc<str>,
|
||||
},
|
||||
InvokePlatformObject {
|
||||
fqn: Rc<str>,
|
||||
},
|
||||
Return {
|
||||
operand: AsmOperand,
|
||||
operand: Option<AsmOperand>,
|
||||
},
|
||||
BinaryOperation {
|
||||
destination: VirtualRegisterId,
|
||||
@ -120,8 +126,18 @@ impl Display for AsmInstruction {
|
||||
AsmInstruction::InvokeObject { fqn } => {
|
||||
write!(f, "invoke_object {}", fqn)
|
||||
}
|
||||
AsmInstruction::InvokePlatformStatic { fqn } => {
|
||||
write!(f, "invoke_platform_static {}", fqn)
|
||||
}
|
||||
AsmInstruction::InvokePlatformObject { fqn } => {
|
||||
write!(f, "invoke_platform_object {}", fqn)
|
||||
}
|
||||
AsmInstruction::Return { operand } => {
|
||||
write!(f, "return {}", operand)
|
||||
write!(f, "return")?;
|
||||
if let Some(operand) = operand {
|
||||
write!(f, " {}", operand)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AsmInstruction::BinaryOperation {
|
||||
destination,
|
||||
@ -151,7 +167,7 @@ pub enum AsmOperand {
|
||||
Float(f32),
|
||||
Double(f64),
|
||||
Boolean(bool),
|
||||
Constant { name: Rc<str> },
|
||||
String(Rc<str>),
|
||||
VirtualRegister(VirtualRegisterId),
|
||||
}
|
||||
|
||||
@ -203,8 +219,8 @@ impl Display for AsmOperand {
|
||||
AsmOperand::Boolean(b) => {
|
||||
write!(f, "{}", b)
|
||||
}
|
||||
AsmOperand::Constant { name } => {
|
||||
write!(f, "<{}>", name)
|
||||
AsmOperand::String(s) => {
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
AsmOperand::VirtualRegister(id) => {
|
||||
write!(f, "vr{}", id)
|
||||
|
||||
@ -13,12 +13,9 @@ pub fn compile_to_ir(
|
||||
|
||||
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!("{}", ir)
|
||||
}
|
||||
println!("{}", &out);
|
||||
|
||||
for ir in &cu_irs {
|
||||
match ir {
|
||||
|
||||
@ -1,119 +1,138 @@
|
||||
use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration};
|
||||
use crate::ast::node::{
|
||||
AdditiveExpression, AdditiveOperator, Call, CompilationUnit, Expression, ExpressionStatement,
|
||||
Function, FunctionBlockBody, FunctionBody, FunctionEqualsBody, Literal, Module,
|
||||
ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration,
|
||||
};
|
||||
use crate::ir::{
|
||||
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression,
|
||||
IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable,
|
||||
};
|
||||
use crate::name_analysis::symbol::{
|
||||
ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
|
||||
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrExpression, IrFunction, IrKind, IrLiteral,
|
||||
IrPrimitiveKind, IrReturn, IrStatement, IrStructKind, IrVariable,
|
||||
};
|
||||
use crate::name_analysis::symbol::{ClassSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
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![];
|
||||
for declaration in compilation_unit.module_level_declarations() {
|
||||
result.append(&mut lower_module_level_declaration(declaration));
|
||||
}
|
||||
result
|
||||
struct CuContext {
|
||||
irs: Vec<Ir>,
|
||||
}
|
||||
|
||||
fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec<Ir> {
|
||||
match declaration {
|
||||
ModuleLevelDeclaration::Module(module) => {
|
||||
todo!()
|
||||
}
|
||||
impl CuContext {
|
||||
pub fn new() -> Self {
|
||||
Self { irs: vec![] }
|
||||
}
|
||||
|
||||
pub fn push_ir(&mut self, ir: Ir) {
|
||||
self.irs.push(ir);
|
||||
}
|
||||
|
||||
pub fn into_irs(self) -> Vec<Ir> {
|
||||
self.irs
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
|
||||
let mut context = CuContext::new();
|
||||
for declaration in compilation_unit.module_level_declarations() {
|
||||
lower_module_level_declaration(declaration, &mut context);
|
||||
}
|
||||
context.into_irs()
|
||||
}
|
||||
|
||||
fn lower_module_level_declaration(
|
||||
module_level_declaration: &ModuleLevelDeclaration,
|
||||
cu_context: &mut CuContext,
|
||||
) {
|
||||
match module_level_declaration {
|
||||
ModuleLevelDeclaration::Module(module) => lower_module(module, cu_context),
|
||||
ModuleLevelDeclaration::Interface(interface) => {
|
||||
todo!()
|
||||
}
|
||||
ModuleLevelDeclaration::Class(class) => {
|
||||
todo!()
|
||||
}
|
||||
ModuleLevelDeclaration::Function(function) => lower_function(function),
|
||||
ModuleLevelDeclaration::Function(function) => lower_function(function, cu_context),
|
||||
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalsTable {
|
||||
t_count: usize,
|
||||
stack_slot_count: usize,
|
||||
stack_slots: HashMap<IrVariable, usize>,
|
||||
fn lower_module(module: &Module, cu_context: &mut CuContext) {
|
||||
for declaration in module.declarations() {
|
||||
lower_module_level_declaration(declaration, cu_context);
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalsTable {
|
||||
pub fn new() -> Self {
|
||||
struct FnContext {
|
||||
t_var_count: usize,
|
||||
statements: Vec<IrStatement>,
|
||||
return_type: Option<TypeSymbol>,
|
||||
}
|
||||
|
||||
impl FnContext {
|
||||
pub fn new(return_type: Option<TypeSymbol>) -> Self {
|
||||
Self {
|
||||
t_count: 0,
|
||||
stack_slot_count: 0,
|
||||
stack_slots: HashMap::new(),
|
||||
t_var_count: 0,
|
||||
statements: vec![],
|
||||
return_type,
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
pub fn next_t_var(&mut self) -> String {
|
||||
let t_var = format!("__t{}", self.t_var_count);
|
||||
self.t_var_count += 1;
|
||||
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 push_statement(&mut self, statement: IrStatement) {
|
||||
self.statements.push(statement);
|
||||
}
|
||||
|
||||
pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize {
|
||||
*self.stack_slots.get(ir_variable).unwrap()
|
||||
pub fn into_statements(self) -> Vec<IrStatement> {
|
||||
self.statements
|
||||
}
|
||||
|
||||
pub fn return_type(&self) -> Option<&TypeSymbol> {
|
||||
self.return_type.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_function(function: &Function) -> Vec<Ir> {
|
||||
fn lower_function(function: &Function, cu_context: &mut CuContext) {
|
||||
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 fqn = function_symbol.fqn_formatted();
|
||||
let parameters = parameter_symbols_to_ir_kinds(function_symbol.parameter_symbols());
|
||||
let return_type = type_symbol_to_ir_kind(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,
|
||||
let mut fn_context = FnContext::new(function_symbol.return_type_owned());
|
||||
lower_function_body(function.function_body(), &mut fn_context);
|
||||
let ir_function = IrFunction::new(
|
||||
&fqn,
|
||||
function_symbol.is_public(),
|
||||
parameters,
|
||||
Box::new(return_type),
|
||||
statements,
|
||||
Box::new(locals_table),
|
||||
))));
|
||||
result.append(
|
||||
&mut consts
|
||||
.into_iter()
|
||||
.map(|constant| Ir::Const(Box::new(constant)))
|
||||
.collect(),
|
||||
return_type,
|
||||
fn_context.into_statements(),
|
||||
);
|
||||
result
|
||||
cu_context.push_ir(Ir::Function(ir_function.into()));
|
||||
}
|
||||
|
||||
fn lower_parameter_symbols(parameter_symbols: &[Rc<RefCell<ParameterSymbol>>]) -> Vec<IrKind> {
|
||||
fn parameter_symbols_to_ir_kinds(
|
||||
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()))
|
||||
.map(|parameter_symbol_ref| {
|
||||
type_symbol_to_ir_kind(parameter_symbol_ref.type_symbol().unwrap())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
|
||||
fn type_symbol_to_ir_kind(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!()
|
||||
primitive_type_symbol_to_ir_kind(primitive_type_symbol)
|
||||
}
|
||||
TypeSymbol::Class(class_symbol) => class_symbol_to_ir_kind(class_symbol.borrow().deref()),
|
||||
TypeSymbol::Interface(interface_type_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
@ -123,7 +142,7 @@ fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
|
||||
fn primitive_type_symbol_to_ir_kind(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
|
||||
IrKind::Primitive(Box::new(match primitive_type_symbol {
|
||||
PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8,
|
||||
PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8,
|
||||
@ -134,59 +153,54 @@ fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> I
|
||||
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::TypedArray { inner_type } => IrPrimitiveKind::Array(Box::new(
|
||||
type_symbol_to_ir_kind(inner_type.as_ref().unwrap()),
|
||||
)),
|
||||
PrimitiveTypeSymbol::Any => IrPrimitiveKind::Any,
|
||||
PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void,
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_function_body(
|
||||
function_body: &FunctionBody,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> (Vec<IrStatement>, Vec<IrConst>) {
|
||||
fn class_symbol_to_ir_kind(class_type_symbol: &ClassSymbol) -> IrKind {
|
||||
let struct_kind = IrStructKind::new(&class_type_symbol.fqn_formatted());
|
||||
IrKind::Struct(struct_kind.into())
|
||||
}
|
||||
|
||||
fn lower_function_body(function_body: &FunctionBody, fn_context: &mut FnContext) {
|
||||
match function_body {
|
||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||
todo!()
|
||||
}
|
||||
FunctionBody::FunctionEqualsBody(equals_body) => {
|
||||
todo!()
|
||||
lower_function_equals_body(equals_body, fn_context);
|
||||
}
|
||||
FunctionBody::FunctionBlockBody(block_body) => {
|
||||
lower_function_block_body(block_body, locals_table)
|
||||
lower_function_block_body(block_body, fn_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_function_equals_body(body: &FunctionEqualsBody, fn_context: &mut FnContext) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn lower_statement(
|
||||
statement: &Statement,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
) -> Vec<IrStatement> {
|
||||
fn lower_function_block_body(body: &FunctionBlockBody, fn_context: &mut FnContext) {
|
||||
let statement_count = body.statements().count();
|
||||
for (i, statement) in body.statements().enumerate() {
|
||||
lower_statement(statement, fn_context, i == statement_count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_statement(statement: &Statement, fn_context: &mut FnContext, is_last: bool) {
|
||||
match statement {
|
||||
Statement::VariableDeclaration(variable_declaration) => {
|
||||
lower_variable_declaration(variable_declaration, consts_pool, locals_table)
|
||||
lower_variable_declaration(variable_declaration, fn_context)
|
||||
}
|
||||
Statement::AssignmentStatement(assignment_statement) => {
|
||||
todo!()
|
||||
}
|
||||
Statement::ExpressionStatement(expression_statement) => {
|
||||
lower_expression_statement(expression_statement, consts_pool, locals_table)
|
||||
lower_expression_statement(expression_statement, fn_context, is_last)
|
||||
}
|
||||
Statement::UseStatement(use_statement) => {
|
||||
todo!()
|
||||
@ -205,465 +219,223 @@ fn lower_statement(
|
||||
|
||||
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_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,
|
||||
) -> 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) => {
|
||||
lower_additive_expression(additive, target, consts_pool, locals_table)
|
||||
}
|
||||
Expression::Multiplicative(multiplicative) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(prefix) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(suffix) => {
|
||||
lower_suffix_expression(suffix, target, consts_pool, locals_table)
|
||||
}
|
||||
Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table),
|
||||
Expression::Identifier(identifier_expression) => lower_identifier(
|
||||
identifier_expression.identifier(),
|
||||
target,
|
||||
consts_pool,
|
||||
locals_table,
|
||||
fn_context: &mut FnContext,
|
||||
) {
|
||||
let initializer = match variable_declaration.expression() {
|
||||
Expression::Literal(literal) => literal_to_ir_expression(literal),
|
||||
Expression::Identifier(identifier_expression) => IrExpression::Variable(
|
||||
IrVariable::new(identifier_expression.identifier().name()).into(),
|
||||
),
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!("Fqn as expressions")
|
||||
}
|
||||
_ => expression_to_ir_expression(variable_declaration.expression(), fn_context),
|
||||
};
|
||||
|
||||
let result_variable = IrVariable::new(variable_declaration.identifier().name());
|
||||
let ir_assign = IrAssign::new(result_variable, initializer);
|
||||
fn_context.push_statement(IrStatement::Assign(ir_assign.into()));
|
||||
}
|
||||
|
||||
fn literal_to_ir_expression(literal: &Literal) -> IrExpression {
|
||||
match literal {
|
||||
Literal::IntLiteral(i) => IrExpression::Literal(IrLiteral::I32(*i).into()),
|
||||
Literal::LongLiteral(l) => IrExpression::Literal(IrLiteral::I64(*l).into()),
|
||||
Literal::DoubleLiteral(d) => IrExpression::Literal(IrLiteral::Double(*d).into()),
|
||||
Literal::SingleQuoteString(s) => {
|
||||
IrExpression::Literal(IrLiteral::String(Rc::from(s.as_ref())).into())
|
||||
}
|
||||
Literal::DString(d_string) => todo!(),
|
||||
Literal::BacktickString(backtick_string) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Closure(closure) => {
|
||||
Literal::BooleanLiteral(b) => IrExpression::Literal(IrLiteral::Boolean(*b).into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn expression_to_ir_expression(
|
||||
expression: &Expression,
|
||||
fn_context: &mut FnContext,
|
||||
) -> IrExpression {
|
||||
IrExpression::Variable(expression_into_ir_variable(expression, fn_context).into())
|
||||
}
|
||||
|
||||
fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnContext) -> IrVariable {
|
||||
match expression {
|
||||
Expression::Ternary(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(list) => {
|
||||
Expression::Or(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::And(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Comparison(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Shift(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive_expression) => {
|
||||
additive_expression_into_ir_variable(additive_expression, fn_context)
|
||||
}
|
||||
Expression::Multiplicative(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(suffix_expression) => {
|
||||
suffix_expression_into_ir_variable(suffix_expression, fn_context)
|
||||
}
|
||||
Expression::Literal(literal) => {
|
||||
let literal_as_ir_expression = literal_to_ir_expression(literal);
|
||||
let t_var_name = fn_context.next_t_var();
|
||||
let t_var_ir_variable = IrVariable::new(&t_var_name);
|
||||
let ir_assign = IrAssign::new(t_var_ir_variable.clone(), literal_as_ir_expression);
|
||||
fn_context.push_statement(IrStatement::Assign(ir_assign.into()));
|
||||
t_var_ir_variable
|
||||
}
|
||||
Expression::Identifier(identifier_expression) => {
|
||||
IrVariable::new(identifier_expression.identifier().name())
|
||||
}
|
||||
Expression::Fqn(_) => {
|
||||
todo!("Fqn as expression")
|
||||
}
|
||||
Expression::Closure(_) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(_) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_suffix_expression(
|
||||
suffix_expression: &SuffixExpression,
|
||||
target: &mut Vec<IrStatement>,
|
||||
consts_pool: &mut Vec<IrConst>,
|
||||
locals_table: &mut LocalsTable,
|
||||
fn additive_expression_into_ir_variable(
|
||||
additive_expression: &AdditiveExpression,
|
||||
fn_context: &mut FnContext,
|
||||
) -> IrVariable {
|
||||
let left = expression_to_ir_expression(additive_expression.left(), fn_context);
|
||||
let right = expression_to_ir_expression(additive_expression.rhs().expression(), fn_context);
|
||||
let operator = match additive_expression.rhs().operator() {
|
||||
AdditiveOperator::Add => IrBinaryOperator::Add,
|
||||
AdditiveOperator::Subtract => IrBinaryOperator::Subtract,
|
||||
};
|
||||
let result_variable_name = fn_context.next_t_var();
|
||||
let result_ir_variable = IrVariable::new(&result_variable_name);
|
||||
let add_op = IrBinaryOperation::new(result_ir_variable.clone(), left, right, operator);
|
||||
fn_context.push_statement(IrStatement::BinaryOperation(add_op.into()));
|
||||
result_ir_variable
|
||||
}
|
||||
|
||||
fn suffix_expression_into_ir_variable(
|
||||
suffix_expression: &SuffixExpression,
|
||||
fn_context: &mut FnContext,
|
||||
) -> 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()),
|
||||
let result_variable_name = fn_context.next_t_var();
|
||||
let result_ir_variable = IrVariable::new(&result_variable_name);
|
||||
let plus_plus_op = IrBinaryOperation::new(
|
||||
result_ir_variable.clone(),
|
||||
expression_to_ir_expression(suffix_expression.expression(), fn_context),
|
||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
||||
IrBinaryOperator::Add,
|
||||
);
|
||||
target.push(IrStatement::BinaryOperation(operation));
|
||||
result_var
|
||||
fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into()));
|
||||
result_ir_variable
|
||||
}
|
||||
SuffixOperator::MinusMinus => {
|
||||
let result_var = locals_table.next_t_var();
|
||||
let operation = IrBinaryOperation::new(
|
||||
result_var.clone(),
|
||||
IrExpression::Variable(receiver_variable.into()),
|
||||
let result_variable_name = fn_context.next_t_var();
|
||||
let result_ir_variable = IrVariable::new(&result_variable_name);
|
||||
let plus_plus_op = IrBinaryOperation::new(
|
||||
result_ir_variable.clone(),
|
||||
expression_to_ir_expression(suffix_expression.expression(), fn_context),
|
||||
IrExpression::Literal(IrLiteral::I32(1).into()),
|
||||
IrBinaryOperator::Subtract,
|
||||
IrBinaryOperator::Subtract, // n.b.
|
||||
);
|
||||
target.push(IrStatement::BinaryOperation(operation));
|
||||
result_var
|
||||
fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into()));
|
||||
result_ir_variable
|
||||
}
|
||||
SuffixOperator::ObjectIndex(object_index) => {
|
||||
todo!("Object indexing")
|
||||
}
|
||||
SuffixOperator::Call(call) => {
|
||||
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,
|
||||
) -> 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
|
||||
fn lower_expression_statement(
|
||||
expression_statement: &ExpressionStatement,
|
||||
fn_context: &mut FnContext,
|
||||
is_last: bool,
|
||||
) {
|
||||
let is_void_return = if let Some(return_type_symbol) = fn_context.return_type() {
|
||||
match return_type_symbol {
|
||||
TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol {
|
||||
PrimitiveTypeSymbol::Void => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
Literal::LongLiteral(long_literal) => {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if is_last && !is_void_return {
|
||||
let return_statement = IrReturn::new(Some(expression_to_ir_expression(
|
||||
expression_statement.expression(),
|
||||
fn_context,
|
||||
)));
|
||||
fn_context.push_statement(IrStatement::Return(return_statement.into()));
|
||||
} else {
|
||||
lower_side_effect_expression(expression_statement.expression(), fn_context);
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_side_effect_expression(expression: &Expression, fn_context: &mut FnContext) {
|
||||
match expression {
|
||||
Expression::Suffix(suffix_expression) => {
|
||||
lower_side_effect_suffix_expression(suffix_expression, fn_context);
|
||||
}
|
||||
_ => {
|
||||
todo!("Anything other than a suffix expression for side-effects should be eliminated as dead code.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_side_effect_suffix_expression(
|
||||
suffix_expression: &SuffixExpression,
|
||||
fn_context: &mut FnContext,
|
||||
) {
|
||||
match suffix_expression.operator() {
|
||||
SuffixOperator::PlusPlus => {
|
||||
todo!()
|
||||
}
|
||||
Literal::DoubleLiteral(double_literal) => {
|
||||
SuffixOperator::MinusMinus => {
|
||||
todo!()
|
||||
}
|
||||
Literal::SingleQuoteString(sq_string) => {
|
||||
SuffixOperator::ObjectIndex(object_index) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::DString(d_string) => {
|
||||
todo!()
|
||||
SuffixOperator::Call(call) => {
|
||||
call_to_ir_expression(call, suffix_expression.expression(), fn_context);
|
||||
}
|
||||
Literal::BacktickString(b_string) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::BooleanLiteral(boolean_literal) => {
|
||||
SuffixOperator::ObjectProperty(object_property) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_call(
|
||||
fn call_to_ir_expression(
|
||||
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 {
|
||||
fn_context: &mut FnContext,
|
||||
) -> IrExpression {
|
||||
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
|
||||
}
|
||||
|
||||
@ -1,134 +0,0 @@
|
||||
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!()
|
||||
}
|
||||
IrStatement::BinaryOperation(binary_operation) => {
|
||||
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
|
||||
}
|
||||
705
src/ir/mod.rs
705
src/ir/mod.rs
@ -1,72 +1,123 @@
|
||||
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;
|
||||
|
||||
pub enum Ir {
|
||||
Struct(Box<IrStruct>),
|
||||
Function(Box<IrFunction>),
|
||||
PlatformFunction(Box<IrPlatformFunction>),
|
||||
Const(Box<IrConst>),
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
impl Display for Ir {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(
|
||||
f,
|
||||
"{}\n",
|
||||
match self {
|
||||
Ir::Struct(ir_struct) => {
|
||||
format!("{}", ir_struct)
|
||||
}
|
||||
Ir::Function(ir_function) => {
|
||||
format!("{}", ir_function)
|
||||
}
|
||||
Ir::PlatformFunction(ir_platform_function) => {
|
||||
format!("{}", ir_platform_function)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrStruct {
|
||||
name: String,
|
||||
name: Rc<str>,
|
||||
is_public: bool,
|
||||
members: Vec<IrStructMember>,
|
||||
}
|
||||
|
||||
impl IrStruct {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
pub fn new(name: &str, is_public: bool, members: Vec<IrStructMember>) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
is_public,
|
||||
members,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.is_public
|
||||
}
|
||||
|
||||
pub fn members(&self) -> &[IrStructMember] {
|
||||
&self.members
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IrStruct {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_public {
|
||||
writer.writeln(&format!("pub struct {} {{", self.name))?;
|
||||
} else {
|
||||
writer.writeln(&format!("struct {} {{", self.name))?;
|
||||
write!(f, "pub ")?;
|
||||
}
|
||||
writer.increase_indent();
|
||||
writeln!(f, "struct {} {{", self.name)?;
|
||||
for member in &self.members {
|
||||
member.pretty_print(writer)?;
|
||||
writer.write("\n")?;
|
||||
writeln!(f, " {}", member)?;
|
||||
}
|
||||
writer.decrease_indent();
|
||||
writer.writeln("}")?;
|
||||
writeln!(f, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrStructMember {
|
||||
name: String,
|
||||
name: Rc<str>,
|
||||
kind: Box<IrKind>,
|
||||
is_public: bool,
|
||||
is_mut: bool,
|
||||
}
|
||||
|
||||
impl IrStructMember {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
pub fn new(name: &str, kind: IrKind, is_public: bool, is_mut: bool) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
kind: kind.into(),
|
||||
is_public,
|
||||
is_mut,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &IrKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.is_public
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IrStructMember {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_public {
|
||||
writer.write("pub ")?;
|
||||
write!(f, "pub ")?;
|
||||
}
|
||||
if self.is_mut {
|
||||
writer.write("mut ")?;
|
||||
write!(f, "mut ")?;
|
||||
}
|
||||
writer.write(&self.name)?;
|
||||
writer.write(": ")?;
|
||||
self.kind.pretty_print(writer)?;
|
||||
Ok(())
|
||||
write!(f, "{}: {}", self.name, self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,11 +126,15 @@ pub enum IrKind {
|
||||
Struct(Box<IrStructKind>),
|
||||
}
|
||||
|
||||
impl IrKind {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
impl Display for IrKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrKind::Primitive(primitive) => primitive.pretty_print(writer),
|
||||
IrKind::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
||||
IrKind::Primitive(ir_primitive_kind) => {
|
||||
write!(f, "{}", ir_primitive_kind)
|
||||
}
|
||||
IrKind::Struct(ir_struct_kind) => {
|
||||
write!(f, "{}", ir_struct_kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,99 +158,115 @@ pub enum IrPrimitiveKind {
|
||||
Array(Box<IrKind>),
|
||||
String,
|
||||
Closure(Box<IrClosureKind>),
|
||||
Ref(Box<IrKind>),
|
||||
Any,
|
||||
Void,
|
||||
}
|
||||
|
||||
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::Any => writer.write("Any"),
|
||||
IrPrimitiveKind::Void => writer.write("Void"),
|
||||
}
|
||||
impl Display for IrPrimitiveKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
IrPrimitiveKind::I8 => "i8",
|
||||
IrPrimitiveKind::I16 => "i16",
|
||||
IrPrimitiveKind::I32 => "i32",
|
||||
IrPrimitiveKind::I64 => "i64",
|
||||
IrPrimitiveKind::I128 => "i128",
|
||||
IrPrimitiveKind::ISize => "isize",
|
||||
IrPrimitiveKind::U8 => "u8",
|
||||
IrPrimitiveKind::U16 => "u16",
|
||||
IrPrimitiveKind::U32 => "u32",
|
||||
IrPrimitiveKind::U64 => "u64",
|
||||
IrPrimitiveKind::U128 => "u128",
|
||||
IrPrimitiveKind::USize => "usize",
|
||||
IrPrimitiveKind::Float => "f32",
|
||||
IrPrimitiveKind::Double => "f64",
|
||||
IrPrimitiveKind::Boolean => "Boolean",
|
||||
IrPrimitiveKind::Array(inner_kind) => &format!("Array<{}>", inner_kind),
|
||||
IrPrimitiveKind::String => "String",
|
||||
IrPrimitiveKind::Closure(ir_closure_kind) => &format!("{}", ir_closure_kind),
|
||||
IrPrimitiveKind::Any => "Any",
|
||||
IrPrimitiveKind::Void => "Void",
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrStructKind {
|
||||
name: String,
|
||||
name: Rc<str>,
|
||||
}
|
||||
|
||||
impl IrStructKind {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
}
|
||||
Self { name: name.into() }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write(&self.name)
|
||||
pub fn name_owned(&self) -> Rc<str> {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IrStructKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrClosureKind {
|
||||
captures_struct_name: String,
|
||||
captures_struct_name: Rc<str>,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
}
|
||||
|
||||
impl Display for IrClosureKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Closure |{}| ({}) -> {}",
|
||||
self.captures_struct_name,
|
||||
self.parameters
|
||||
.iter()
|
||||
.map(|ir_kind| format!("{}", ir_kind))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
self.return_type
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrFunction {
|
||||
name: String,
|
||||
fqn: Rc<str>,
|
||||
is_public: bool,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
statements: Vec<IrStatement>,
|
||||
locals_table: Box<LocalsTable>,
|
||||
}
|
||||
|
||||
impl IrFunction {
|
||||
pub fn new(
|
||||
name: String,
|
||||
fqn: &str,
|
||||
is_public: bool,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
return_type: IrKind,
|
||||
statements: Vec<IrStatement>,
|
||||
locals_table: Box<LocalsTable>,
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
fqn: fqn.into(),
|
||||
is_public,
|
||||
parameters,
|
||||
return_type,
|
||||
return_type: return_type.into(),
|
||||
statements,
|
||||
locals_table,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
pub fn fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
pub fn fqn_owned(&self) -> Rc<str> {
|
||||
self.fqn.clone()
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> &[IrKind] {
|
||||
@ -209,76 +280,93 @@ impl IrFunction {
|
||||
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(", ")?;
|
||||
}
|
||||
impl Display for IrFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_public {
|
||||
write!(f, "pub ")?;
|
||||
}
|
||||
writer.write(") -> ")?;
|
||||
self.return_type.pretty_print(writer)?;
|
||||
writer.write(" {\n")?;
|
||||
writer.increase_indent();
|
||||
writeln!(
|
||||
f,
|
||||
"fn {}({}) -> {} {{",
|
||||
self.fqn,
|
||||
self.parameters
|
||||
.iter()
|
||||
.map(|ir_kind| format!("{}", ir_kind))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
self.return_type
|
||||
)?;
|
||||
for statement in &self.statements {
|
||||
statement.pretty_print(writer)?;
|
||||
writeln!(f, " {}", statement)?;
|
||||
}
|
||||
writer.decrease_indent();
|
||||
writer.writeln("}")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrPlatformFunction {
|
||||
name: String,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
}
|
||||
|
||||
impl IrPlatformFunction {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
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")?;
|
||||
writeln!(f, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrStatement {
|
||||
Allocate(IrAllocate),
|
||||
Call(IrCall),
|
||||
Return(IrReturn),
|
||||
Assign(IrAssign),
|
||||
MakeClosure(IrMakeClosure),
|
||||
BinaryOperation(IrBinaryOperation),
|
||||
pub struct IrPlatformFunction {
|
||||
fqn: Rc<str>,
|
||||
is_public: bool,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
}
|
||||
|
||||
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),
|
||||
IrStatement::BinaryOperation(binary_operation) => binary_operation.pretty_print(writer),
|
||||
impl Display for IrPlatformFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_public {
|
||||
write!(f, "pub ")?;
|
||||
}
|
||||
writeln!(
|
||||
f,
|
||||
"platform fn {}({}) -> {}",
|
||||
self.fqn,
|
||||
self.parameters
|
||||
.iter()
|
||||
.map(|ir_kind| format!("{}", ir_kind))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
self.return_type
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrStatement {
|
||||
Allocate(Box<IrAllocate>),
|
||||
Call(Box<IrCall>),
|
||||
Return(Box<IrReturn>),
|
||||
Assign(Box<IrAssign>),
|
||||
MakeClosure(Box<IrMakeClosure>),
|
||||
BinaryOperation(Box<IrBinaryOperation>),
|
||||
}
|
||||
|
||||
impl Display for IrStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
IrStatement::Allocate(ir_allocate) => {
|
||||
format!("{}", ir_allocate)
|
||||
}
|
||||
IrStatement::Call(ir_call) => {
|
||||
format!("{}", ir_call)
|
||||
}
|
||||
IrStatement::Return(ir_return) => {
|
||||
format!("{}", ir_return)
|
||||
}
|
||||
IrStatement::Assign(ir_assign) => {
|
||||
format!("{}", ir_assign)
|
||||
}
|
||||
IrStatement::MakeClosure(ir_make_closure) => {
|
||||
format!("{}", ir_make_closure)
|
||||
}
|
||||
IrStatement::BinaryOperation(ir_binary_operation) => {
|
||||
format!("{}", ir_binary_operation)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,11 +375,15 @@ pub enum IrAllocable {
|
||||
Array(Box<IrArrayKind>),
|
||||
}
|
||||
|
||||
impl IrAllocable {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
impl Display for IrAllocable {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrAllocable::Struct(struct_kind) => struct_kind.pretty_print(writer),
|
||||
IrAllocable::Array(array_kind) => array_kind.pretty_print(writer),
|
||||
IrAllocable::Struct(ir_struct_kind) => {
|
||||
write!(f, "{}(", ir_struct_kind)
|
||||
}
|
||||
IrAllocable::Array(ir_array_kind) => {
|
||||
write!(f, "{}(", ir_array_kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -301,11 +393,15 @@ pub enum IrArrayKind {
|
||||
DynamicSize(Box<IrDynamicArrayKind>),
|
||||
}
|
||||
|
||||
impl IrArrayKind {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
impl Display for IrArrayKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> 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),
|
||||
IrArrayKind::StaticSize(ir_static_array_kind) => {
|
||||
write!(f, "{}", ir_static_array_kind)
|
||||
}
|
||||
IrArrayKind::DynamicSize(ir_dynamic_array_kind) => {
|
||||
write!(f, "{}", ir_dynamic_array_kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,12 +411,9 @@ pub struct IrStaticArrayKind {
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl IrStaticArrayKind {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write("[")?;
|
||||
self.inner_kind.pretty_print(writer)?;
|
||||
writer.write(&format!("; {}]", self.size))?;
|
||||
Ok(())
|
||||
impl Display for IrStaticArrayKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Array<{}>[{}]", self.inner_kind, self.size)
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,26 +422,33 @@ pub struct IrDynamicArrayKind {
|
||||
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(())
|
||||
impl Display for IrDynamicArrayKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Array<{}>", self.inner_kind)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrAllocate {
|
||||
name: String,
|
||||
result_variable: Rc<str>,
|
||||
declared_kind: Box<IrAllocable>,
|
||||
kind_to_alloc: Box<IrAllocable>,
|
||||
}
|
||||
|
||||
impl IrAllocate {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
pub fn new(
|
||||
result_variable: &str,
|
||||
declared_kind: IrAllocable,
|
||||
kind_to_alloc: IrAllocable,
|
||||
) -> Self {
|
||||
Self {
|
||||
result_variable: result_variable.into(),
|
||||
declared_kind: declared_kind.into(),
|
||||
kind_to_alloc: kind_to_alloc.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn result_variable(&self) -> &str {
|
||||
&self.result_variable
|
||||
}
|
||||
|
||||
pub fn declared_kind(&self) -> &IrAllocable {
|
||||
@ -358,13 +458,15 @@ impl IrAllocate {
|
||||
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(())
|
||||
impl Display for IrAllocate {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}: {} = alloc {}",
|
||||
self.result_variable, self.declared_kind, self.kind_to_alloc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,16 +507,15 @@ impl IrBinaryOperation {
|
||||
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(())
|
||||
impl Display for IrBinaryOperation {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} = {} {} {}",
|
||||
self.destination, self.left, self.operator, self.right
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,83 +549,46 @@ impl Display for IrBinaryOperator {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
value: String,
|
||||
}
|
||||
|
||||
pub struct IrStringArrayConst {
|
||||
name: String,
|
||||
value: Vec<String>,
|
||||
}
|
||||
|
||||
pub enum IrExpression {
|
||||
Variable(Box<IrVariable>),
|
||||
ConstRef(Box<IrConstRef>),
|
||||
Literal(Box<IrLiteral>),
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
impl Display for IrExpression {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
IrExpression::Variable(ir_variable) => {
|
||||
format!("{}", ir_variable)
|
||||
}
|
||||
IrExpression::Literal(ir_literal) => {
|
||||
format!("{}", ir_literal)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||
pub struct IrVariable {
|
||||
name: String,
|
||||
name: Rc<str>,
|
||||
}
|
||||
|
||||
impl IrVariable {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
}
|
||||
Self { name: name.into() }
|
||||
}
|
||||
|
||||
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: 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)
|
||||
impl Display for IrVariable {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -544,57 +608,63 @@ pub enum IrLiteral {
|
||||
Boolean(bool),
|
||||
Float(f32),
|
||||
Double(f64),
|
||||
String(Rc<str>),
|
||||
}
|
||||
|
||||
impl IrLiteral {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
match self {
|
||||
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)),
|
||||
}
|
||||
impl Display for IrLiteral {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
IrLiteral::I8(i) => format!("{}", *i),
|
||||
IrLiteral::I16(i) => format!("{}", *i),
|
||||
IrLiteral::I32(i) => format!("{}", *i),
|
||||
IrLiteral::I64(i) => format!("{}", *i),
|
||||
IrLiteral::I128(i) => format!("{}", *i),
|
||||
IrLiteral::ISize(i) => format!("{}", *i),
|
||||
IrLiteral::U8(u) => format!("{}", *u),
|
||||
IrLiteral::U16(u) => format!("{}", *u),
|
||||
IrLiteral::U32(u) => format!("{}", *u),
|
||||
IrLiteral::U64(u) => format!("{}", *u),
|
||||
IrLiteral::U128(u) => format!("{}", *u),
|
||||
IrLiteral::USize(u) => format!("{}", *u),
|
||||
IrLiteral::Boolean(b) => format!("{}", *b),
|
||||
IrLiteral::Float(float) => format!("{}", *float),
|
||||
IrLiteral::Double(double) => format!("{}", *double),
|
||||
IrLiteral::String(s) => format!("{}", s),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrCall {
|
||||
result_name: String,
|
||||
result_variable: Option<Rc<str>>,
|
||||
declared_type: Box<IrKind>,
|
||||
fqn: Rc<str>,
|
||||
function_fqn: Rc<str>,
|
||||
call_type: IrCallType,
|
||||
arguments: Vec<IrExpression>,
|
||||
}
|
||||
|
||||
impl IrCall {
|
||||
pub fn new(
|
||||
result_name: &str,
|
||||
declared_type: Box<IrKind>,
|
||||
result_variable: Option<&str>,
|
||||
declared_type: IrKind,
|
||||
fqn: &str,
|
||||
call_type: IrCallType,
|
||||
arguments: Vec<IrExpression>,
|
||||
) -> Self {
|
||||
Self {
|
||||
result_name: result_name.to_string(),
|
||||
declared_type,
|
||||
fqn: fqn.into(),
|
||||
result_variable: result_variable.map(Rc::from),
|
||||
declared_type: declared_type.into(),
|
||||
function_fqn: fqn.into(),
|
||||
call_type,
|
||||
arguments,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn result_name(&self) -> &str {
|
||||
&self.result_name
|
||||
pub fn result_variable(&self) -> Option<&str> {
|
||||
self.result_variable.as_ref().map(Rc::as_ref)
|
||||
}
|
||||
|
||||
pub fn declared_type(&self) -> &IrKind {
|
||||
@ -602,11 +672,11 @@ impl IrCall {
|
||||
}
|
||||
|
||||
pub fn function_name(&self) -> &str {
|
||||
&self.fqn
|
||||
&self.function_fqn
|
||||
}
|
||||
|
||||
pub fn function_name_owned(&self) -> Rc<str> {
|
||||
self.fqn.clone()
|
||||
self.function_fqn.clone()
|
||||
}
|
||||
|
||||
pub fn call_type(&self) -> &IrCallType {
|
||||
@ -616,25 +686,51 @@ impl IrCall {
|
||||
pub fn arguments(&self) -> &[IrExpression] {
|
||||
&self.arguments
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write_indented(&format!("{}: ", self.result_name))?;
|
||||
self.declared_type.pretty_print(writer)?;
|
||||
writer.write(&format!(" = call {}(", self.fqn))?;
|
||||
for (i, argument) in self.arguments.iter().enumerate() {
|
||||
argument.pretty_print(writer)?;
|
||||
if i != self.arguments.len() - 1 {
|
||||
writer.write(", ")?;
|
||||
}
|
||||
impl Display for IrCall {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(result_variable) = &self.result_variable {
|
||||
write!(f, "{}: {} = ", result_variable, self.declared_type)?;
|
||||
}
|
||||
writer.write(")\n")?;
|
||||
Ok(())
|
||||
write!(
|
||||
f,
|
||||
"{} {}({})",
|
||||
self.call_type,
|
||||
self.function_fqn,
|
||||
self.arguments
|
||||
.iter()
|
||||
.map(|ir_expression| ir_expression.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum IrCallType {
|
||||
Static,
|
||||
Object,
|
||||
PlatformStatic,
|
||||
PlatformObject,
|
||||
}
|
||||
|
||||
impl Display for IrCallType {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrCallType::Static => {
|
||||
write!(f, "call_static")
|
||||
}
|
||||
IrCallType::Object => {
|
||||
write!(f, "call_object")
|
||||
}
|
||||
IrCallType::PlatformStatic => {
|
||||
write!(f, "call_platform_static")
|
||||
}
|
||||
IrCallType::PlatformObject => {
|
||||
write!(f, "call_platform_object")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrAssign {
|
||||
@ -643,8 +739,11 @@ pub struct IrAssign {
|
||||
}
|
||||
|
||||
impl IrAssign {
|
||||
pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
|
||||
Self { lhs, rhs }
|
||||
pub fn new(lhs: IrVariable, rhs: IrExpression) -> Self {
|
||||
Self {
|
||||
lhs: lhs.into(),
|
||||
rhs: rhs.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lhs(&self) -> &IrVariable {
|
||||
@ -654,34 +753,36 @@ impl IrAssign {
|
||||
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(())
|
||||
impl Display for IrAssign {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} = {}", self.lhs, self.rhs)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrReturn {
|
||||
expression: Box<IrExpression>,
|
||||
expression: Option<Box<IrExpression>>,
|
||||
}
|
||||
|
||||
impl IrReturn {
|
||||
pub fn new(expression: Box<IrExpression>) -> Self {
|
||||
Self { expression }
|
||||
pub fn new(expression: Option<IrExpression>) -> Self {
|
||||
Self {
|
||||
expression: expression.map(Box::new),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expression(&self) -> &IrExpression {
|
||||
&self.expression
|
||||
pub fn expression(&self) -> Option<&IrExpression> {
|
||||
self.expression.as_ref().map(Box::as_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
writer.write_indented("return ")?;
|
||||
self.expression.pretty_print(writer)?;
|
||||
writer.write("\n")?;
|
||||
impl Display for IrReturn {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "return")?;
|
||||
if let Some(expression) = &self.expression {
|
||||
write!(f, " {}", expression)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -690,13 +791,13 @@ pub struct IrMakeClosure {
|
||||
captures_kind: Option<Box<IrStructKind>>,
|
||||
parameters: Vec<IrKind>,
|
||||
return_type: Box<IrKind>,
|
||||
name: String,
|
||||
fn_name: String,
|
||||
result_variable: Rc<str>,
|
||||
function_fqn: Rc<str>,
|
||||
captures_variable: Box<IrVariable>,
|
||||
}
|
||||
|
||||
impl IrMakeClosure {
|
||||
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
|
||||
impl Display for IrMakeClosure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#![feature(new_range_api)]
|
||||
#![feature(coerce_unsized)]
|
||||
#![feature(unsize)]
|
||||
#![feature(coerce_unsized)]
|
||||
#![allow(warnings)]
|
||||
extern crate core;
|
||||
|
||||
|
||||
@ -529,9 +529,7 @@ fn na_p2_variable_declaration(
|
||||
}
|
||||
|
||||
// initializer
|
||||
if let Some(expression) = variable_declaration.expression_mut() {
|
||||
na_p2_expression(expression, symbol_table, diagnostics);
|
||||
}
|
||||
na_p2_expression(variable_declaration.expression_mut(), symbol_table, diagnostics);
|
||||
}
|
||||
|
||||
fn na_p2_assignment_statement(
|
||||
|
||||
@ -24,6 +24,10 @@ impl ClassSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fqn_formatted(&self) -> String {
|
||||
self.fqn_parts.join("::")
|
||||
}
|
||||
|
||||
pub fn declared_name(&self) -> &str {
|
||||
self.fqn_parts.last().unwrap()
|
||||
}
|
||||
|
||||
@ -86,6 +86,10 @@ impl FunctionSymbol {
|
||||
pub fn return_type(&self) -> Option<&TypeSymbol> {
|
||||
self.return_type.as_ref()
|
||||
}
|
||||
|
||||
pub fn return_type_owned(&self) -> Option<TypeSymbol> {
|
||||
self.return_type.clone()
|
||||
}
|
||||
|
||||
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
|
||||
self.return_type = Some(type_symbol);
|
||||
|
||||
@ -694,9 +694,7 @@ VariableDeclaration:
|
||||
- type_use:
|
||||
member:
|
||||
optional: true
|
||||
- expression:
|
||||
member:
|
||||
optional: true
|
||||
- expression
|
||||
fields:
|
||||
- variable_symbol:
|
||||
kind: VariableSymbol
|
||||
|
||||
Loading…
Reference in New Issue
Block a user