Class: Kumi::Core::Analyzer::Folder
- Inherits:
-
Object
- Object
- Kumi::Core::Analyzer::Folder
- Defined in:
- lib/kumi/core/analyzer/folder.rb
Instance Method Summary collapse
- #debug(msg) ⇒ Object
- #fold ⇒ Object
- #fold_call(node) ⇒ Object
- #fold_declaration(decl) ⇒ Object
- #fold_node(node) ⇒ Object
-
#initialize(pass, nast_module, order, registry) ⇒ Folder
constructor
A new instance of Folder.
Constructor Details
#initialize(pass, nast_module, order, registry) ⇒ Folder
Returns a new instance of Folder.
7 8 9 10 11 12 13 14 |
# File 'lib/kumi/core/analyzer/folder.rb', line 7 def initialize(pass, nast_module, order, registry) @nast_module = nast_module @order = order @registry = registry @pass = pass @known_constants = {} @changed = false end |
Instance Method Details
#debug(msg) ⇒ Object
16 17 18 |
# File 'lib/kumi/core/analyzer/folder.rb', line 16 def debug(msg) @pass.method(:debug).call(msg) end |
#fold ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/kumi/core/analyzer/folder.rb', line 20 def fold folded_decls = {} @order.each do |decl_name| decl = @nast_module.decls[decl_name] next unless decl folded_decls[decl_name] = fold_declaration(decl) end [NAST::Module.new(decls: folded_decls), @changed] end |
#fold_call(node) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/kumi/core/analyzer/folder.rb', line 68 def fold_call(node) folded_args = node.args.map { |arg| fold_node(arg) } folded_call = if folded_args.map(&:object_id) == node.args.map(&:object_id) node else NAST::Call.new(fn: node.fn, args: folded_args, opts: node.opts, loc: node.loc) end debug "[FOLD] - Attempting to evaluate call to :#{folded_call.fn}" evaluated_value = ConstantEvaluator.evaluate(folded_call, @registry, @known_constants) if evaluated_value.nil? debug "[FOLD] - Could not evaluate. Keeping call." folded_call else debug "[FOLD] - SUCCESS! Folded call to :#{folded_call.fn} -> #{evaluated_value.inspect}" @changed = true NAST::Const.new(value: evaluated_value, loc: node.loc) end end |
#fold_declaration(decl) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/kumi/core/analyzer/folder.rb', line 32 def fold_declaration(decl) debug "[FOLD] Folding declaration :#{decl.name}" new_body = fold_node(decl.body) @changed ||= !new_body.equal?(decl.body) # *** FIX ***: A node is constant if it's a Const OR a Tuple of only Consts. is_constant = new_body.is_a?(NAST::Const) || (new_body.is_a?(NAST::Tuple) && new_body.args.all? { |arg| arg.is_a?(NAST::Const) }) if is_constant @known_constants[decl.name] = new_body debug "[FOLD] - Identified :#{decl.name} as a constant value." end NAST::Declaration.new(name: decl.name, body: new_body, loc: decl.loc, meta: decl.) end |
#fold_node(node) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/kumi/core/analyzer/folder.rb', line 49 def fold_node(node) case node when NAST::Call fold_call(node) when NAST::Ref resolved_node = @known_constants.fetch(node.name, node) unless resolved_node.equal?(node) debug "[FOLD] - Propagating constant for ref :#{node.name}" @changed = true end resolved_node when NAST::Tuple new_args = node.args.map { |arg| fold_node(arg) } new_args.map(&:object_id) == node.args.map(&:object_id) ? node : NAST::Tuple.new(args: new_args, loc: node.loc) else node end end |