mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
add (Typed) Body
This commit is contained in:
parent
4d692af639
commit
35137d2542
6 changed files with 405 additions and 21 deletions
|
@ -204,9 +204,9 @@ pub enum Expr2 {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ValueDef {
|
pub struct ValueDef {
|
||||||
pattern: PatternId, // 4B
|
pub pattern: PatternId, // 4B
|
||||||
expr_type: Option<(TypeId, Rigids)>, // ?
|
pub expr_type: Option<(TypeId, Rigids)>, // ?
|
||||||
expr_var: Variable, // 4B
|
pub expr_var: Variable, // 4B
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShallowClone for ValueDef {
|
impl ShallowClone for ValueDef {
|
||||||
|
@ -229,11 +229,13 @@ pub enum FunctionDef {
|
||||||
arguments: PoolVec<(Pattern2, Type2)>, // 8B
|
arguments: PoolVec<(Pattern2, Type2)>, // 8B
|
||||||
rigids: NodeId<Rigids>, // 4B
|
rigids: NodeId<Rigids>, // 4B
|
||||||
return_type: TypeId, // 4B
|
return_type: TypeId, // 4B
|
||||||
|
body: ExprId, // 4B
|
||||||
},
|
},
|
||||||
NoAnnotation {
|
NoAnnotation {
|
||||||
name: Symbol, // 8B
|
name: Symbol, // 8B
|
||||||
arguments: PoolVec<(Pattern2, Variable)>, // 8B
|
arguments: PoolVec<(Pattern2, Variable)>, // 8B
|
||||||
return_var: Variable, // 4B
|
return_var: Variable, // 4B
|
||||||
|
body: ExprId, // 4B
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,21 +247,25 @@ impl ShallowClone for FunctionDef {
|
||||||
arguments,
|
arguments,
|
||||||
rigids,
|
rigids,
|
||||||
return_type,
|
return_type,
|
||||||
|
body,
|
||||||
} => Self::WithAnnotation {
|
} => Self::WithAnnotation {
|
||||||
name: *name,
|
name: *name,
|
||||||
arguments: arguments.shallow_clone(),
|
arguments: arguments.shallow_clone(),
|
||||||
rigids: *rigids,
|
rigids: *rigids,
|
||||||
return_type: *return_type,
|
return_type: *return_type,
|
||||||
|
body: *body,
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::NoAnnotation {
|
Self::NoAnnotation {
|
||||||
name,
|
name,
|
||||||
arguments,
|
arguments,
|
||||||
return_var,
|
return_var,
|
||||||
|
body,
|
||||||
} => Self::NoAnnotation {
|
} => Self::NoAnnotation {
|
||||||
name: *name,
|
name: *name,
|
||||||
arguments: arguments.shallow_clone(),
|
arguments: arguments.shallow_clone(),
|
||||||
return_var: *return_var,
|
return_var: *return_var,
|
||||||
|
body: *body,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,15 @@
|
||||||
// };
|
// };
|
||||||
// use crate::pattern::{bindings_from_patterns, canonicalize_pattern, Pattern};
|
// use crate::pattern::{bindings_from_patterns, canonicalize_pattern, Pattern};
|
||||||
// use crate::procedure::References;
|
// use crate::procedure::References;
|
||||||
use crate::ast::{FunctionDef, Rigids, ValueDef};
|
use crate::ast::{Expr2, FunctionDef, Rigids, ValueDef};
|
||||||
use crate::expr::Env;
|
use crate::expr::Output;
|
||||||
|
use crate::expr::{to_expr2, to_expr_id, Env};
|
||||||
use crate::pattern::{
|
use crate::pattern::{
|
||||||
symbols_and_variables_from_pattern, symbols_from_pattern, to_pattern_id, Pattern2, PatternId,
|
symbols_and_variables_from_pattern, symbols_from_pattern, to_pattern_id, Pattern2, PatternId,
|
||||||
};
|
};
|
||||||
use crate::pool::{NodeId, Pool, PoolStr, PoolVec, ShallowClone};
|
use crate::pool::{NodeId, Pool, PoolStr, PoolVec, ShallowClone};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use crate::types::{to_annotation2, Alias, Annotation2, References, Signature, Type2, TypeId};
|
use crate::types::{to_annotation2, Alias, Annotation2, Signature, Type2, TypeId};
|
||||||
use roc_can::expr::Output;
|
|
||||||
use roc_collections::all::{default_hasher, ImMap, ImSet, MutMap, MutSet, SendMap};
|
use roc_collections::all::{default_hasher, ImMap, ImSet, MutMap, MutSet, SendMap};
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
@ -425,6 +425,346 @@ fn canonicalize_pending_def<'a>(
|
||||||
// invalid aliases (shadowed, incorrect patterns )
|
// invalid aliases (shadowed, incorrect patterns )
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
|
||||||
|
TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr) => {
|
||||||
|
match to_annotation2(env, scope, &loc_ann.value, loc_ann.region) {
|
||||||
|
Annotation2::Erroneous(_) => todo!(),
|
||||||
|
Annotation2::Annotation {
|
||||||
|
named_rigids,
|
||||||
|
unnamed_rigids,
|
||||||
|
symbols,
|
||||||
|
signature,
|
||||||
|
} => {
|
||||||
|
// Record all the annotation's references in output.references.lookups
|
||||||
|
|
||||||
|
for symbol in symbols {
|
||||||
|
output.references.lookups.insert(symbol);
|
||||||
|
output.references.referenced_aliases.insert(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rigids = {
|
||||||
|
let named = PoolVec::with_capacity(named_rigids.len() as u32, env.pool);
|
||||||
|
let unnamed = PoolVec::with_capacity(unnamed_rigids.len() as u32, env.pool);
|
||||||
|
|
||||||
|
for (node_id, (name, variable)) in named.iter_node_ids().zip(named_rigids) {
|
||||||
|
let poolstr = PoolStr::new(name, env.pool);
|
||||||
|
env.pool[node_id] = (poolstr, variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_id, rigid) in unnamed.iter_node_ids().zip(unnamed_rigids) {
|
||||||
|
env.pool[node_id] = rigid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rigids { named, unnamed }
|
||||||
|
};
|
||||||
|
|
||||||
|
// bookkeeping for tail-call detection. If we're assigning to an
|
||||||
|
// identifier (e.g. `f = \x -> ...`), then this symbol can be tail-called.
|
||||||
|
let outer_identifier = env.tailcallable_symbol;
|
||||||
|
|
||||||
|
if let Pattern2::Identifier(ref defined_symbol) = env.pool[loc_can_pattern] {
|
||||||
|
env.tailcallable_symbol = Some(*defined_symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
// regiser the name of this closure, to make sure the closure won't capture it's own name
|
||||||
|
if let (Pattern2::Identifier(ref defined_symbol), &ast::Expr::Closure(_, _)) =
|
||||||
|
(&env.pool[loc_can_pattern], &loc_expr.value)
|
||||||
|
{
|
||||||
|
env.closure_name_symbol = Some(*defined_symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
let (loc_can_expr, can_output) =
|
||||||
|
to_expr2(env, scope, &loc_expr.value, loc_expr.region);
|
||||||
|
|
||||||
|
output.references.union_mut(can_output.references.clone());
|
||||||
|
|
||||||
|
// reset the tailcallable_symbol
|
||||||
|
env.tailcallable_symbol = outer_identifier;
|
||||||
|
|
||||||
|
// First, make sure we are actually assigning an identifier instead of (for example) a tag.
|
||||||
|
//
|
||||||
|
// If we're assigning (UserId userId) = ... then this is certainly not a closure declaration,
|
||||||
|
// which also implies it's not a self tail call!
|
||||||
|
//
|
||||||
|
// Only defs of the form (foo = ...) can be closure declarations or self tail calls.
|
||||||
|
match loc_can_expr {
|
||||||
|
Expr2::Closure {
|
||||||
|
args: closure_args,
|
||||||
|
body,
|
||||||
|
extra,
|
||||||
|
name: closure_symbol,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let symbol = match env.pool[loc_can_pattern] {
|
||||||
|
Pattern2::Identifier(ref s) => *s,
|
||||||
|
_ => todo!(
|
||||||
|
r"this is an error; functions must be bound with an identifier pattern!"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Since everywhere in the code it'll be referred to by its defined name,
|
||||||
|
// remove its generated name from the closure map.
|
||||||
|
let references =
|
||||||
|
env.closures.remove(&closure_symbol).unwrap_or_else(|| {
|
||||||
|
panic!( r"Tried to remove symbol {:?} from procedures, but it was not found: {:?}", closure_symbol, env.closures)
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO should we re-insert this function into env.closures?
|
||||||
|
env.closures.insert(symbol, references);
|
||||||
|
|
||||||
|
// Recursion doesn't count as referencing. (If it did, all recursive functions
|
||||||
|
// would result in circular def errors!)
|
||||||
|
refs_by_symbol.entry(symbol).and_modify(|(_, refs)| {
|
||||||
|
refs.lookups.remove(&symbol);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Functions' references don't count in defs.
|
||||||
|
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
||||||
|
// parent commit for the bug this fixed!
|
||||||
|
let refs = References::new();
|
||||||
|
|
||||||
|
let arguments: PoolVec<(Pattern2, Type2)> =
|
||||||
|
PoolVec::with_capacity(closure_args.len() as u32, env.pool);
|
||||||
|
|
||||||
|
let return_type: TypeId;
|
||||||
|
|
||||||
|
let annotation = match signature {
|
||||||
|
Signature::Value { .. } => {
|
||||||
|
todo!("type annotation says 0 arguments, but it's a function")
|
||||||
|
}
|
||||||
|
Signature::Function {
|
||||||
|
arguments: type_arguments,
|
||||||
|
closure_type_id,
|
||||||
|
return_type_id,
|
||||||
|
}
|
||||||
|
| Signature::FunctionWithAliases {
|
||||||
|
arguments: type_arguments,
|
||||||
|
closure_type_id,
|
||||||
|
return_type_id,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if arguments.len() != type_arguments.len() {
|
||||||
|
panic!("argument number mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
let it: Vec<_> = closure_args
|
||||||
|
.iter(env.pool)
|
||||||
|
.map(|(x, y)| (*x, *y))
|
||||||
|
.zip(
|
||||||
|
type_arguments
|
||||||
|
.iter(env.pool)
|
||||||
|
.map(|t| t.shallow_clone()),
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (node_id, ((_, pattern_id), typ)) in
|
||||||
|
arguments.iter_node_ids().zip(it.into_iter())
|
||||||
|
{
|
||||||
|
let pattern = &env.pool[pattern_id];
|
||||||
|
|
||||||
|
env.pool[node_id] = (pattern.shallow_clone(), typ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_type = return_type_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let function_def = FunctionDef::WithAnnotation {
|
||||||
|
name: symbol,
|
||||||
|
arguments,
|
||||||
|
rigids: env.pool.add(rigids),
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
};
|
||||||
|
|
||||||
|
let def = Def::Function(function_def);
|
||||||
|
|
||||||
|
can_defs_by_symbol.insert(symbol, def);
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
let annotation = match signature {
|
||||||
|
Signature::Value { annotation } => annotation,
|
||||||
|
Signature::Function {
|
||||||
|
arguments,
|
||||||
|
closure_type_id,
|
||||||
|
return_type_id,
|
||||||
|
} => Type2::Function(arguments, closure_type_id, return_type_id),
|
||||||
|
Signature::FunctionWithAliases { annotation, .. } => annotation,
|
||||||
|
};
|
||||||
|
let annotation = env.add(annotation, loc_ann.region);
|
||||||
|
|
||||||
|
let value_def = ValueDef {
|
||||||
|
pattern: loc_can_pattern,
|
||||||
|
expr_type: Some((annotation, rigids)),
|
||||||
|
expr_var: env.var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let def = Def::Value(value_def);
|
||||||
|
|
||||||
|
for symbol in
|
||||||
|
symbols_from_pattern(env.pool, env.pool.get(loc_can_pattern))
|
||||||
|
{
|
||||||
|
can_defs_by_symbol.insert(symbol, def.shallow_clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, (symbol, region)) in scope.idents() {
|
||||||
|
// if !vars_by_symbol.contains_key(&symbol) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
let refs = can_output.references.clone();
|
||||||
|
refs_by_symbol.insert(*symbol, (*region, refs));
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Body(loc_pattern, loc_can_pattern, loc_expr) => {
|
||||||
|
// bookkeeping for tail-call detection. If we're assigning to an
|
||||||
|
// identifier (e.g. `f = \x -> ...`), then this symbol can be tail-called.
|
||||||
|
let outer_identifier = env.tailcallable_symbol;
|
||||||
|
|
||||||
|
if let Pattern2::Identifier(ref defined_symbol) = env.pool[loc_can_pattern] {
|
||||||
|
env.tailcallable_symbol = Some(*defined_symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
// regiser the name of this closure, to make sure the closure won't capture it's own name
|
||||||
|
if let (Pattern2::Identifier(ref defined_symbol), &ast::Expr::Closure(_, _)) =
|
||||||
|
(&env.pool[loc_can_pattern], &loc_expr.value)
|
||||||
|
{
|
||||||
|
env.closure_name_symbol = Some(*defined_symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
let (loc_can_expr, can_output) = to_expr2(env, scope, &loc_expr.value, loc_expr.region);
|
||||||
|
|
||||||
|
output.references.union_mut(can_output.references.clone());
|
||||||
|
|
||||||
|
// reset the tailcallable_symbol
|
||||||
|
env.tailcallable_symbol = outer_identifier;
|
||||||
|
|
||||||
|
// First, make sure we are actually assigning an identifier instead of (for example) a tag.
|
||||||
|
//
|
||||||
|
// If we're assigning (UserId userId) = ... then this is certainly not a closure declaration,
|
||||||
|
// which also implies it's not a self tail call!
|
||||||
|
//
|
||||||
|
// Only defs of the form (foo = ...) can be closure declarations or self tail calls.
|
||||||
|
match loc_can_expr {
|
||||||
|
Expr2::Closure {
|
||||||
|
args: closure_args,
|
||||||
|
body,
|
||||||
|
extra,
|
||||||
|
name: closure_symbol,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let symbol = match env.pool[loc_can_pattern] {
|
||||||
|
Pattern2::Identifier(ref s) => *s,
|
||||||
|
_ => todo!(
|
||||||
|
r"this is an error; functions must be bound with an identifier pattern!"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Since everywhere in the code it'll be referred to by its defined name,
|
||||||
|
// remove its generated name from the closure map.
|
||||||
|
let references =
|
||||||
|
env.closures.remove(&closure_symbol).unwrap_or_else(|| {
|
||||||
|
panic!( r"Tried to remove symbol {:?} from procedures, but it was not found: {:?}", closure_symbol, env.closures)
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO should we re-insert this function into env.closures?
|
||||||
|
env.closures.insert(symbol, references);
|
||||||
|
|
||||||
|
// Recursion doesn't count as referencing. (If it did, all recursive functions
|
||||||
|
// would result in circular def errors!)
|
||||||
|
refs_by_symbol.entry(symbol).and_modify(|(_, refs)| {
|
||||||
|
refs.lookups.remove(&symbol);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Functions' references don't count in defs.
|
||||||
|
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
||||||
|
// parent commit for the bug this fixed!
|
||||||
|
let refs = References::new();
|
||||||
|
|
||||||
|
let arguments: PoolVec<(Pattern2, Variable)> =
|
||||||
|
PoolVec::with_capacity(closure_args.len() as u32, env.pool);
|
||||||
|
|
||||||
|
let it: Vec<_> = closure_args.iter(env.pool).map(|(x, y)| (*x, *y)).collect();
|
||||||
|
|
||||||
|
for (node_id, (_, pattern_id)) in arguments.iter_node_ids().zip(it.into_iter())
|
||||||
|
{
|
||||||
|
let pattern = &env.pool[pattern_id];
|
||||||
|
|
||||||
|
env.pool[node_id] = (pattern.shallow_clone(), env.var_store.fresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_def = FunctionDef::NoAnnotation {
|
||||||
|
name: symbol,
|
||||||
|
arguments,
|
||||||
|
return_var: env.var_store.fresh(),
|
||||||
|
body,
|
||||||
|
};
|
||||||
|
|
||||||
|
let def = Def::Function(function_def);
|
||||||
|
|
||||||
|
can_defs_by_symbol.insert(symbol, def);
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
let value_def = ValueDef {
|
||||||
|
pattern: loc_can_pattern,
|
||||||
|
expr_type: None,
|
||||||
|
expr_var: env.var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let def = Def::Value(value_def);
|
||||||
|
|
||||||
|
for symbol in symbols_from_pattern(env.pool, env.pool.get(loc_can_pattern)) {
|
||||||
|
can_defs_by_symbol.insert(symbol, def.shallow_clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, (symbol, region)) in scope.idents() {
|
||||||
|
// if !vars_by_symbol.contains_key(&symbol) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
let refs = can_output.references.clone();
|
||||||
|
refs_by_symbol.insert(*symbol, (*region, refs));
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
|
pub struct References {
|
||||||
|
pub bound_symbols: MutSet<Symbol>,
|
||||||
|
pub lookups: MutSet<Symbol>,
|
||||||
|
pub referenced_aliases: MutSet<Symbol>,
|
||||||
|
pub calls: MutSet<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl References {
|
||||||
|
pub fn new() -> References {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn union_mut(&mut self, other: References) {
|
||||||
|
self.lookups.extend(other.lookups);
|
||||||
|
self.calls.extend(other.calls);
|
||||||
|
self.bound_symbols.extend(other.bound_symbols);
|
||||||
|
self.referenced_aliases.extend(other.referenced_aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_lookup(&self, symbol: Symbol) -> bool {
|
||||||
|
self.lookups.contains(&symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,15 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
use crate::ast::{Expr2, ExprId, FloatVal, IntStyle, IntVal};
|
use crate::ast::{Expr2, ExprId, FloatVal, IntStyle, IntVal};
|
||||||
|
use crate::def::References;
|
||||||
use crate::pattern::to_pattern2;
|
use crate::pattern::to_pattern2;
|
||||||
use crate::pool::{NodeId, Pool, PoolStr, PoolVec};
|
use crate::pool::{NodeId, Pool, PoolStr, PoolVec};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use crate::types::{Type2, TypeId};
|
use crate::types::{Type2, TypeId};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inlinable_string::InlinableString;
|
use inlinable_string::InlinableString;
|
||||||
use roc_can::expr::Output;
|
|
||||||
use roc_can::expr::Recursive;
|
use roc_can::expr::Recursive;
|
||||||
use roc_can::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
use roc_can::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
||||||
use roc_can::procedure::References;
|
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::operator::CalledVia;
|
use roc_module::operator::CalledVia;
|
||||||
|
@ -21,6 +20,27 @@ use roc_problem::can::{Problem, RuntimeError};
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::subs::{VarStore, Variable};
|
use roc_types::subs::{VarStore, Variable};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq)]
|
||||||
|
pub struct Output {
|
||||||
|
pub references: crate::def::References,
|
||||||
|
pub tail_call: Option<Symbol>,
|
||||||
|
pub aliases: MutMap<Symbol, NodeId<crate::types::Alias>>,
|
||||||
|
pub non_closures: MutSet<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Output {
|
||||||
|
pub fn union(&mut self, other: Self) {
|
||||||
|
self.references.union_mut(other.references);
|
||||||
|
|
||||||
|
if let (None, Some(later)) = (self.tail_call, other.tail_call) {
|
||||||
|
self.tail_call = Some(later);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.aliases.extend(other.aliases);
|
||||||
|
self.non_closures.extend(other.non_closures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Env<'a> {
|
pub struct Env<'a> {
|
||||||
pub home: ModuleId,
|
pub home: ModuleId,
|
||||||
pub var_store: VarStore,
|
pub var_store: VarStore,
|
||||||
|
@ -181,7 +201,7 @@ pub fn to_expr2<'a>(
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
parse_expr: &'a roc_parse::ast::Expr<'a>,
|
parse_expr: &'a roc_parse::ast::Expr<'a>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> (crate::ast::Expr2, Output) {
|
) -> (crate::ast::Expr2, self::Output) {
|
||||||
use roc_parse::ast::Expr::*;
|
use roc_parse::ast::Expr::*;
|
||||||
match parse_expr {
|
match parse_expr {
|
||||||
Float(string) => {
|
Float(string) => {
|
||||||
|
@ -326,7 +346,7 @@ pub fn to_expr2<'a>(
|
||||||
if let Expr2::Var(symbol) = &can_update {
|
if let Expr2::Var(symbol) = &can_update {
|
||||||
match canonicalize_fields(env, scope, fields) {
|
match canonicalize_fields(env, scope, fields) {
|
||||||
Ok((can_fields, mut output)) => {
|
Ok((can_fields, mut output)) => {
|
||||||
output.references = output.references.union(update_out.references);
|
output.references.union_mut(update_out.references);
|
||||||
|
|
||||||
let answer = Expr2::Update {
|
let answer = Expr2::Update {
|
||||||
record_var: env.var_store.fresh(),
|
record_var: env.var_store.fresh(),
|
||||||
|
@ -447,8 +467,8 @@ pub fn to_expr2<'a>(
|
||||||
let (else_expr, else_output) =
|
let (else_expr, else_output) =
|
||||||
to_expr2(env, scope, &else_branch.value, else_branch.region);
|
to_expr2(env, scope, &else_branch.value, else_branch.region);
|
||||||
|
|
||||||
output.references = output.references.union(then_output.references);
|
output.references.union_mut(then_output.references);
|
||||||
output.references = output.references.union(else_output.references);
|
output.references.union_mut(else_output.references);
|
||||||
|
|
||||||
let expr = Expr2::If {
|
let expr = Expr2::If {
|
||||||
cond_var: env.var_store.fresh(),
|
cond_var: env.var_store.fresh(),
|
||||||
|
@ -474,7 +494,7 @@ pub fn to_expr2<'a>(
|
||||||
let (can_when_branch, branch_references) =
|
let (can_when_branch, branch_references) =
|
||||||
canonicalize_when_branch(env, scope, *branch, &mut output);
|
canonicalize_when_branch(env, scope, *branch, &mut output);
|
||||||
|
|
||||||
output.references = output.references.union(branch_references);
|
output.references.union_mut(branch_references);
|
||||||
|
|
||||||
env.pool[node_id] = can_when_branch;
|
env.pool[node_id] = can_when_branch;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +656,7 @@ pub fn to_expr2<'a>(
|
||||||
|
|
||||||
env.pool[node_id] = (env.var_store.fresh(), arg_expr_id);
|
env.pool[node_id] = (env.var_store.fresh(), arg_expr_id);
|
||||||
|
|
||||||
output.references = output.references.union(arg_out.references);
|
output.references.union_mut(arg_out.references);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default: We're not tail-calling a symbol (by name), we're tail-calling a function value.
|
// Default: We're not tail-calling a symbol (by name), we're tail-calling a function value.
|
||||||
|
@ -965,7 +985,7 @@ fn canonicalize_fields<'a>(
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
output.references = output.references.union(field_out.references);
|
output.references.union_mut(field_out.references);
|
||||||
}
|
}
|
||||||
Err(CanonicalizeFieldProblem::InvalidOptionalValue {
|
Err(CanonicalizeFieldProblem::InvalidOptionalValue {
|
||||||
field_name: _,
|
field_name: _,
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
use crate::ast::{ExprId, FloatVal, IntVal};
|
use crate::ast::{ExprId, FloatVal, IntVal};
|
||||||
use crate::expr::{to_expr_id, Env};
|
use crate::expr::{to_expr_id, Env, Output};
|
||||||
use crate::pool::{NodeId, Pool, PoolStr, PoolVec};
|
use crate::pool::{NodeId, Pool, PoolStr, PoolVec, ShallowClone};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use roc_can::expr::{unescape_char, Output};
|
use roc_can::expr::unescape_char;
|
||||||
use roc_can::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
use roc_can::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_parse::ast::{StrLiteral, StrSegment};
|
use roc_parse::ast::{StrLiteral, StrSegment};
|
||||||
|
@ -55,6 +55,12 @@ pub enum Pattern2 {
|
||||||
MalformedPattern(MalformedPatternProblem, Region),
|
MalformedPattern(MalformedPatternProblem, Region),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShallowClone for Pattern2 {
|
||||||
|
fn shallow_clone(&self) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RecordDestruct {
|
pub struct RecordDestruct {
|
||||||
pub var: Variable, // 4B
|
pub var: Variable, // 4B
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub const NODE_BYTES: usize = 32;
|
||||||
// On the plus side, we could be okay with higher memory usage early on,
|
// On the plus side, we could be okay with higher memory usage early on,
|
||||||
// and then later use the Mesh strategy to reduce long-running memory usage.
|
// and then later use the Mesh strategy to reduce long-running memory usage.
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, Eq)]
|
||||||
pub struct NodeId<T> {
|
pub struct NodeId<T> {
|
||||||
index: u32,
|
index: u32,
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
|
@ -57,6 +57,12 @@ impl<T> Clone for NodeId<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> PartialEq for NodeId<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.index == other.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Copy for NodeId<T> {}
|
impl<T> Copy for NodeId<T> {}
|
||||||
|
|
||||||
pub struct Pool {
|
pub struct Pool {
|
||||||
|
|
|
@ -41,6 +41,12 @@ pub enum Type2 {
|
||||||
Erroneous(roc_types::types::Problem),
|
Erroneous(roc_types::types::Problem),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShallowClone for Type2 {
|
||||||
|
fn shallow_clone(&self) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Type2 {
|
impl Type2 {
|
||||||
fn substitute(_pool: &mut Pool, _subs: &MutMap<Variable, TypeId>, _type_id: TypeId) {
|
fn substitute(_pool: &mut Pool, _subs: &MutMap<Variable, TypeId>, _type_id: TypeId) {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue