Class: Lisp::Function
- Inherits:
-
Atom
show all
- Defined in:
- lib/rubylisp/function.rb
Instance Attribute Summary collapse
Attributes inherited from Atom
#value
Instance Method Summary
collapse
Methods inherited from Atom
#alist?, #all?, #car, #cdr, #character?, #class?, #copy, #eq?, #evaluate, #false?, #frame?, #length, #lisp_object?, #list?, #macro?, #negative?, #number?, #object?, #pair?, #positive?, #primitive?, #print_string, #quoted, #set!, #special?, #string?, #symbol?, #true?, #vector?, #zero?
Constructor Details
#initialize(name, arguments, doc, body, env) ⇒ Function
Returns a new instance of Function.
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/rubylisp/function.rb', line 23
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 arity.
5
6
7
|
# File 'lib/rubylisp/function.rb', line 5
def arity
@arity
end
|
Returns the value of attribute doc.
5
6
7
|
# File 'lib/rubylisp/function.rb', line 5
def doc
@doc
end
|
Instance Method Details
#apply_to(parameters, env) ⇒ Object
70
71
72
|
# File 'lib/rubylisp/function.rb', line 70
def apply_to(parameters, env)
internal_apply_to(parameters, env, true)
end
|
#apply_to_without_evaluating(parameters, env) ⇒ Object
74
75
76
|
# File 'lib/rubylisp/function.rb', line 74
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/function.rb', line 7
def compute_required_argument_count(args)
a = args
@arity = 0
@var_args = false
while a
if a.symbol?
@var_args = true
return
else
@arity += 1
end
a = a.cdr
end
end
|
82
83
84
|
# File 'lib/rubylisp/function.rb', line 82
def function?
true
end
|
#internal_apply_to(parameters, env, should_eval) ⇒ Object
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/function.rb', line 36
def internal_apply_to(parameters, env, should_eval)
if @var_args
raise "#{@name} expected at least #{@arity} parameters, received #{parameters.length}." if parameters.length < @arity
else
raise "#{@name} expected #{@arity} parameters, received #{parameters.length}." unless parameters.length == @arity
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_each(local_env)
end
|
78
79
80
|
# File 'lib/rubylisp/function.rb', line 78
def to_s
"<function: #{@name}>"
end
|
86
87
88
|
# File 'lib/rubylisp/function.rb', line 86
def type
:function
end
|