Module: Musa::REPL::CustomizableDSLContext

Defined in:
lib/musa-dsl/repl/repl.rb

Overview

Mixin for DSL contexts that can be bound to a REPL.

This module provides the interface required for a DSL context to work with the REPL server. Classes that include this module can execute REPL-sent code in their own context, making their DSL methods available to live coding clients.

Requirements

Classes that include this module must implement the #binder method, which should return a Ruby Binding object representing the execution context.

Integration with DynamicProxy

Typically used with Musa::Extension::DynamicProxy::DynamicProxy:

class MyDSL
  include CustomizableDSLContext

  def initialize
    @repl = REPL.new(bind: Musa::Extension::DynamicProxy::DynamicProxy.new(self))
  end

  protected def binder
    @__binder ||= binding
  end

  # DSL methods available in REPL:
  def play(note)
    # ...
  end
end

Execution Context

Code sent via REPL is evaluated in the binding returned by #binder, giving it access to:

  • Instance variables of the DSL context
  • All DSL methods (public and private)
  • Local variables captured in the binding

Examples:

Basic implementation

class LiveCodingEnvironment
  include Musa::REPL::CustomizableDSLContext

  def initialize
    @sequencer = Musa::Sequencer::Sequencer.new(4, 24)
    @repl = REPL.new(bind: Musa::Extension::DynamicProxy::DynamicProxy.new(self))
  end

  protected def binder
    @__binder ||= binding
  end

  # DSL methods accessible from REPL:
  def at(position, &block)
    @sequencer.at(position, &block)
  end
end

From REPL client

# Code sent by editor:
at 0 { play C4 }
at 4 { play D4 }
# Executes in LiveCodingEnvironment instance context

See Also:

Instance Method Summary collapse

Instance Method Details

#execute(source_block, file, line) ⇒ Object

Executes source code in the DSL context.

Called by the REPL to evaluate received code blocks. Delegates to Binding#eval with the binding provided by #binder.

Parameters

  • source_block: Ruby code as string
  • file: Filename for error reporting (typically '(repl)')
  • line: Starting line number for error reporting

Error Handling

Exceptions raised during evaluation propagate to the caller (REPL), which formats them and sends them to the client.

Examples:

Internal usage by REPL

# REPL calls this internally:
context.execute("sequencer.at 0 { puts 'tick' }", "(repl)", 1)

Parameters:

  • source_block (String)

    Ruby code to execute

  • file (String)

    filename for backtrace (usually '(repl)')

  • line (Integer)

    starting line number for backtrace

Returns:

  • (Object)

    result of evaluating the source code

Raises:

  • (Exception)

    any exception raised by the executed code

See Also:



751
752
753
# File 'lib/musa-dsl/repl/repl.rb', line 751

def execute(source_block, file, line)
  binder.eval source_block, file, line
end