Add symbols' localized type variable to the AST

This commit is contained in:
Ayaz Hafiz 2022-10-17 17:28:54 -05:00
parent 9d9053c2d1
commit 8aee32830a
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
11 changed files with 230 additions and 167 deletions

View file

@ -100,7 +100,7 @@ pub enum Expr {
},
// Lookups
Var(Symbol),
Var(Symbol, Variable),
AbilityMember(
/// Actual member name
Symbol,
@ -256,7 +256,7 @@ impl Expr {
Self::Str(..) => Category::Str,
Self::SingleQuote(..) => Category::Character,
Self::List { .. } => Category::List,
&Self::Var(sym) => Category::Lookup(sym),
&Self::Var(sym, _) => Category::Lookup(sym),
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
Self::When { .. } => Category::When,
Self::If { .. } => Category::If,
@ -372,7 +372,7 @@ impl AccessorData {
record_var,
ext_var,
field_var,
loc_expr: Box::new(Loc::at_zero(Expr::Var(record_symbol))),
loc_expr: Box::new(Loc::at_zero(Expr::Var(record_symbol, record_var))),
field,
};
@ -440,7 +440,10 @@ impl OpaqueWrapFunctionData {
let body = Expr::OpaqueRef {
opaque_var,
name: opaque_name,
argument: Box::new((argument_var, Loc::at_zero(Expr::Var(argument_symbol)))),
argument: Box::new((
argument_var,
Loc::at_zero(Expr::Var(argument_symbol, argument_var)),
)),
specialized_def_type: Box::new(specialized_def_type),
type_arguments,
lambda_set_variables,
@ -592,7 +595,7 @@ pub fn canonicalize_expr<'a>(
} => {
let (can_update, update_out) =
canonicalize_expr(env, var_store, scope, loc_update.region, &loc_update.value);
if let Var(symbol) = &can_update.value {
if let Var(symbol, _) = &can_update.value {
match canonicalize_fields(env, var_store, scope, region, fields.items) {
Ok((can_fields, mut output)) => {
output.references.union_mut(&update_out.references);
@ -765,7 +768,7 @@ pub fn canonicalize_expr<'a>(
output.tail_call = None;
let expr = match fn_expr.value {
Var(symbol) => {
Var(symbol, _) => {
output.references.insert_call(symbol);
// we're tail-calling a symbol by name, check if it's the tail-callable symbol
@ -994,7 +997,7 @@ pub fn canonicalize_expr<'a>(
// Get all the lookups that were referenced in the condition,
// so we can print their values later.
let lookups_in_cond = get_lookup_symbols(&loc_condition.value, var_store);
let lookups_in_cond = get_lookup_symbols(&loc_condition.value);
let (loc_continuation, output2) = canonicalize_expr(
env,
@ -1600,7 +1603,7 @@ fn canonicalize_var_lookup(
var_store.fresh(),
)
} else {
Var(symbol)
Var(symbol, var_store.fresh())
}
}
Err(problem) => {
@ -1623,7 +1626,7 @@ fn canonicalize_var_lookup(
var_store.fresh(),
)
} else {
Var(symbol)
Var(symbol, var_store.fresh())
}
}
Err(problem) => {
@ -1657,7 +1660,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
| other @ EmptyRecord
| other @ Accessor { .. }
| other @ Update { .. }
| other @ Var(_)
| other @ Var(..)
| other @ AbilityMember(..)
| other @ RunLowLevel { .. }
| other @ TypedHole { .. }
@ -1960,67 +1963,71 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
match loc_expr.value {
Var(symbol) if symbol.is_builtin() => match builtin_defs_map(symbol, var_store) {
Some(Def {
loc_expr:
Loc {
value:
Closure(ClosureData {
recursive,
arguments: params,
loc_body: boxed_body,
..
}),
..
},
..
}) => {
debug_assert_eq!(recursive, Recursive::NotRecursive);
Var(symbol, _) if symbol.is_builtin() => {
match builtin_defs_map(symbol, var_store) {
Some(Def {
loc_expr:
Loc {
value:
Closure(ClosureData {
recursive,
arguments: params,
loc_body: boxed_body,
..
}),
..
},
..
}) => {
debug_assert_eq!(recursive, Recursive::NotRecursive);
// Since this is a canonicalized Expr, we should have
// already detected any arity mismatches and replaced this
// with a RuntimeError if there was a mismatch.
debug_assert_eq!(params.len(), args.len());
// Since this is a canonicalized Expr, we should have
// already detected any arity mismatches and replaced this
// with a RuntimeError if there was a mismatch.
debug_assert_eq!(params.len(), args.len());
// Start with the function's body as the answer.
let mut loc_answer = *boxed_body;
// Start with the function's body as the answer.
let mut loc_answer = *boxed_body;
// Wrap the body in one LetNonRec for each argument,
// such that at the end we have all the arguments in
// scope with the values the caller provided.
for ((_param_var, _exhaustive_mark, loc_pattern), (expr_var, loc_expr)) in
params.iter().cloned().zip(args.into_iter()).rev()
{
// TODO get the correct vars into here.
// Not sure if param_var should be involved.
let pattern_vars = SendMap::default();
// Wrap the body in one LetNonRec for each argument,
// such that at the end we have all the arguments in
// scope with the values the caller provided.
for (
(_param_var, _exhaustive_mark, loc_pattern),
(expr_var, loc_expr),
) in params.iter().cloned().zip(args.into_iter()).rev()
{
// TODO get the correct vars into here.
// Not sure if param_var should be involved.
let pattern_vars = SendMap::default();
let def = Def {
loc_pattern,
loc_expr,
expr_var,
pattern_vars,
annotation: None,
};
let def = Def {
loc_pattern,
loc_expr,
expr_var,
pattern_vars,
annotation: None,
};
loc_answer = Loc {
region: Region::zero(),
value: LetNonRec(Box::new(def), Box::new(loc_answer)),
};
loc_answer = Loc {
region: Region::zero(),
value: LetNonRec(Box::new(def), Box::new(loc_answer)),
};
}
loc_answer.value
}
Some(_) => {
unreachable!("Tried to inline a non-function");
}
None => {
unreachable!(
"Tried to inline a builtin that wasn't registered: {:?}",
symbol
);
}
loc_answer.value
}
Some(_) => {
unreachable!("Tried to inline a non-function");
}
None => {
unreachable!(
"Tried to inline a builtin that wasn't registered: {:?}",
symbol
);
}
},
}
_ => {
// For now, we only inline calls to builtins. Leave this alone!
Call(
@ -2172,7 +2179,10 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
Interpolation(loc_interpolated_expr) => loc_interpolated_expr,
};
let fn_expr = Loc::at(Region::zero(), Expr::Var(Symbol::STR_CONCAT));
let fn_expr = Loc::at(
Region::zero(),
Expr::Var(Symbol::STR_CONCAT, var_store.fresh()),
);
let expr = Expr::Call(
Box::new((
var_store.fresh(),
@ -2615,16 +2625,22 @@ pub struct DestructureDef {
pub pattern_vars: VecMap<Symbol, Variable>,
}
fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Variable)> {
fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> {
let mut stack: Vec<&Expr> = vec![expr];
let mut symbols = Vec::new();
while let Some(expr) = stack.pop() {
match expr {
Expr::Var(symbol) | Expr::Update { symbol, .. } | Expr::AbilityMember(symbol, _, _) => {
Expr::Var(symbol, var)
| Expr::Update {
symbol,
record_var: var,
..
}
| Expr::AbilityMember(symbol, _, var) => {
// Don't introduce duplicates, or make unused variables
if !symbols.iter().any(|(sym, _)| sym == symbol) {
symbols.push((*symbol, var_store.fresh()));
symbols.push((*symbol, *var));
}
}
Expr::List { loc_elems, .. } => {
@ -2665,7 +2681,7 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
stack.reserve(1 + args.len());
match &boxed_expr.1.value {
Expr::Var(_) => {
Expr::Var(_, _) => {
// do nothing
}
function_expr => {