Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Simplify cloning #147

Merged
merged 1 commit into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/compilation/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use indexmap::IndexMap;
use crate::{
ast,
hir::{ClassData, FunctionData, ModuleData, TraitData},
semantics::{InsertDestructors, ModuleContext, ParameterNamer, TemporariesInserter, ToHIR},
semantics::{
clone::Clonner, InsertDestructors, ModuleContext, ParameterNamer, TemporariesInserter,
ToHIR,
},
SourceFile,
};
use log::{debug, trace};
Expand Down Expand Up @@ -220,11 +223,12 @@ impl Compiler {
.map_err(|e| miette::Report::from(e).with_source_code(source_file))?;
debug!(target: &format!("{name}-hir"), "\n{:#}", hir);

trace!(target: "steps", "Inserting destructors `{}`", path.display());
trace!(target: "steps", "Running passes on `{}`", path.display());
hir.drive_mut(&mut ParameterNamer::new());
hir.drive_mut(&mut Clonner::new(&mut context));
hir.drive_mut(&mut TemporariesInserter::new());
hir.insert_destructors(&mut context);
debug!(target: &format!("{name}-hir-with-destructors"), "\n{:#}", hir);
debug!(target: &format!("{name}-hir-after-passes"), "\n{:#}", hir);

self.modules[module.index()] = hir;

Expand Down
94 changes: 65 additions & 29 deletions src/semantics/clone.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,82 @@
use derive_visitor::VisitorMut;

use crate::{
hir::{Call, Expression, Typed},
hir::{
Assignment, Call, Expression, ImplicitConversion, ImplicitConversionKind, Initializer,
Return, Typed, VariableData,
},
syntax::Ranged,
};

use super::Context;

pub trait CloneIfNeeded: Sized {
fn clone_if_needed_inplace(&mut self, context: &mut impl Context);
#[derive(VisitorMut)]
#[visitor(
Assignment(exit),
Return(exit),
Initializer(exit),
Call(exit),
VariableData(exit)
)]
pub struct Clonner<'ctx> {
context: &'ctx mut dyn Context,
}

fn clone_if_needed(mut self, context: &mut impl Context) -> Self {
self.clone_if_needed_inplace(context);
self
impl<'ctx> Clonner<'ctx> {
pub fn new(context: &'ctx mut dyn Context) -> Self {
Self { context }
}
}

impl CloneIfNeeded for Expression {
fn clone_if_needed_inplace(&mut self, context: &mut impl Context) {
fn clone_expr(&mut self, expr: &mut Expression) -> Option<()> {
if !matches!(
self,
Expression::ImplicitConversion(_)
| Expression::VariableReference(_)
expr,
Expression::VariableReference(_)
| Expression::MemberReference(_)
) || self.ty().is_any_reference()
{
return;
| Expression::ImplicitConversion(ImplicitConversion {
kind: ImplicitConversionKind::Dereference,
..
})
) {
return None;
}

if let Some(clone) = context.clone_for(self.ty()) {
let mut expr: Expression = Call {
range: self.range(),
function: clone,
generic: None,
args: vec![],
}
.into();
std::mem::swap(&mut expr, self);
match self {
Expression::Call(call) => {
call.args.push(expr);
}
_ => unreachable!("We've just replaced self with call"),
let clone = self.context.clone_for(expr.ty())?;
let mut expr_new: Expression = Call {
range: expr.range(),
function: clone,
generic: None,
args: vec![],
}
.into();
std::mem::swap(&mut expr_new, expr);
match expr {
Expression::Call(call) => {
call.args.push(expr_new);
}
_ => unreachable!("We've just replaced self with call"),
}
Some(())
}

fn exit_variable_data(&mut self, var: &mut VariableData) {
var.initializer.as_mut().map(|expr| self.clone_expr(expr));
}

fn exit_assignment(&mut self, assignment: &mut Assignment) {
self.clone_expr(&mut assignment.value);
}

fn exit_return(&mut self, ret: &mut Return) {
ret.value_mut().map(|expr| self.clone_expr(expr));
}

fn exit_initializer(&mut self, init: &mut Initializer) {
self.clone_expr(&mut init.value);
}

fn exit_call(&mut self, call: &mut Call) {
for arg in &mut call.args {
self.clone_expr(arg);
}
}
}
5 changes: 1 addition & 4 deletions src/semantics/contexts/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ pub trait Context: FindDeclaration + AddDeclaration + Display {
}

/// Find clone function for type
fn clone_for(&mut self, ty: Type) -> Option<Function>
where
Self: Sized,
{
fn clone_for(&mut self, ty: Type) -> Option<Function> {
let name = format!("clone <:{ty}>");
self.function_with_name(&name)
}
Expand Down
3 changes: 1 addition & 2 deletions src/semantics/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::{
};

use super::{
clone::CloneIfNeeded,
error::{NotConvertible, NotImplemented, TypeMismatch, TypeWithSpan},
Context, Implements, Implicit,
};
Expand Down Expand Up @@ -315,7 +314,7 @@ impl ConversionRequest {
}

if !from.is_any_reference() && !to.is_any_reference() {
return Ok(self.from.value.clone_if_needed(context));
return Ok(self.from.value);
}

if from.is_any_reference() {
Expand Down
8 changes: 2 additions & 6 deletions src/semantics/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::{
};

use super::{
clone::CloneIfNeeded,
error::{CantDeduceReturnType, Error, ReturnTypeMismatch},
Context, Convert, ConvertibleTo, FunctionContext, GenericContext, Monomorphize, ToHIR,
TraitContext,
Expand Down Expand Up @@ -131,10 +130,7 @@ impl Declare for ast::FunctionDeclaration {
}
.into());
}
body = vec![hir::Return::Implicit {
value: expr.clone_if_needed(context),
}
.into()];
body = vec![hir::Return::Implicit { value: expr }.into()];
}

declaration.write().unwrap().body = body;
Expand Down Expand Up @@ -295,7 +291,7 @@ impl Declare for ast::VariableDeclaration {
declaration.write().unwrap().initializer = Some(initializer)
} else {
declaration.write().unwrap().ty = initializer.ty();
declaration.write().unwrap().initializer = Some(initializer.clone_if_needed(context));
declaration.write().unwrap().initializer = Some(initializer);
}

Ok(declaration)
Expand Down
22 changes: 4 additions & 18 deletions src/semantics/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
semantics::{ConvertibleTo, GenericContext},
};

use super::{clone::CloneIfNeeded, Context, ReplaceWithTypeInfo};
use super::{Context, ReplaceWithTypeInfo};

/// Trait to get monomorphized version of statements
pub trait Monomorphize {
Expand Down Expand Up @@ -80,7 +80,7 @@ impl Monomorphize for Variable {

impl Monomorphize for Assignment {
fn monomorphize(&mut self, context: &mut impl Context) {
self.target.monomorphize_without_clonning(context);
self.target.monomorphize(context);
self.value.monomorphize(context);
}
}
Expand Down Expand Up @@ -146,12 +146,8 @@ impl Monomorphize for ImplicitConversion {
}
}

trait MonomorphizeWithoutClonning {
fn monomorphize_without_clonning(&mut self, context: &mut impl Context);
}

impl MonomorphizeWithoutClonning for Expression {
fn monomorphize_without_clonning(&mut self, context: &mut impl Context) {
impl Monomorphize for Expression {
fn monomorphize(&mut self, context: &mut impl Context) {
match self {
Expression::Call(c) => c.monomorphize(context),
Expression::VariableReference(var) => var.monomorphize(context),
Expand All @@ -167,16 +163,6 @@ impl MonomorphizeWithoutClonning for Expression {
}
}

impl Monomorphize for Expression {
fn monomorphize(&mut self, context: &mut impl Context) {
let was_generic = self.is_generic();
self.monomorphize_without_clonning(context);
if was_generic && !self.is_generic() {
self.clone_if_needed_inplace(context);
}
}
}

impl Monomorphize for Constructor {
fn monomorphize(&mut self, context: &mut impl Context) {
if !self.is_generic() {
Expand Down
2 changes: 1 addition & 1 deletion src/tests/snapshots/ppl__tests__array.hir.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ push 1 to (&arr:ReferenceMut<Array<Integer>>)
if (&arr:ReferenceMut<Array<Integer>>) is not empty:
println "Not empty"

println (*(&arr:ReferenceMut<Array<Integer>>) [ 0 ]:Integer)
println clone (*(&arr:ReferenceMut<Array<Integer>>) [ 0 ]:Integer)
Loading
Loading