class Core::Loader::Context
- public
Public Class Methods
load(path:, root:, type:, target:, strict:)
click to toggle source
# File lib/core/loader/context.rb, line 13 def load(path:, root:, type:, target:, strict:) new(path: path, root: root, type: type, target: target, strict: strict).load end
new(path:, root:, type:, target:, strict:)
click to toggle source
# File lib/core/loader/context.rb, line 18 def initialize(path:, root:, type:, target:, strict:) @path = Pathname(path) @root = Pathname(root) @type = type.to_sym @target = target @strict = strict prepare_to_load! end
Public Instance Methods
load()
click to toggle source
- public
# File lib/core/loader/context.rb, line 29 def load eval(@path.read, binding, @path.to_s) end
Private Instance Methods
complete_expression?(string)
click to toggle source
Based on github.com/banister/method_source.
# File lib/core/loader/context.rb, line 128 def complete_expression?(string) original_verbose = $VERBOSE $VERBOSE = nil catch :valid do eval "BEGIN{throw :valid}\n#{string}" end true rescue ::SyntaxError false ensure $VERBOSE = original_verbose end
extract_block_inner_source(block, path)
click to toggle source
# File lib/core/loader/context.rb, line 79 def extract_block_inner_source(block, path) source = extract_block_source(block, path).strip if source.end_with?("end") scan_to_complete_expression(source, "do", -4, path) elsif source.end_with?("}") scan_to_complete_expression(source, "{", -2, path) else # We should never get here, but raise an error just to be clear. # raise "could not parse inner source of `#{path}`" end end
extract_block_source(block, path)
click to toggle source
# File lib/core/loader/context.rb, line 93 def extract_block_source(block, path) lineno = block.source_location[1] lines = path.each_line.to_a[(lineno - 1)..] lines.count.times do |index| possible_source = lines.take(index + 1).join if complete_expression?(possible_source) return possible_source end end # We should never get here, but raise an error just to be clear. # raise "could not find a complete expression in `#{path}`" end
prepare_to_load!()
click to toggle source
# File lib/core/loader/context.rb, line 33 def prepare_to_load! @target.makeables.each do |makeable| define_singleton_method(makeable) do |*name, **kwargs, &block| if @strict && makeable != @type raise "expected to define an object of type `#{@type}` but was `#{makeable}` (#{@path})" end definable_path = Pathname(@path.to_s.gsub(@root.to_s, "")) expected_name = definable_path.dirname.join( definable_path.basename(definable_path.extname) ).to_s.split("/").reject(&:empty?).compact.map(&:to_sym) if name.empty? name = expected_name elsif @strict && name != expected_name raise "expected to define an object named `#{expected_name.join(", ")}` but was `#{name.join(", ")}` (#{@path})" end path, line = caller(1..1).first.split(":", 3) location = Core::Define::Location.new(path: path, line: line) defined = @target.make(makeable, *name, __location__: location, **kwargs) if block header = @path.read.each_line.take(block.source_location[1] - 1).join source = extract_block_inner_source(block, @path) type = case defined when ::Class "class" when ::Module "module" end eval_source = <<~SOURCE #{header}#{type} #{defined}#{source} end SOURCE eval(eval_source, TOPLEVEL_BINDING, @path.to_s) end defined end end end
scan_to_complete_expression(source, matcher, ending_offset, path)
click to toggle source
# File lib/core/loader/context.rb, line 110 def scan_to_complete_expression(source, matcher, ending_offset, path) source.scan(matcher) do offset = $~.offset(0)[0] + 2 possible_inner_source = source[offset..ending_offset] if complete_expression?(possible_inner_source) return possible_inner_source end end # We should never get here, but raise an error just to be clear. # raise "could not find a complete expression for `#{matcher}` in `#{path}`" end