Skip to content

Commit

Permalink
refactor: inline callable reference expr into reference expr (#41)
Browse files Browse the repository at this point in the history
Simplifies AST and we don't do this wonky substitution anymore.
  • Loading branch information
junlarsen authored Feb 7, 2025
1 parent cb3acf3 commit 0f5d593
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 438 deletions.
39 changes: 19 additions & 20 deletions compiler/eight-middle/src/ast_lowering_pass/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::context::CompileContext;
use crate::hir::{HirCallableSymbol, HirTy};
use crate::hir::{
HirConstructExprArgument, HirExpr, HirExprStmt, HirFunction, HirFunctionParameterSignature,
HirFunctionSignature, HirInstance, HirInstanceSignature, HirLetStmt, HirModule, HirModuleBody,
HirModuleSignature, HirStmt, HirStruct, HirStructFieldSignature, HirStructSignature, HirTrait,
HirTraitSignature, HirType, HirTypeParameterSignature, HirTypeSignature,
HirFunctionSignature, HirInstance, HirInstanceSignature, HirLetStmt, HirLocalReferenceSymbol,
HirModule, HirModuleBody, HirModuleSignature, HirStmt, HirStruct, HirStructFieldSignature,
HirStructSignature, HirTrait, HirTraitSignature, HirType, HirTypeParameterSignature,
HirTypeSignature,
};
use crate::hir::{HirReferenceSymbol, HirTy};
use crate::hir_builder::HirBuilder;
use crate::scope::Scope;
use crate::HirResult;
Expand Down Expand Up @@ -231,22 +232,19 @@ impl<'ast, 'hir> AstLoweringPass<'ast, 'hir> {
AstUnaryOp::Neg => ("Neg", "neg"),
_ => ice!("visit_unary_op called addressof or deref operator"),
};
let sym = HirCallableSymbol::new_trait_function(
let symbol = HirReferenceSymbol::new_trait_function(
trait_name,
node.op_span,
vec![],
function_name,
node.op_span,
vec![],
);
let callable_reference = HirBuilder::build_callable_reference_expr(
node.span,
sym,
self.cc.hir_uninitialized_type(),
);
let reference =
HirBuilder::build_reference_expr(node.span, self.cc.hir_uninitialized_type(), symbol);
Ok(HirExpr::Call(HirBuilder::build_call_expr(
node.span,
HirExpr::CallableReference(callable_reference),
HirExpr::Reference(reference),
vec![self.visit_expr(node.operand)?],
// There are no explicit type arguments provided, besides, as we mentioned above, there
// are no type parameters on these trait functions.
Expand Down Expand Up @@ -275,22 +273,19 @@ impl<'ast, 'hir> AstLoweringPass<'ast, 'hir> {
AstBinaryOp::And => ("And", "and"),
AstBinaryOp::Or => ("Or", "or"),
};
let sym = HirCallableSymbol::new_trait_function(
let symbol = HirReferenceSymbol::new_trait_function(
trait_name,
node.op_span,
vec![],
function_name,
node.op_span,
vec![],
);
let callable_reference = HirBuilder::build_callable_reference_expr(
node.span,
sym,
self.cc.hir_uninitialized_type(),
);
let reference =
HirBuilder::build_reference_expr(node.span, self.cc.hir_uninitialized_type(), symbol);
Ok(HirExpr::Call(HirBuilder::build_call_expr(
node.span,
HirExpr::CallableReference(callable_reference),
HirExpr::Reference(reference),
vec![self.visit_expr(node.lhs)?, self.visit_expr(node.rhs)?],
// There are no explicit type arguments provided, besides, as we mentioned above, there
// are no type parameters on these trait functions.
Expand Down Expand Up @@ -333,9 +328,13 @@ impl<'ast, 'hir> AstLoweringPass<'ast, 'hir> {
) -> HirResult<HirExpr<'hir>> {
Ok(HirExpr::Reference(HirBuilder::build_reference_expr(
node.span,
self.cc.intern_str(&node.name.name),
node.name.span,
self.cc.hir_uninitialized_type(),
// Assume that it is a local reference by default. The value here does not really matter
// as the type checker will replace this as it sees fit.
HirReferenceSymbol::Local(HirLocalReferenceSymbol {
name: self.cc.intern_str(&node.name.name),
name_span: node.name.span,
}),
)))
}

Expand Down
55 changes: 28 additions & 27 deletions compiler/eight-middle/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub enum HirExpr<'hir> {
BooleanLiteral(HirBooleanLiteralExpr<'hir>),
Assign(HirAssignExpr<'hir>),
Reference(HirReferenceExpr<'hir>),
CallableReference(HirCallableReferenceExpr<'hir>),
ConstantIndex(HirConstantIndexExpr<'hir>),
OffsetIndex(HirOffsetIndexExpr<'hir>),
Call(HirCallExpr<'hir>),
Expand All @@ -36,7 +35,6 @@ impl<'hir> HirExpr<'hir> {
HirExpr::Construct(e) => e.span,
HirExpr::Group(e) => e.span,
HirExpr::Reference(e) => e.span,
HirExpr::CallableReference(e) => e.span,
HirExpr::AddressOf(e) => e.span,
HirExpr::Deref(e) => e.span,
}
Expand All @@ -53,7 +51,6 @@ impl<'hir> HirExpr<'hir> {
HirExpr::Construct(e) => e.ty,
HirExpr::Group(e) => e.ty,
HirExpr::Reference(e) => e.ty,
HirExpr::CallableReference(e) => e.ty,
HirExpr::AddressOf(e) => e.ty,
HirExpr::Deref(e) => e.ty,
}
Expand Down Expand Up @@ -99,24 +96,16 @@ pub struct HirDerefExpr<'hir> {
#[derive(Debug)]
pub struct HirReferenceExpr<'hir> {
pub span: Span,
pub name: &'hir str,
pub name_span: Span,
/// The type of `name` in the current scope.
pub ty: &'hir HirTy<'hir>,
pub kind: HirReferenceSymbol<'hir>,
}

#[derive(Debug)]
pub struct HirCallableReferenceExpr<'hir> {
pub span: Span,
pub symbol: HirCallableSymbol<'hir>,
pub ty: &'hir HirTy<'hir>,
}

impl HirCallableSymbol<'_> {
impl HirReferenceSymbol<'_> {
/// Try to convert this callable reference into a compiler intrinsic.
#[rustfmt::skip]
pub fn get_compiler_intrinsic_candidate(&self) -> Option<CompilerIntrinsic> {
let HirCallableSymbol::TraitFunction(symbol) = self else {
let HirReferenceSymbol::TraitMethod(symbol) = self else {
return None
};
match (symbol.trait_name, symbol.method_name, symbol.method_type_arguments.as_slice()) {
Expand Down Expand Up @@ -144,21 +133,33 @@ impl HirCallableSymbol<'_> {
}
}

/// A reference to a callable symbol.
/// A reference to a symbol.
///
/// A callable symbol is a function or a trait instance's implementation of a trait function. This
/// distinction from [`HirReferenceExpr`] is important because it allows us to distinguish between
/// values in scope and function, as well as making the distinction between trait functions and
/// regular functions.
/// A reference can be resolved into one of four categories:
///
/// 1. Local variable
/// 2. Global function
/// 3. Trait method
/// 4. Compiler intrinsic
///
/// References are assumed to be local until proven otherwise. This simplifies things a bit by not
/// requiring to have an undecided variant.
#[derive(Debug)]
pub enum HirCallableSymbol<'hir> {
Function(HirFunctionCallableSymbol<'hir>),
TraitFunction(HirTraitFunctionCallableSymbol<'hir>),
pub enum HirReferenceSymbol<'hir> {
Local(HirLocalReferenceSymbol<'hir>),
Function(HirFunctionReferenceSymbol<'hir>),
TraitMethod(HirTraitMethodReferenceSymbol<'hir>),
Intrinsic(CompilerIntrinsic),
}

#[derive(Debug)]
pub struct HirFunctionCallableSymbol<'hir> {
pub struct HirLocalReferenceSymbol<'hir> {
pub name: &'hir str,
pub name_span: Span,
}

#[derive(Debug)]
pub struct HirFunctionReferenceSymbol<'hir> {
pub name: &'hir str,
pub name_span: Span,
/// The type arguments that the callable reference was instantiated with.
Expand All @@ -169,7 +170,7 @@ pub struct HirFunctionCallableSymbol<'hir> {
}

#[derive(Debug)]
pub struct HirTraitFunctionCallableSymbol<'hir> {
pub struct HirTraitMethodReferenceSymbol<'hir> {
pub trait_name: &'hir str,
pub trait_name_span: Span,
pub trait_type_arguments: Vec<&'hir HirTy<'hir>>,
Expand All @@ -179,13 +180,13 @@ pub struct HirTraitFunctionCallableSymbol<'hir> {
pub instantiated_call_parameters: Vec<&'hir HirTy<'hir>>,
}

impl<'hir> HirCallableSymbol<'hir> {
impl<'hir> HirReferenceSymbol<'hir> {
pub fn new_function(
name: &'hir str,
name_span: Span,
type_arguments: Vec<&'hir HirTy<'hir>>,
) -> Self {
Self::Function(HirFunctionCallableSymbol {
Self::Function(HirFunctionReferenceSymbol {
name,
name_span,
type_arguments,
Expand All @@ -201,7 +202,7 @@ impl<'hir> HirCallableSymbol<'hir> {
method_name_span: Span,
method_type_arguments: Vec<&'hir HirTy<'hir>>,
) -> Self {
Self::TraitFunction(HirTraitFunctionCallableSymbol {
Self::TraitMethod(HirTraitMethodReferenceSymbol {
trait_name,
trait_name_span,
trait_type_arguments,
Expand Down
20 changes: 3 additions & 17 deletions compiler/eight-middle/src/hir_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::hir::{
HirInstance, HirInstanceSignature, HirIntegerLiteralExpr, HirLetStmt, HirLoopStmt,
HirOffsetIndexExpr, HirReferenceExpr, HirReturnStmt, HirStmt, HirTrait, HirTraitSignature,
};
use crate::hir::{HirCallableReferenceExpr, HirCallableSymbol, HirTy};
use crate::hir::{HirReferenceSymbol, HirTy};
use crate::{HirResult, LinkageType};
use eight_span::Span;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -315,23 +315,9 @@ impl<'hir> HirBuilder {

pub fn build_reference_expr(
span: Span,
name: &'hir str,
name_span: Span,
ty: &'hir HirTy<'hir>,
kind: HirReferenceSymbol<'hir>,
) -> HirReferenceExpr<'hir> {
HirReferenceExpr {
span,
name,
name_span,
ty,
}
}

pub fn build_callable_reference_expr(
span: Span,
symbol: HirCallableSymbol<'hir>,
ty: &'hir HirTy<'hir>,
) -> HirCallableReferenceExpr<'hir> {
HirCallableReferenceExpr { span, symbol, ty }
HirReferenceExpr { span, ty, kind }
}
}
45 changes: 18 additions & 27 deletions compiler/eight-middle/src/hir_lowering_pass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::context::CompileContext;
use crate::hir::{
HirBooleanLiteralExpr, HirCallExpr, HirExpr, HirIntegerLiteralExpr, HirReferenceExpr,
};
use crate::hir::{HirCallableReferenceExpr, HirCallableSymbol, HirModule};
use crate::hir::{HirExprStmt, HirFunction, HirLetStmt, HirStmt};
use crate::hir::{HirGroupExpr, HirTy};
use crate::hir::{HirModule, HirReferenceSymbol};
use crate::mir::MirModule;
use crate::mir::MirTy;
use crate::mir::MirValueId;
Expand Down Expand Up @@ -167,7 +167,6 @@ impl<'hir, 'mir> MirModuleLoweringPass<'mir> {
match expr {
HirExpr::IntegerLiteral(e) => self.visit_integer_literal_expr(b, cx, e),
HirExpr::Reference(e) => self.visit_reference_expr(b, cx, e),
HirExpr::CallableReference(e) => self.visit_callable_reference_expr(b, cx, e),
HirExpr::Call(e) => self.visit_call_expr(b, cx, e),
HirExpr::BooleanLiteral(e) => self.visit_boolean_literal_expr(b, cx, e),
HirExpr::Group(e) => self.visit_group_expr(b, cx, e),
Expand Down Expand Up @@ -213,29 +212,21 @@ impl<'hir, 'mir> MirModuleLoweringPass<'mir> {
cx: &MirModuleContext<'mir, 'hir>,
expr: &'hir HirReferenceExpr<'hir>,
) -> MirResult<MirValueId> {
// Arguments can be used directly, but locals need to be loaded.
let id = self.locals.find(&expr.name).unwrap_or_else(|| {
ice!("failed to find local value for {}", expr.name);
});
let value_ty = b.data().get_value_type(*id);
let expected_ty = self.visit_ty(expr.ty)?;
// If it is a pointer type, we automatically dereference it.
if let MirTy::Pointer(_) = value_ty {
let load = b.build_load(cx, *id, expected_ty, None);
return Ok(load);
}
Ok(*id)
}

pub fn visit_callable_reference_expr(
&mut self,
b: &mut MirFunctionBuilder<'mir>,
cx: &MirModuleContext<'mir, 'hir>,
expr: &'hir HirCallableReferenceExpr<'hir>,
) -> MirResult<MirValueId> {
match &expr.symbol {
// If this is a simple function name, we can lower it to a specific function value.
HirCallableSymbol::Function(symbol) => {
match &expr.kind {
HirReferenceSymbol::Local(local) => {
let id = self.locals.find(&local.name).unwrap_or_else(|| {
ice!("failed to find local value for {}", local.name);
});
let value_ty = b.data().get_value_type(*id);
let expected_ty = self.visit_ty(expr.ty)?;
// If it is a pointer type, we automatically dereference it.
if let MirTy::Pointer(_) = value_ty {
let load = b.build_load(cx, *id, expected_ty, None);
return Ok(load);
}
Ok(*id)
}
HirReferenceSymbol::Function(symbol) => {
// TODO: Mangle the name along with the type arguments.
let name = self.cc.intern_str(symbol.name);
let id = cx.data().get_function_id(name).unwrap_or_else(|| {
Expand All @@ -246,8 +237,8 @@ impl<'hir, 'mir> MirModuleLoweringPass<'mir> {
});
Ok(b.build_function_ref(id))
}
HirCallableSymbol::TraitFunction(_) => unimplemented!(),
HirCallableSymbol::Intrinsic(_) => unimplemented!(),
HirReferenceSymbol::Intrinsic(_) => unimplemented!(),
HirReferenceSymbol::TraitMethod(_) => unimplemented!(),
}
}

Expand Down
23 changes: 8 additions & 15 deletions compiler/eight-middle/src/hir_textual_pass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
//! invents syntax not found in the base language, such as statement blocks and while loops.
use crate::hir::{
HirAddressOfExpr, HirAssignExpr, HirBooleanLiteralExpr, HirCallExpr, HirCallableReferenceExpr,
HirCallableSymbol, HirConstantIndexExpr, HirConstructExpr, HirConstructExprArgument,
HirDerefExpr, HirExpr, HirFunction, HirGroupExpr, HirInstance, HirIntegerLiteralExpr, HirOffsetIndexExpr, HirReferenceExpr,
HirAddressOfExpr, HirAssignExpr, HirBooleanLiteralExpr, HirCallExpr, HirConstantIndexExpr,
HirConstructExpr, HirConstructExprArgument, HirDerefExpr, HirExpr, HirFunction, HirGroupExpr,
HirInstance, HirIntegerLiteralExpr, HirOffsetIndexExpr, HirReferenceExpr, HirReferenceSymbol,
};
use crate::hir::{
HirBlockStmt, HirBreakStmt, HirContinueStmt, HirExprStmt, HirFunctionParameterSignature,
Expand Down Expand Up @@ -577,7 +577,6 @@ impl<'a> HirModuleTextualPass<'a> {
HirExpr::BooleanLiteral(e) => self.visit_boolean_literal_expr(e),
HirExpr::Assign(e) => self.visit_assign_expr(e),
HirExpr::Reference(e) => self.visit_reference_expr(e),
HirExpr::CallableReference(e) => self.visit_callable_reference_expr(e),
HirExpr::ConstantIndex(e) => self.visit_constant_index_expr(e),
HirExpr::OffsetIndex(e) => self.visit_offset_index_expr(e),
HirExpr::Call(e) => self.visit_call_expr(e),
Expand Down Expand Up @@ -623,15 +622,9 @@ impl<'a> HirModuleTextualPass<'a> {
&'a self,
expr: &'hir HirReferenceExpr,
) -> DocBuilder<'a, Arena<'a>> {
self.arena.text(expr.name)
}

pub fn visit_callable_reference_expr<'hir: 'a>(
&'a self,
expr: &'hir HirCallableReferenceExpr,
) -> DocBuilder<'a, Arena<'a>> {
match &expr.symbol {
HirCallableSymbol::Function(s) => self
match &expr.kind {
HirReferenceSymbol::Local(s) => self.arena.text(s.name),
HirReferenceSymbol::Function(s) => self
.arena
.text(s.name)
.append(self.arena.text("::"))
Expand All @@ -641,7 +634,7 @@ impl<'a> HirModuleTextualPass<'a> {
self.arena.text(","),
))
.append(self.arena.text(">")),
HirCallableSymbol::TraitFunction(s) => self
HirReferenceSymbol::TraitMethod(s) => self
.arena
.text(s.trait_name)
.append(self.arena.text("<"))
Expand All @@ -659,7 +652,7 @@ impl<'a> HirModuleTextualPass<'a> {
self.arena.text(","),
))
.append(self.arena.text(">")),
HirCallableSymbol::Intrinsic(intrinsic) => self.arena.text(intrinsic.to_string()),
HirReferenceSymbol::Intrinsic(intrinsic) => self.arena.text(intrinsic.to_string()),
}
}

Expand Down
Loading

0 comments on commit 0f5d593

Please sign in to comment.