Module: Jade::Frontend::SemanticAnalysis::FunctionDeclaration

Extended by:
FunctionDeclaration, Helper
Included in:
FunctionDeclaration
Defined in:
lib/jade/frontend/semantic_analysis/function_declaration.rb

Instance Method Summary collapse

Methods included from Helper

analyze_duplicate_fields, analyze_in_parallel, analyze_in_sequence, analyze_node, bind, collect_vars, lookup, validate_type_symbol

Instance Method Details

#analyze(node, registry, scope, entry) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/jade/frontend/semantic_analysis/function_declaration.rb', line 8

def analyze(node, registry, scope, entry)
  node => AST::FunctionDeclaration(name:, body:, params:, return_type:)

  symbol_ref = entry.lookup_value(name).to_ref

  params_r = params.reduce(Result[nil, [], scope]) do |acc, param|
    bind(acc.scope, Symbol.var(param.name, param.range), entry)
      .add_errors(acc.errors)
  end

  Result
    .combine(node, scope:,
      body: analyze_node(body, registry, params_r.scope, entry),
    )
    .map_node { it.with(symbol: symbol_ref) }
    .add_errors(params_r.errors)
    .add_errors(validate_type_symbol(symbol_ref, registry, entry))
    .add_errors(validate_predicate_return(name, return_type, symbol_ref, registry, entry))
    .add_errors(params.flat_map { validate_no_predicate_param(it, entry) })
end

#validate_no_predicate_param(param, entry) ⇒ Object

‘?` suffix is reserved for function declaration names. Forbid it on parameters so `def f(empty?: Bool) -> Bool` doesn’t bind ‘empty?` as a value.



32
33
34
35
36
# File 'lib/jade/frontend/semantic_analysis/function_declaration.rb', line 32

def validate_no_predicate_param(param, entry)
  return [] unless param.name.end_with?('?')

  [Error::PredicateNameNotAllowed.new(entry.name, param.range, name: param.name)]
end

#validate_predicate_return(name, return_type_ast, symbol, registry, entry) ⇒ Object

‘?`-suffixed function names must declare a `Bool` return type. Catches `def empty? -> Int` at semantic analysis.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/jade/frontend/semantic_analysis/function_declaration.rb', line 40

def validate_predicate_return(name, return_type_ast, symbol, registry, entry)
  return [] unless name.end_with?('?')

  case registry.lookup(symbol).return_type
  in Symbol::TypeRef['Basics', 'Bool'] |
     Symbol::TypeApplication(constructor: Symbol::TypeRef['Basics', 'Bool'], args: [])
    []
  else
    [Error::PredicateMustReturnBool.new(
      entry.name,
      return_type_ast.range,
      fn_name: name,
    )]
  end
end