Class: Ryac::Pipeline::StageRunner

Inherits:
Object
  • Object
show all
Includes:
SourcePatcher
Defined in:
lib/ryac/pipeline/stage_runner.rb,
sig/ryac/pipeline/stage_runner.rbs

Overview

The one place that executes a stage list.

The list is ordered — phase is position, nothing else. Compaction is the fixed first step. A maximal run of consecutive needs_analysis? stages forms the analysis batch: TypeProf runs once for it, every member collects into one patch pool, the pool is applied in a single splice, and each member's finish then contributes aliases/preamble in list order. A list that would need a second batch implies a second TypeProf run — that is a composition error, and it raises before running anything half-way.

Instance Method Summary collapse

Methods included from SourcePatcher

#apply_patches, #mk, #src, #verify_parses

Constructor Details

#initialize(stdlib_requires: [], rbs_files: {}, lazy_files: []) ⇒ StageRunner

Returns a new instance of StageRunner.

Parameters:

  • stdlib_requires: (Array[String]) (defaults to: [])
  • rbs_files: (Hash[String, String]) (defaults to: {})
  • lazy_files: (Array[String]) (defaults to: [])


18
19
20
21
22
# File 'lib/ryac/pipeline/stage_runner.rb', line 18

def initialize(stdlib_requires: [], rbs_files: {}, lazy_files: [])
  @stdlib_requires = stdlib_requires
  @rbs_files = rbs_files
  @lazy_files = lazy_files
end

Instance Method Details

#call(code, stage_defs) ⇒ RenameResult

Parameters:

  • code (String)
  • stage_defs (Array[Minifier::stage_entry])

Returns:



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
# File 'lib/ryac/pipeline/stage_runner.rb', line 24

def call(code, stage_defs)
  stages = stage_defs.map { |entry| instantiate(entry) }

  batches = stages.chunk_while { |a, b| a.needs_analysis? == b.needs_analysis? }.to_a
  analysis_batches = batches.count { |chunk| chunk.fetch(0).needs_analysis? }
  if analysis_batches > 1
    raise ArgumentError,
          "stage list needs #{analysis_batches} analysis batches; " \
          "TypeProf runs once, so all analysis stages must be consecutive"
  end

  result = Compactor.new.call(code)
  # The compacted text is the dialect every stage downstream assumes.
  # If it does not parse, the Compactor is the culprit — name it here
  # instead of letting whichever stage trips first inherit the blame.
  verify_parses(result, 'compacted')
  aliases = ''
  preamble = ''

  batches.each do |chunk|
    if chunk.fetch(0).needs_analysis?
      result, aliases, preamble = run_analysis_batch(result, chunk)
    else
      chunk.each { |stage| result = stage.call(result) }
    end
  end

  verify_parses(result, 'code')
  verify_parses(aliases, 'aliases')
  RenameResult.new(code: result, aliases: aliases, preamble: preamble)
end

#instantiate(entry) ⇒ Stage

Parameters:

  • entry (Minifier::stage_entry)

Returns:



58
59
60
61
62
63
# File 'lib/ryac/pipeline/stage_runner.rb', line 58

def instantiate(entry)
  klass, kwargs = entry
  # A stage entry is data ([class] or [class, kwargs]); configuration
  # becomes constructor state here and nowhere else.
  kwargs ? klass.new(**kwargs) : klass.new
end

#run_analysis_batch(code, batch) ⇒ [String, String, String]

Parameters:

  • code (String)
  • batch (Array[Stage])

Returns:

  • ([String, String, String])


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ryac/pipeline/stage_runner.rb', line 65

def run_analysis_batch(code, batch)
  source = ConcatenatedSource.new(
    content: code,
    stdlib_requires: @stdlib_requires,
    rbs_files: @rbs_files,
    lazy_files: @lazy_files
  )
  options = {} #: Hash[Symbol, untyped]
  batch.each { |stage| options.merge!(stage.analysis_options) }
  analysis = Analyzer.new(**options).call(source)

  ctx = StageContext.new(code, analysis.prism_ast, analysis, '', '')
  patches = [] #: Array[patch_entry]
  batch.each { |stage| stage.collect(ctx, patches) }

  result = apply_patches(code, patches)
  ctx.source = result
  batch.each { |stage| stage.finish(ctx) }

  [result, ctx.aliases, ctx.preamble]
end