class Ruspea::Runtime::Lm
Attributes
arity[R]
body[R]
closure[R]
params[R]
Public Class Methods
new(params: [], body: Nill.instance, closure: Env::Empty.instance)
click to toggle source
# File lib/ruspea/runtime/lm.rb, line 5 def initialize(params: [], body: Nill.instance, closure: Env::Empty.instance) @params = params @arity = params.length @body = body @closure = closure end
Public Instance Methods
call(*args, context: nil, evaler: nil)
click to toggle source
# File lib/ruspea/runtime/lm.rb, line 12 def call(*args, context: nil, evaler: nil) context ||= Env::Empty.instance evaler ||= Ruspea::Interpreter::Evaler.new env, callable = env_and_callable_body(args, context, evaler) env.define Sym.new("%ctx"), context callable.call closure.around(env), evaler, args end
Private Instance Methods
env_and_callable_body(args, context, evaler)
click to toggle source
# File lib/ruspea/runtime/lm.rb, line 26 def env_and_callable_body(args, context, evaler) if body.respond_to? :call [ environment_with(args, context, evaler: ->(arg, _) { arg }), ->(environment, evaler, _) { body.call environment, evaler } ] else if args.length != arity raise Ruspea::Error::Arity.new(arity, args.length) end [ environment = environment_with(args, context, evaler: evaler), ->(environment, evaler, args) { evaluate(body, context: environment, evaler: evaler) } ] end end
environment_with(args, context, evaler:)
click to toggle source
# File lib/ruspea/runtime/lm.rb, line 46 def environment_with(args, context, evaler:) env = Env.new(context) args.each_with_index.reduce(env) { |env, tuple| arg, idx = tuple sym = if arg.is_a?(Ruspea::Interpreter::Form) arg.value else arg end env.tap { |e| e.define( params[idx], evaler.call(sym, context: context)) } } end
evaluate(forms, result = nil, evaler:, context:)
click to toggle source
# File lib/ruspea/runtime/lm.rb, line 64 def evaluate(forms, result = nil, evaler:, context:) return result if forms.empty? evaluate( forms.tail, evaler.call(forms.head, context: context), evaler: evaler, context: context) end