wip lots of shared references

This commit is contained in:
Richard Feldman 2019-10-29 01:12:15 -04:00
parent 4894293e6b
commit 01d84c7221
2 changed files with 84 additions and 68 deletions

View file

@ -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

View file

@ -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<Expr<'a>>) -> &'a Located<Expr<'a>> {
pub fn desugar<'a>(arena: &'a Bump, expr: Expr<'a>, region: Region) -> Located<Expr<'a>> {
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<Expr<'a>>) -> &'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<Expr<'a>>) -> &'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<Expr>> = Vec::new_in(arena);
let mut op_stack: Vec<Located<Operator>> = Vec::new_in(arena);
@ -167,7 +176,7 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'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<Expr<'a>>) -> &'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<Expr<'a>>) -> &'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<Expr<'a>>, Loc<Expr<'a>>, Loc<Expr<'a>>)),
// Case(
@ -267,17 +282,15 @@ pub fn desugar<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'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<Expr> 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<Expr> 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<Expr<'a>>) -> &'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<Expr<'a>>) -> 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),
}