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
#all?, #car, #cdr, #character?, #class?, #copy, #environment?, #eof_object?, #eq?, #equal?, #eqv?, #evaluate, #false?, #frame?, #function?, #length, #lisp_object?, #list?, #negative?, #number?, #object?, #pair?, #port?, #positive?, #primitive?, #print_string, #quoted, #set!, #set_location, #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
33
|
# 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 body.
5
6
7
|
# File 'lib/rubylisp/macro.rb', line 5
def body
@body
end
|
Returns the value of attribute doc.
5
6
7
|
# File 'lib/rubylisp/macro.rb', line 5
def doc
@doc
end
|
Returns the value of attribute name.
5
6
7
|
# File 'lib/rubylisp/macro.rb', line 5
def name
@name
end
|
Instance Method Details
#apply_to(parameters, env) ⇒ Object
80
81
82
|
# 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) ⇒ Object
84
85
86
|
# 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) ⇒ 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
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
69
70
71
72
73
|
# 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
result = @body.evaluate(local_env)
result
end
|
#internal_apply_to(parameters, env, should_eval) ⇒ Object
75
76
77
78
|
# 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
|
92
93
94
|
# File 'lib/rubylisp/macro.rb', line 92
def macro?
true
end
|
88
89
90
|
# File 'lib/rubylisp/macro.rb', line 88
def to_s
"<macro: #{@name}>"
end
|
96
97
98
|
# File 'lib/rubylisp/macro.rb', line 96
def type
:macro
end
|