Class: Peruby::CompileUnit

Inherits:
Object
  • Object
show all
Defined in:
lib/peruby/compile_unit.rb

Overview

One parse/compile/run unit.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(runtime: Runtime.new, file: '-e', interpreter: :compiled) ⇒ CompileUnit

Returns a new instance of CompileUnit.



8
9
10
11
12
# File 'lib/peruby/compile_unit.rb', line 8

def initialize(runtime: Runtime.new, file: '-e', interpreter: :compiled)
  @runtime = runtime
  @file = file
  @interpreter = interpreter
end

Instance Attribute Details

#fileObject (readonly)

Returns the value of attribute file.



6
7
8
# File 'lib/peruby/compile_unit.rb', line 6

def file
  @file
end

#runtimeObject (readonly)

Returns the value of attribute runtime.



6
7
8
# File 'lib/peruby/compile_unit.rb', line 6

def runtime
  @runtime
end

Instance Method Details

#compile(source, env: nil) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/peruby/compile_unit.rb', line 14

def compile(source, env: nil)
  @runtime.with_file(@file) do
    previous_env = @compile_env
    @compile_env = (env || @runtime.env).fork
    @compile_scopes = [{}]
    @predeclared = {}.compare_by_identity
    strict = @compile_env.strict_categories
    warnings = @runtime.warning_categories
    tree = Parser.parse(source, file: @file, known_subs: known_subs(@compile_env.package), unit: self,
                                package: @compile_env.package)
    Validator.validate(tree, runtime: @runtime, strict:, warnings:)
    operation = compiler.compile(tree)
    @runtime.run_phase(:check)
    @interpreter == :tree ? operation : Op::Compiled.new(operation.to_callable, operation.to_subroutine_callable)
  ensure
    @compile_env = previous_env
  end
end

#enter_compile_scopeObject



56
57
58
# File 'lib/peruby/compile_unit.rb', line 56

def enter_compile_scope
  @compile_scopes << {}
end

#leave_compile_scopeObject



60
61
62
# File 'lib/peruby/compile_unit.rb', line 60

def leave_compile_scope
  @compile_scopes.pop
end

#predeclare(node) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/peruby/compile_unit.rb', line 64

def predeclare(node)
  # perlmod: BEGIN runs immediately and can see lexicals declared before it.
  variables = node.variable.is_a?(Node::Variable) ? [node.variable] : node.variable.items
  values = variables.map { |variable| empty_value(variable.sigil) }
  variables.zip(values) do |variable, value|
    @compile_scopes.last[[variable.sigil, variable.name]] = value if value
  end
  @predeclared[node] = values
end

#predeclare_variable(variable) ⇒ Object



74
75
76
# File 'lib/peruby/compile_unit.rb', line 74

def predeclare_variable(variable)
  @compile_scopes.last[[variable.sigil, variable.name]] = empty_value(variable.sigil)
end

#register_phase(kind, block, _token, package) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/peruby/compile_unit.rb', line 41

def register_phase(kind, block, _token, package)
  Validator.validate(block, runtime: @runtime, strict: @compile_env&.strict_categories || Set.new,
                            warnings: @runtime.warning_categories)
  operation = Op::PackageBlock.new(package, compiler.compile(block))
  env = phase_env
  return operation.run(env, :void) if kind == :begin

  @runtime.register_phase(kind, operation, env:)
end

#run(source, context: :void) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/peruby/compile_unit.rb', line 33

def run(source, context: :void)
  @runtime.with_file(@file) do
    operation = compile(source)
    @runtime.run_phase(:init)
    @runtime.local_stack.within { operation.run(@runtime.env, context) }
  end
end

#run_at_compile_time(node) ⇒ Object



51
52
53
54
# File 'lib/peruby/compile_unit.rb', line 51

def run_at_compile_time(node)
  env = node.is_a?(Node::Use) ? @compile_env : phase_env
  compiler.compile(node).run(env, :void)
end