From 01d84c722150fb67bf2bc59bca1a5f227b8a135b Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 29 Oct 2019 01:12:15 -0400 Subject: [PATCH] wip lots of shared references --- src/can/mod.rs | 4 +- src/can/operator.rs | 148 ++++++++++++++++++++++++-------------------- 2 files changed, 84 insertions(+), 68 deletions(-) diff --git a/src/can/mod.rs b/src/can/mod.rs index 646c05f9a6..851a6b949f 100644 --- a/src/can/mod.rs +++ b/src/can/mod.rs @@ -55,7 +55,7 @@ pub fn canonicalize_declaration<'a>( // visited an Operator node we'd recursively try to apply this to each of its nested // operators, and thena again on *their* nested operators, ultimately applying the // rules multiple times unnecessarily. - let loc_expr = operator::desugar(arena, &loc_expr); + let loc_expr = operator::desugar(arena, loc_expr.value, loc_expr.region); // If we're canonicalizing the declaration `foo = ...` inside the `Main` module, // scope_prefix will be "Main.foo$" and its first closure will be named "Main.foo$0" @@ -1287,7 +1287,7 @@ fn can_defs<'a>( // Used in constraint generation let rigid_info = Info::with_capacity(defs.len()); let mut flex_info = Info::with_capacity(defs.len()); - let mut iter = defs.iter(); + let mut iter = defs.into_iter(); while let Some(loc_def) = iter.next() { // Each assignment gets to have all the idents in scope that are assigned in this diff --git a/src/can/operator.rs b/src/can/operator.rs index 33eb5df51e..f661402a97 100644 --- a/src/can/operator.rs +++ b/src/can/operator.rs @@ -33,11 +33,11 @@ fn new_op_expr<'a>( /// Reorder the expression tree based on operator precedence and associativity rules, /// then replace the Operator nodes with Apply nodes. Also drop SpaceBefore and SpaceAfter nodes. -pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Located> { +pub fn desugar<'a>(arena: &'a Bump, expr: Expr<'a>, region: Region) -> Located> { use operator::Associativity::*; use std::cmp::Ordering; - match &loc_expr.value { + match expr { Float(_) | Int(_) | HexInt(_) @@ -51,30 +51,33 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca | MalformedIdent(_) | MalformedClosure | PrecedenceConflict(_, _, _) - | Variant(_, _) => loc_expr, + | Variant(_, _) => Located { + value: expr, + region, + }, - Field(sub_expr, paths) => arena.alloc(Located { - region: loc_expr.region, - value: Field(desugar(arena, sub_expr), paths.clone()), - }), + Field(sub_expr, paths) => Located { + region, + value: Field( + arena.alloc(desugar(arena, sub_expr.value, sub_expr.region)), + paths.clone(), + ), + }, List(elems) => { let mut new_elems = Vec::with_capacity_in(elems.len(), arena); - for elem in elems { - new_elems.push(desugar(arena, elem)); + for loc_elem in elems.into_iter() { + new_elems.push(&*arena.alloc(desugar(arena, loc_elem.value, loc_elem.region))); } let value: Expr<'a> = List(new_elems); - arena.alloc(Located { - region: loc_expr.region, - value, - }) + Located { region, value } } Record(fields) => { let mut new_fields = Vec::with_capacity_in(fields.len(), arena); for field in fields { - let value = desugar_field(arena, &field.value); + let value = desugar_field(arena, field.value); new_fields.push(Located { value, @@ -82,17 +85,23 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca }); } - arena.alloc(Located { - region: loc_expr.region, + Located { + region, value: Record(new_fields), - }) + } } - Closure(loc_patterns, loc_ret) => arena.alloc(Located { - region: loc_expr.region, - value: Closure(loc_patterns, desugar(arena, loc_ret)), - }), + Closure(loc_patterns, loc_ret) => Located { + region, + value: Closure( + loc_patterns, + &*arena.alloc(desugar(arena, loc_ret.value, loc_ret.region)), + ), + }, Operator(_) => { - let mut infixes = Infixes::new(arena.alloc(loc_expr)); + let mut infixes = Infixes::new(arena.alloc(Located { + value: expr, + region, + })); let mut arg_stack: Vec<&'a Located> = Vec::new_in(arena); let mut op_stack: Vec> = Vec::new_in(arena); @@ -167,7 +176,7 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca arena.alloc(broken_expr), ); - return arena.alloc(Located { region, value }); + return Located { region, value }; } _ => { @@ -224,7 +233,7 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca assert_eq!(arg_stack.len(), 1); - arg_stack.pop().unwrap() + *arg_stack.pop().unwrap() } Defs(defs, loc_ret) => { @@ -232,30 +241,36 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca for loc_def in defs.into_iter() { let loc_def = &*arena.alloc(Located { - // TODO try to avoid this clone() if possible - value: desugar_def(arena, loc_def.value, loc_expr), + value: desugar_def(arena, loc_def.value), region: loc_def.region, }); desugared_defs.push(loc_def); } - arena.alloc(Located { - value: Defs(desugared_defs, desugar(arena, loc_ret)), - region: loc_expr.region, - }) + Located { + value: Defs( + desugared_defs, + &*arena.alloc(desugar(arena, loc_ret.value, loc_ret.region)), + ), + region, + } } Apply(loc_fn, loc_args, called_via) => { let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena); - for loc_arg in loc_args { - desugared_args.push(desugar(arena, loc_arg)); + for loc_arg in loc_args.into_iter() { + desugared_args.push(&*arena.alloc(desugar(arena, loc_arg.value, loc_arg.region))); } - arena.alloc(Located { - value: Apply(desugar(arena, loc_fn), desugared_args, called_via.clone()), - region: loc_expr.region, - }) + Located { + value: Apply( + arena.alloc(desugar(arena, loc_fn.value, loc_fn.region)), + desugared_args, + called_via.clone(), + ), + region, + } } // If(&'a (Loc>, Loc>, Loc>)), // Case( @@ -267,17 +282,15 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca // and should be dropped. desugar( arena, - arena.alloc(Located { - // TODO FIXME performance disaster!!! Must remove this clone! - // - // This won't be easy because: - // - // * If this function takes an &'a Expr, then Infixes hits a problem. - // * If SpaceBefore holds a Loc<&'a Expr>, then Spaceable hits a problem. - // * If all the existing &'a Loc values become Loc<&'a Expr>...who knows? - value: (*expr).clone(), - region: loc_expr.region, - }), + // TODO FIXME performance disaster!!! Must remove this clone! + // + // This won't be easy because: + // + // * If this function takes an &'a Expr, then Infixes hits a problem. + // * If SpaceBefore holds a Loc<&'a Expr>, then Spaceable hits a problem. + // * If all the existing &'a Loc values become Loc<&'a Expr>...who knows? + // (*expr).clone(), + *expr, region, ) } SpaceAfter(expr, _) => { @@ -285,44 +298,47 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located>) -> &'a Loca // and should be dropped. desugar( arena, - arena.alloc(Located { - // TODO FIXME performance disaster!!! Must remove this clone! (Not easy.) - value: (*expr).clone(), - region: loc_expr.region, - }), + // TODO FIXME performance disaster!!! Must remove this clone! (Not easy.) + // (*expr).clone(), + *expr, region, ) } other => panic!("TODO desugar {:?}", other), } } -fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>, loc_expr: &'a Located>) -> Def<'a> { +fn desugar_def<'a>(arena: &'a Bump, def: Def<'a>) -> Def<'a> { match def { - Def::Body(pattern, loc_expr) => Def::Body(pattern.clone(), desugar(arena, loc_expr)), + Def::Body(pattern, loc_expr) => Def::Body( + pattern, + arena.alloc(desugar(arena, loc_expr.value, loc_expr.region)), + ), Def::Annotation(_, _) => def, Def::CustomType(_, _) => def, Def::TypeAlias(_, _) => def, - Def::SpaceBefore(other_def, _) => desugar_def(arena, other_def, loc_expr), - Def::SpaceAfter(_, _) => def, + Def::SpaceBefore(other_def, _) | Def::SpaceAfter(other_def, _) => { + desugar_def(arena, *other_def) + } } } fn desugar_field<'a>( arena: &'a Bump, - field: &'a AssignedField<'a, Expr<'a>>, + field: AssignedField<'a, Expr<'a>>, ) -> AssignedField<'a, Expr<'a>> { use parse::ast::AssignedField::*; + match field { - LabeledValue(ref loc_str, spaces, loc_expr) => { - AssignedField::LabeledValue(loc_str.clone(), spaces, desugar(arena, loc_expr)) - } - LabelOnly(ref loc_str, spaces) => LabelOnly(loc_str.clone(), spaces), - SpaceBefore(ref field, spaces) => { - SpaceBefore(arena.alloc(desugar_field(arena, field)), spaces) - } - SpaceAfter(ref field, spaces) => { - SpaceAfter(arena.alloc(desugar_field(arena, field)), spaces) + LabeledValue(ref loc_str, spaces, loc_expr) => AssignedField::LabeledValue( + loc_str.clone(), + spaces, + arena.alloc(desugar(arena, loc_expr.value, loc_expr.region)), + ), + LabelOnly(loc_str, spaces) => LabelOnly(loc_str, spaces), + SpaceBefore(field, spaces) => { + SpaceBefore(arena.alloc(desugar_field(arena, *field)), spaces) } + SpaceAfter(field, spaces) => SpaceAfter(arena.alloc(desugar_field(arena, *field)), spaces), Malformed(string) => Malformed(string), }