Skip to content

Commit

Permalink
add parser code for lambda types
Browse files Browse the repository at this point in the history
Add LambdaCaptureKind to allow specifying move/copy/borrow treatment for free variables.  Tweak simplifier to *not* remove lambda values (even though they are now ) to avoid losing some errors/warnings.

add lambda-lifting specialization and _ argument handling to generate Closure expressions in the move-model.
  • Loading branch information
brmataptos committed Oct 21, 2024
1 parent 7cfe2c4 commit 2a740e8
Show file tree
Hide file tree
Showing 110 changed files with 1,978 additions and 27,397 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion third_party/move/evm/move-to-yul/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ impl<'a> Context<'a> {
Tuple(_)
| TypeParameter(_)
| Reference(_, _)
| Fun(_, _)
| Fun(..)
| TypeDomain(_)
| ResourceDomain(_, _, _)
| Error
Expand Down
2 changes: 1 addition & 1 deletion third_party/move/evm/move-to-yul/src/solidity_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ impl SolidityType {
},
TypeParameter(_)
| Reference(_, _)
| Fun(_, _)
| Fun(..)
| TypeDomain(_)
| ResourceDomain(_, _, _)
| Error
Expand Down
22 changes: 13 additions & 9 deletions third_party/move/move-compiler-v2/src/bytecode_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,23 @@ impl<'env> Generator<'env> {
self.emit_with(*id, |attr| Bytecode::SpecBlock(attr, spec));
},
// TODO(LAMBDA)
ExpData::Lambda(id, _, _) => self.error(
ExpData::Lambda(id, _, _, _, _) => self.error(
*id,
"Function-typed values not yet supported except as parameters to calls to inline functions",
),
// TODO(LAMBDA)
ExpData::Invoke(_, exp, _) => self.error(
exp.as_ref().node_id(),
ExpData::MoveFunctionExp(id, _mid, _fid) => self.error(
*id,
"Function-typed values not yet supported except as parameters to calls to inline functions",
),
// TODO(LAMBDA)
ExpData::Curry(id, _mask, _fnexp, _args) => self.error(
*id,
"Function-typed values not yet supported except as parameters to calls to inline functions",
),
// TODO(LAMBDA)
ExpData::Invoke(id, _exp, _) => self.error(
*id,
"Calls to function values other than inline function parameters not yet supported",
),
ExpData::Quant(id, _, _, _, _, _) => {
Expand Down Expand Up @@ -813,12 +823,6 @@ impl<'env> Generator<'env> {

Operation::NoOp => {}, // do nothing

// TODO(LAMBDA)
Operation::Closure(..) => self.error(
id,
"Function-typed values not yet supported except as parameters to calls to inline functions",
),

// Non-supported specification related operations
Operation::Exists(Some(_))
| Operation::SpecFunction(_, _, _)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ fn find_possibly_modified_vars(
exp.visit_positions(&mut |pos, e| {
use ExpData::*;
match e {
Invalid(_) | Value(..) | LoopCont(..) => {
Invalid(_) | Value(..) | LoopCont(..) | MoveFunctionExp(..) => {
// Nothing happens inside these expressions, so don't bother `modifying` state.
},
LocalVar(id, sym) => {
Expand Down Expand Up @@ -359,7 +359,7 @@ fn find_possibly_modified_vars(
_ => {},
}
},
Lambda(node_id, pat, _) => {
Lambda(node_id, pat, _, _, _) => {
// Define a new scope for bound vars, and turn off `modifying` within.
match pos {
VisitorPosition::Pre => {
Expand All @@ -380,6 +380,19 @@ fn find_possibly_modified_vars(
_ => {},
};
},
Curry(_, _mask, _fnexp, _explist) => {
// Turn off `modifying` inside.
match pos {
VisitorPosition::Pre => {
modifying_stack.push(modifying);
modifying = false;
},
VisitorPosition::Post => {
modifying = modifying_stack.pop().expect("unbalanced visit 10");
},
_ => {},
}
},
Block(node_id, pat, _, _) => {
// Define a new scope for bound vars, and turn off `modifying` within.
match pos {
Expand Down Expand Up @@ -978,7 +991,8 @@ impl<'env> ExpRewriterFunctions for SimplifierRewriter<'env> {
let ability_set = self
.env()
.type_abilities(&ty, self.func_env.get_type_parameters_ref());
ability_set.has_ability(Ability::Drop)
// Don't drop a function-valued expression so we don't lose errors.
!ty.has_function() && ability_set.has_ability(Ability::Drop)
} else {
// We're missing type info, be conservative
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl<'env, 'params> SymbolVisitor<'env, 'params> {
Pre | Post | BeforeBody | MidMutate | BeforeThen | BeforeElse
| PreSequenceValue => {},
},
Lambda(_, pat, _) => {
Lambda(_, pat, _, _, _) => {
match position {
Pre => self.seen_uses.enter_scope(),
Post => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ fn identify_function_types_with_functions_in_args(func_types: Vec<Type>) -> Vec<
func_types
.into_iter()
.filter_map(|ty| {
if let Type::Fun(argt, _) = &ty {
if argt.deref().has_function() {
if let Type::Fun(args, _, _) = &ty {
if args.deref().has_function() {
Some(ty)
} else {
None
Expand All @@ -41,8 +41,8 @@ fn identify_function_typed_params_with_functions_in_rets(
func_types
.iter()
.filter_map(|param| {
if let Type::Fun(_argt, rest) = &param.1 {
let rest_unboxed = rest.deref();
if let Type::Fun(_args, result, _) = &param.1 {
let rest_unboxed = result.deref();
if rest_unboxed.has_function() {
Some((*param, rest_unboxed))
} else {
Expand Down Expand Up @@ -270,7 +270,7 @@ fn check_privileged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv
},
ExpData::Assign(_, pat, _)
| ExpData::Block(_, pat, _, _)
| ExpData::Lambda(_, pat, _) => {
| ExpData::Lambda(_, pat, _, _, _) => {
pat.visit_pre_post(&mut |_, pat| {
if let Pattern::Struct(id, str, _, _) = pat {
let module_id = str.module_id;
Expand Down Expand Up @@ -344,7 +344,7 @@ pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) {

// Check that functions being called are accessible.
if let Some(def) = caller_func.get_def() {
let callees_with_sites = def.called_funs_with_callsites();
let callees_with_sites = def.used_funs_with_uses();
for (callee, sites) in &callees_with_sites {
let callee_func = env.get_function(*callee);
// Check visibility.
Expand Down
4 changes: 2 additions & 2 deletions third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn run_inlining(env: &mut GlobalEnv, scope: RewritingScope, keep_inline_func
let mut visited_targets = BTreeSet::new();
while let Some(target) = todo.pop_first() {
if visited_targets.insert(target.clone()) {
let callees_with_sites = target.called_funs_with_call_sites(env);
let callees_with_sites = target.used_funs_with_uses(env);
for (callee, sites) in callees_with_sites {
todo.insert(RewriteTarget::MoveFun(callee));
targets.entry(RewriteTarget::MoveFun(callee));
Expand Down Expand Up @@ -1161,7 +1161,7 @@ impl<'env, 'rewriter> ExpRewriterFunctions for InlinedRewriter<'env, 'rewriter>
};
let call_loc = self.env.get_node_loc(id);
if let Some(lambda_target) = optional_lambda_target {
if let ExpData::Lambda(_, pat, body) = lambda_target.as_ref() {
if let ExpData::Lambda(_, pat, body, _, _) = lambda_target.as_ref() {
let args_vec: Vec<Exp> = args.to_vec();
Some(InlinedRewriter::construct_inlined_call_expression(
self.env,
Expand Down
Loading

0 comments on commit 2a740e8

Please sign in to comment.