class Lisp::Macro
Attributes
body[R]
doc[R]
name[R]
Public Class Methods
new(name, arguments, doc, body, env)
click to toggle source
# File lib/rubylisp/macro.rb, line 22 def initialize(name, arguments, doc, body, env) #puts "Macro#initialize #{name} #{arguments.to_a}" sig = ([name] << arguments.to_a).flatten @doc = "(#{(sig.collect {|e| e.to_s}).join(" ")})" @name = name @arguments = arguments @doc = [@doc, doc].join("\n\n") unless doc.nil? || doc.to_s.empty? @body = body @env = env @local_env = nil compute_required_argument_count(@arguments) end
Public Instance Methods
apply_to(parameters, env)
click to toggle source
# File lib/rubylisp/macro.rb, line 80 def apply_to(parameters, env) internal_apply_to(parameters, env, false) end
apply_to_without_evaluating(parameters, env)
click to toggle source
# File lib/rubylisp/macro.rb, line 84 def apply_to_without_evaluating(parameters, env) internal_apply_to(parameters, env, false) end
compute_required_argument_count(args)
click to toggle source
# File lib/rubylisp/macro.rb, line 7 def compute_required_argument_count(args) a = args @required_argument_count = 0 @var_args = false while a if a.symbol? @var_args = true return else @required_argument_count += 1 end a = a.cdr end end
expand(parameters, env, should_eval)
click to toggle source
# File lib/rubylisp/macro.rb, line 35 def expand(parameters, env, should_eval) if @var_args return Lisp::Debug.process_error("#{@name} expected at least #{@required_argument_count} parameters, received #{parameters.length}.", env) if parameters.length < @required_argument_count else return Lisp::Debug.process_error("#{@name} expected #{@required_argument_count} parameters, received #{parameters.length}.", env) unless parameters.length == @required_argument_count end local_env = EnvironmentFrame.extending(@env, @name, env.frame) self_sym = Symbol.named("self") if env.frame local_env.bind_locally(self_sym, env.frame) elsif env.local_binding_for(self_sym) local_env.bind_locally(self_sym, env.value_of(self_sym)) end arg = @arguments param = parameters accumulating_arg = nil accumulated_params = [] while !param.nil? param_value = should_eval ? param.car.evaluate(env) : param.car if accumulating_arg accumulated_params << param_value else local_env.bind_locally(arg.car, param_value) unless arg.car.nil? end param = param.cdr arg = arg.cdr unless accumulating_arg accumulating_arg = arg if arg.symbol? end local_env.bind_locally(accumulating_arg, Lisp::ConsCell.array_to_list(accumulated_params)) if accumulating_arg #puts "expanding #{@name}" #puts " #{@body.print_string}" result = @body.evaluate(local_env) #puts " #{result.print_string}" result end
internal_apply_to(parameters, env, should_eval)
click to toggle source
# File lib/rubylisp/macro.rb, line 75 def internal_apply_to(parameters, env, should_eval) expanded_macro = expand(parameters, env, should_eval) expanded_macro.evaluate(env) end
macro?()
click to toggle source
# File lib/rubylisp/macro.rb, line 92 def macro? true end
to_s()
click to toggle source
# File lib/rubylisp/macro.rb, line 88 def to_s "<macro: #{@name}>" end
type()
click to toggle source
# File lib/rubylisp/macro.rb, line 96 def type :macro end