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

Commit

Permalink
Simplify cloning (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavrilikhin-d authored May 1, 2024
1 parent 168c553 commit ac3f009
Show file tree
Hide file tree
Showing 31 changed files with 624 additions and 444 deletions.
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

0 comments on commit ac3f009

Please sign in to comment.