Handle simple aliased fn in params value def

This commit is contained in:
Agus Zubiaga 2024-08-27 01:25:59 -03:00
parent 6cffe9b1db
commit 36df43fadc
No known key found for this signature in database
6 changed files with 77 additions and 29 deletions

View file

@ -751,6 +751,9 @@ mod cli_run {
App1.getCompanies [1, 2]: ["https://api.example.com/one/companies/1", "https://api.example.com/one/companies/2"] App1.getCompanies [1, 2]: ["https://api.example.com/one/companies/1", "https://api.example.com/one/companies/2"]
App2.getCompanies [3, 4]: ["http://api.example.com/two/companies/3", "http://api.example.com/two/companies/4"] App2.getCompanies [3, 4]: ["http://api.example.com/two/companies/3", "http://api.example.com/two/companies/4"]
App2.getCompanies [5, 6]: ["http://api.example.com/two/companies/5", "http://api.example.com/two/companies/6"] App2.getCompanies [5, 6]: ["http://api.example.com/two/companies/5", "http://api.example.com/two/companies/6"]
App1.getPostAliased 1: https://api.example.com/one/posts/1
App2.getPostAliased 2: http://api.example.com/two/posts/2
App3.getPostAliased 3: https://api.example.com/three/posts/3
usersApp1: ["https://api.example.com/one/users/1", "https://api.example.com/one/users/2", "https://api.example.com/one/users/3"] usersApp1: ["https://api.example.com/one/users/1", "https://api.example.com/one/users/2", "https://api.example.com/one/users/3"]
getUserApp3Nested 3: https://api.example.com/three/users/3 getUserApp3Nested 3: https://api.example.com/three/users/3
usersApp3Passed: ["https://api.example.com/three/users/1", "https://api.example.com/three/users/2", "https://api.example.com/three/users/3"] usersApp3Passed: ["https://api.example.com/three/users/1", "https://api.example.com/three/users/2", "https://api.example.com/three/users/3"]

View file

@ -1,4 +1,12 @@
module { appId, protocol } -> [baseUrl, getUser, getPost, getPosts, getPostComments, getCompanies] module { appId, protocol } -> [
baseUrl,
getUser,
getPost,
getPosts,
getPostComments,
getCompanies,
getPostAliased,
]
## value def referencing params ## value def referencing params
baseUrl : Str baseUrl : Str
@ -33,3 +41,8 @@ getCompanies = \ids ->
protocol "api.example.com/$(appId)/companies/$(Num.toStr id)" protocol "api.example.com/$(appId)/companies/$(Num.toStr id)"
List.map ids getCompany List.map ids getCompany
## aliasing top-level fn
getPostAliased : U32 -> Str
getPostAliased =
getPost

View file

@ -44,6 +44,9 @@ main =
App1.getCompanies [1, 2]: $(Inspect.toStr (App1.getCompanies [1, 2])) App1.getCompanies [1, 2]: $(Inspect.toStr (App1.getCompanies [1, 2]))
App2.getCompanies [3, 4]: $(Inspect.toStr (App2.getCompanies [3, 4])) App2.getCompanies [3, 4]: $(Inspect.toStr (App2.getCompanies [3, 4]))
App2.getCompanies [5, 6]: $(Inspect.toStr (App2.getCompanies [5, 6])) App2.getCompanies [5, 6]: $(Inspect.toStr (App2.getCompanies [5, 6]))
App1.getPostAliased 1: $(App1.getPostAliased 1)
App2.getPostAliased 2: $(App2.getPostAliased 2)
App3.getPostAliased 3: $(App3.getPostAliased 3)
usersApp1: $(Inspect.toStr usersApp1) usersApp1: $(Inspect.toStr usersApp1)
getUserApp3Nested 3: $(getUserApp3Nested 3) getUserApp3Nested 3: $(getUserApp3Nested 3)
usersApp3Passed: $(Inspect.toStr usersApp3Passed) usersApp3Passed: $(Inspect.toStr usersApp3Passed)

View file

@ -113,21 +113,35 @@ impl Annotation {
self self
} }
pub fn convert_to_fn(&mut self, argument_count: usize, var_store: &mut VarStore) { pub fn add_arguments(&mut self, argument_count: usize, var_store: &mut VarStore) {
let mut arg_types = Vec::with_capacity(argument_count); match self.signature {
Type::Function(ref mut arg_types, _, _) => {
arg_types.reserve(argument_count);
for _ in 0..argument_count { for _ in 0..argument_count {
let var = var_store.fresh(); let var = var_store.fresh();
self.introduced_variables.insert_inferred(Loc::at_zero(var)); self.introduced_variables.insert_inferred(Loc::at_zero(var));
arg_types.push(Type::Variable(var)); arg_types.push(Type::Variable(var));
}
}
_ => {
let mut arg_types = Vec::with_capacity(argument_count);
for _ in 0..argument_count {
let var = var_store.fresh();
self.introduced_variables.insert_inferred(Loc::at_zero(var));
arg_types.push(Type::Variable(var));
}
self.signature = Type::Function(
arg_types,
Box::new(Type::Variable(var_store.fresh())),
Box::new(self.signature.clone()),
);
}
} }
self.signature = Type::Function(
arg_types,
Box::new(Type::Variable(var_store.fresh())),
Box::new(self.signature.clone()),
);
} }
} }

View file

@ -3135,11 +3135,11 @@ impl Declarations {
Index::push_new(&mut self.function_bodies, loc_function_def); Index::push_new(&mut self.function_bodies, loc_function_def);
if let Some(annotation) = &mut self.annotations[index] { if let Some(annotation) = &mut self.annotations[index] {
annotation.convert_to_fn(new_args_len, var_store); annotation.add_arguments(new_args_len, var_store);
} }
if let Some((_var, annotation)) = self.host_exposed_annotations.get_mut(&index) { if let Some((_var, annotation)) = self.host_exposed_annotations.get_mut(&index) {
annotation.convert_to_fn(new_args_len, var_store); annotation.add_arguments(new_args_len, var_store);
} }
self.declarations[index] = DeclarationTag::Function(function_def_index); self.declarations[index] = DeclarationTag::Function(function_def_index);

View file

@ -12,7 +12,6 @@ use roc_collections::VecMap;
use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol}; use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol};
use roc_region::all::Loc; use roc_region::all::Loc;
use roc_types::subs::{VarStore, Variable}; use roc_types::subs::{VarStore, Variable};
use roc_types::types::Type;
struct LowerParams<'a> { struct LowerParams<'a> {
home_id: ModuleId, home_id: ModuleId,
@ -56,12 +55,21 @@ impl<'a> LowerParams<'a> {
match tag { match tag {
Value => { Value => {
self.lower_expr(&mut decls.expressions[index].value); let aliasing_fn = self.lower_expr(true, &mut decls.expressions[index].value);
if let Some(new_arg) = self.home_params_argument() { if let Some(new_arg) = self.home_params_argument() {
// This module has params, and this is a top-level value, if !aliasing_fn {
// so we need to convert it into a function that takes them. // This module has params, and this is a top-level value,
decls.convert_value_to_function(index, vec![new_arg], self.var_store); // so we need to convert it into a function that takes them.
decls.convert_value_to_function(index, vec![new_arg], self.var_store);
} else {
// This value def is just aliasing another function,
// we only need to fix the annotation
if let Some(ann) = &mut decls.annotations[index] {
ann.add_arguments(1, self.var_store);
}
}
} }
} }
Function(fn_def_index) | Recursive(fn_def_index) | TailRecursive(fn_def_index) => { Function(fn_def_index) | Recursive(fn_def_index) | TailRecursive(fn_def_index) => {
@ -75,25 +83,24 @@ impl<'a> LowerParams<'a> {
.push((var, mark, pattern)); .push((var, mark, pattern));
if let Some(ann) = &mut decls.annotations[index] { if let Some(ann) = &mut decls.annotations[index] {
if let Type::Function(args, _, _) = &mut ann.signature { ann.add_arguments(1, self.var_store);
args.push(Type::Variable(var))
}
} }
} }
self.lower_expr(&mut decls.expressions[index].value) self.lower_expr(false, &mut decls.expressions[index].value);
} }
Destructure(_) | Expectation | ExpectationFx => { Destructure(_) | Expectation | ExpectationFx => {
self.lower_expr(&mut decls.expressions[index].value) self.lower_expr(false, &mut decls.expressions[index].value);
} }
MutualRecursion { .. } => {} MutualRecursion { .. } => {}
} }
} }
} }
fn lower_expr(&mut self, expr: &mut Expr) { fn lower_expr(&mut self, is_value_def: bool, expr: &mut Expr) -> bool {
let mut expr_stack = vec![expr]; let mut expr_stack = vec![expr];
let mut aliasing_fn = false;
while let Some(expr) = expr_stack.pop() { while let Some(expr) = expr_stack.pop() {
match expr { match expr {
@ -120,8 +127,14 @@ impl<'a> LowerParams<'a> {
} }
Var(symbol, var) => { Var(symbol, var) => {
if let Some((params, arity)) = self.params_extended_home_symbol(symbol) { if let Some((params, arity)) = self.params_extended_home_symbol(symbol) {
if is_value_def && arity > 0 {
// Aliased top-level function, no need to lower
aliasing_fn = true;
continue;
}
*expr = self.lower_naked_params_var( *expr = self.lower_naked_params_var(
*arity, arity,
*symbol, *symbol,
*var, *var,
params.whole_symbol, params.whole_symbol,
@ -357,17 +370,19 @@ impl<'a> LowerParams<'a> {
| AbilityMember(_, _, _) => { /* terminal */ } | AbilityMember(_, _, _) => { /* terminal */ }
} }
} }
aliasing_fn
} }
fn unique_symbol(&mut self) -> Symbol { fn unique_symbol(&mut self) -> Symbol {
Symbol::new(self.home_id, self.ident_ids.gen_unique()) Symbol::new(self.home_id, self.ident_ids.gen_unique())
} }
fn params_extended_home_symbol(&self, symbol: &Symbol) -> Option<(&ModuleParams, &usize)> { fn params_extended_home_symbol(&self, symbol: &Symbol) -> Option<(&ModuleParams, usize)> {
if symbol.module_id() == self.home_id { if symbol.module_id() == self.home_id {
match self.home_params { match self.home_params {
Some(params) => match params.arity_by_name.get(&symbol.ident_id()) { Some(params) => match params.arity_by_name.get(&symbol.ident_id()) {
Some(arity) => Some((params, arity)), Some(arity) => Some((params, *arity)),
None => None, None => None,
}, },
None => None, None => None,