Module: Jade::Codegen::Transforms::FoldShape
- Included in:
- FoldShape
- Defined in:
- lib/jade/codegen/transforms/fold_shape.rb
Constant Summary collapse
- ACC_NAME =
'__fold_acc__'
Constants included from Helpers
Instance Method Summary collapse
-
#generate_body(shape, registry) ⇒ Object
Emits
xs.reverse.reduce(BASE) { |acc, head| COMBINE' }. -
#shape_for(body, self_sym, param_names, registry) ⇒ Object
The right-fold shape:.
Methods included from Helpers
data_define, dict_constraints, dict_synthetic_name, fn_constraints, fn_impl_synthetic_name, generate_many, generate_node, impl_synthetic_name, param_synthetic_name, resolve_callee_symbol, ruby_classes_for_type, to_qualified
Instance Method Details
#generate_body(shape, registry) ⇒ Object
Emits xs.reverse.reduce(BASE) { |acc, head| COMBINE' }. The
reverse gives right-associative combine order regardless of the
combiner's algebraic properties. Task effects are unaffected by
build order — only the final Task chain shape determines run-time
behavior.
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/jade/codegen/transforms/fold_shape.rb', line 64 def generate_body(shape, registry) shape => { list_arg:, base:, head_name:, combine:, self_call: } base_code = generate_node(base, registry) combine_code = substitute(combine, self_call) .then { generate_node(it, registry) } "#{list_arg}.reverse.reduce(#{base_code}) " \ "{ |#{ACC_NAME}, #{head_name}| #{combine_code} }" end |
#shape_for(body, self_sym, param_names, registry) ⇒ Object
The right-fold shape:
def f(xs) ->
case xs
of [] -> BASE (no self-call)
of [h | rest] -> COMBINE (exactly one f(rest), strict)
Returns a shape hash, or nil if the body doesn't match.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/jade/codegen/transforms/fold_shape.rb', line 18 def shape_for(body, self_sym, param_names, registry) return nil unless param_names.size == 1 sig = [self_sym, 1] expr = unwrap_body(body) return nil unless expr.is_a?(AST::CaseOf) return nil unless expr.branches.size == 2 list_arg = param_names.first return nil unless subject_is_arg?(expr.expression, list_arg) empty_branch = expr.branches.find { empty_list_pattern?(it.pattern) } cons_branch = expr.branches.find { cons_pattern?(it.pattern) } return nil unless empty_branch && cons_branch return nil if SelfCall.contains_self_call?( empty_branch.body, sig, registry ) head_name = head_binding_name(cons_branch.pattern) rest_name = rest_binding_name(cons_branch.pattern) return nil unless head_name && rest_name calls = strict_self_calls(cons_branch.body, sig, registry) return nil unless calls&.size == 1 call = calls.first return nil unless call.args.size == 1 arg = call.args.first return nil unless arg in AST::VariableReference(name: ^rest_name) return nil unless rest_used_only?(cons_branch.body, rest_name, call) { list_arg: list_arg, base: empty_branch.body, head_name: head_name, combine: cons_branch.body, self_call: call, } end |