Module: Jade::Frontend::TypeChecking::Inference::FunctionDeclaration
- Extended by:
- FunctionDeclaration, Helpers
- Included in:
- FunctionDeclaration
- Defined in:
- lib/jade/frontend/type_checking/inference/function_declaration.rb
Instance Method Summary collapse
Methods included from Helpers
check, generalize, instantiate, type_from_symbol, unify
Instance Method Details
#infer(node, registry, state, _) ⇒ Object
9 10 11 12 13 14 15 16 17 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 58 59 60 61 62 63 64 65 |
# File 'lib/jade/frontend/type_checking/inference/function_declaration.rb', line 9 def infer(node, registry, state, _) node => AST::FunctionDeclaration(symbol:, body:, params:) # Use the binding directly instead of env.lookup, which would # instantiate fresh vars and detach body call sites' dict markers # from the binding's stored constraints. state .env .bindings[symbol.qualified_name] => { type: fn_type, constraints: fn_constraints, } arg_types, return_type = Type.signature(fn_type) new_state, body_result = arg_types .zip(params) .reduce(state) do |acc, (t, p)| acc.bind(p.name, Scheme.mono(t)) end .then { check(body, registry, it, Expected.check(return_type)) } new_state .unify( body_result.type, return_type, fn_type.unbound_vars ) do Error::FunctionBodyTypeMismatch.new( state.env.entry_name, node.range, expected: it.expected, actual: it.actual, function_name: node.name, ) end .then do |st| next st if st.env.bindings[symbol.qualified_name].is_a?(Scheme) updated_constraints = (fn_constraints + body_result.constraints) .map { st.env.substitution.apply(it) } .uniq # TODO: for impl function declarations, unresolved constraints here # (e.g. Eq(a) when the body calls == on a field of type a) should # be stored as impl-level constraints, not function-level ones. # The impl finalization pass (see TypeChecking.finalize) should then # promote them into deps when the impl is instantiated for a concrete type. st.bind( symbol.qualified_name, Placeholder[ st.env.substitution.apply(fn_type), updated_constraints, ] ) end .then { [it, Result.init(Type.unit)] } end |