Class: Sevgi::Executor

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/sevgi/executor.rb,
lib/sevgi/executor/error.rb,
lib/sevgi/executor/scope.rb,
lib/sevgi/executor/source.rb

Overview

Executes Sevgi script source inside an isolated module scope.

The executor is used by script mode and by the Load DSL word to preserve a useful load stack while keeping DSL methods out of the caller's global object whenever possible.

Defined Under Namespace

Classes: Error, Scope, Source

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeExecutor

Returns a new instance of Executor.



74
# File 'lib/sevgi/executor.rb', line 74

def initialize = @scopes = []

Class Method Details

.execute(string, file: nil, line: nil, require: nil, receiver: nil) { ... } ⇒ Sevgi::Executor::Scope?

Executes Ruby source inside a managed Sevgi script scope.

Parameters:

  • string (String)

    source to evaluate

  • file (String, nil) (defaults to: nil)

    source file name used for errors and backtraces

  • line (Integer, nil) (defaults to: nil)

    starting source line used for errors and backtraces

  • require (String, nil) (defaults to: nil)

    optional Ruby library to require before execution

  • receiver (Object, nil) (defaults to: nil)

    receiver used while booting the DSL

Yields:

  • optional boot block that installs DSL methods before evaluation

Yield Returns:

  • (void)

Returns:

Raises:

  • (LoadError)

    when the optional required library cannot be loaded



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/sevgi/executor.rb', line 39

def self.execute(string, file: nil, line: nil, require: nil, receiver: nil, &block)
  return if string.empty?

  interrupt = Signal.trap("INT") { Kernel.abort("") }

  ::Kernel.require(require) if require

  scope = instance.create
  catch(:result) { scope.call(Source.new(string:, file:, line:), receiver, &block) }

ensure
  Signal.trap("INT", interrupt) if interrupt
  instance.shutdown if scope
end

.execute_file(file, require: nil, receiver: nil) { ... } ⇒ Sevgi::Executor::Scope?

Executes a file inside a managed Sevgi script scope.

Parameters:

  • file (String)

    source file to read and execute

  • require (String, nil) (defaults to: nil)

    optional Ruby library to require before execution

  • receiver (Object, nil) (defaults to: nil)

    receiver used while booting the DSL

Yields:

  • optional boot block that installs DSL methods before evaluation

Yield Returns:

  • (void)

Returns:

Raises:

  • (Errno::ENOENT)

    when the file cannot be read

  • (LoadError)

    when the optional required library cannot be loaded



63
64
65
# File 'lib/sevgi/executor.rb', line 63

def self.execute_file(file, require: nil, receiver: nil, &block)
  execute(::File.read(file), file: file, line: 1, require:, receiver:, &block)
end

.load(file) ⇒ Sevgi::Executor::Scope

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Loads a script file inside the current executor scope.

Parameters:

  • file (String)

    path to a Sevgi script file

Returns:

Raises:

  • (Sevgi::PanicError)

    when there is no active executor scope



23
24
25
26
27
# File 'lib/sevgi/executor.rb', line 23

def self.load(file, ...)
  PanicError.("box stack empty; create a box first") unless instance.current

  instance.current.load(file, ...)
end

.shutdownSevgi::Executor::Scope?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Removes the current executor scope.

Returns:



70
71
72
# File 'lib/sevgi/executor.rb', line 70

def self.shutdown
  instance.shutdown
end

Instance Method Details

#create(scope = nil) ⇒ Sevgi::Executor::Scope

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates and pushes a new executor scope.

Parameters:

  • scope (Module, nil) (defaults to: nil)

    existing module scope to reuse

Returns:



80
# File 'lib/sevgi/executor.rb', line 80

def create(scope = nil) = Scope.new(scope).tap { @scopes << it }

#currentSevgi::Executor::Scope?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the active executor scope.

Returns:



85
# File 'lib/sevgi/executor.rb', line 85

def current = @scopes.last

#shutdownSevgi::Executor::Scope?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Removes the active executor scope.

Returns:



90
# File 'lib/sevgi/executor.rb', line 90

def shutdown = @scopes.pop