Class: Lisp::Macro
Instance Attribute Summary collapse
Attributes inherited from Atom
#value
Instance Method Summary
collapse
-
#apply_to(parameters, env) ⇒ Object
-
#apply_to_without_evaluating(parameters, env) ⇒ Object
-
#compute_required_argument_count(args) ⇒ Object
-
#expand(parameters, env, should_eval) ⇒ Object
-
#initialize(name, arguments, doc, body, env) ⇒ Macro
constructor
-
#internal_apply_to(parameters, env, should_eval) ⇒ Object
-
#macro? ⇒ Boolean
-
#to_s ⇒ Object
-
#type ⇒ Object
Methods inherited from Atom
#alist?, #all?, #car, #cdr, #character?, #class?, #copy, #eq?, #evaluate, #false?, #frame?, #function?, #length, #lisp_object?, #list?, #negative?, #number?, #object?, #pair?, #positive?, #primitive?, #print_string, #quoted, #set!, #special?, #string?, #symbol?, #true?, #vector?, #zero?
Constructor Details
#initialize(name, arguments, doc, body, env) ⇒ Macro
Returns a new instance of Macro.
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/rubylisp/macro.rb', line 22
def initialize(name, arguments, doc, body, env)
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
|
Instance Attribute Details
Returns the value of attribute doc.
5
6
7
|
# File 'lib/rubylisp/macro.rb', line 5
def doc
@doc
end
|
Instance Method Details
#apply_to(parameters, env) ⇒ Object
75
76
77
|
# File 'lib/rubylisp/macro.rb', line 75
def apply_to(parameters, env)
internal_apply_to(parameters, env, false)
end
|
#apply_to_without_evaluating(parameters, env) ⇒ Object
79
80
81
|
# File 'lib/rubylisp/macro.rb', line 79
def apply_to_without_evaluating(parameters, env)
internal_apply_to(parameters, env, false)
end
|
#compute_required_argument_count(args) ⇒ Object
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 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) ⇒ Object
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/rubylisp/macro.rb', line 34
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, 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
@body.evaluate(local_env)
end
|
#internal_apply_to(parameters, env, should_eval) ⇒ Object
70
71
72
73
|
# File 'lib/rubylisp/macro.rb', line 70
def internal_apply_to(parameters, env, should_eval)
expanded_macro = expand(parameters, env, should_eval)
expanded_macro.evaluate(env)
end
|
87
88
89
|
# File 'lib/rubylisp/macro.rb', line 87
def macro?
true
end
|
83
84
85
|
# File 'lib/rubylisp/macro.rb', line 83
def to_s
"<macro: #{@name}>"
end
|
91
92
93
|
# File 'lib/rubylisp/macro.rb', line 91
def type
:macro
end
|