reference 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/reference.rb +210 -0
- metadata +37 -0
data/reference.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
# Author:: Eric Mahurin
|
3
|
+
# License:: Ruby license
|
4
|
+
|
5
|
+
# These base references are defined simply by get and set procs. The
|
6
|
+
# dereferencing methods [] (get) and []= (set) will just call these procs.
|
7
|
+
#
|
8
|
+
# require 'reference'
|
9
|
+
#
|
10
|
+
# # multiple ways to make a reference to lines in stdin/stdout
|
11
|
+
# lineref = Reference.new(method(:gets),method(:puts))
|
12
|
+
# lineref = Reference.new(proc{gets},proc{|v|puts(v)})
|
13
|
+
# line = lineref[] # line = gets
|
14
|
+
# lineref[]="hello world!" # puts("hello world!")
|
15
|
+
class Reference
|
16
|
+
|
17
|
+
# Create a reference given get and set procs.
|
18
|
+
def initialize(getter,setter)
|
19
|
+
@getter = getter
|
20
|
+
@setter = setter
|
21
|
+
end
|
22
|
+
# Get the value of the referenced thing. Optional arguments may modify
|
23
|
+
# the meaning of what is referenced.
|
24
|
+
# Will simply call the get proc for the base class.
|
25
|
+
def [](*args)
|
26
|
+
@getter[*args]
|
27
|
+
end
|
28
|
+
# Set the value of the referenced thing. The last argument (required)
|
29
|
+
# is taken as the value. Optional preceding arguments may modify the
|
30
|
+
# meaning of what is referenced.
|
31
|
+
# Will simply call the set proc for the base class.
|
32
|
+
def []=(*args)
|
33
|
+
@setter[*args]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class Binding
|
39
|
+
|
40
|
+
# Do an eval in the binding context
|
41
|
+
def eval(s,*file_line)
|
42
|
+
Kernel.eval(s,self,*file_line)
|
43
|
+
end
|
44
|
+
# Get a variable/expression (Symbol or String) in the binding context.
|
45
|
+
def variable_get(var)
|
46
|
+
eval(var.to_s)
|
47
|
+
end
|
48
|
+
# Set a variable/expression (Symbol or String) in the binding context.
|
49
|
+
def variable_set(var,value)
|
50
|
+
eval("proc{|_v| #{var} = _v}")[value]
|
51
|
+
end
|
52
|
+
# Create a reference to an assignable variable or expression that is
|
53
|
+
# accessible within the binding context.
|
54
|
+
def variable_reference(var)
|
55
|
+
Reference.new(
|
56
|
+
eval("proc { #{var} }"),
|
57
|
+
eval("proc {|_v| #{var} = _v }")
|
58
|
+
);
|
59
|
+
end
|
60
|
+
# Provide access to the object of the binding context.
|
61
|
+
def self()
|
62
|
+
eval("self")
|
63
|
+
end
|
64
|
+
# Return a Proc for the given method (Symbol or String) of the binding
|
65
|
+
# context.
|
66
|
+
def method(meth)
|
67
|
+
eval("proc{|*_a,&_b| #{meth}(*_a,&_b)}")
|
68
|
+
end
|
69
|
+
# Call the method in the binding context for anything else.
|
70
|
+
def method_missing(meth,*args,&block)
|
71
|
+
eval("proc{|*_a,&_b| #{meth}(*_a,&_b)}").call(*args,&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class Object
|
77
|
+
|
78
|
+
# This class serves dual purposes. It can act as an object Reference or
|
79
|
+
# a Reference maker (for attribute like methods of this object)
|
80
|
+
class ObjectReference < Reference
|
81
|
+
|
82
|
+
# Create an ObjectReference
|
83
|
+
def initialize(obj)
|
84
|
+
@obj = obj
|
85
|
+
end
|
86
|
+
# With no arguments, this will dereference returning the object. With
|
87
|
+
# arguments, it will create a Reference using method_missing.
|
88
|
+
def [](*args)
|
89
|
+
if args.size==0
|
90
|
+
@obj
|
91
|
+
else
|
92
|
+
method_missing(:"[]",*args)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
# Deferencing set. To set the object it will use the <tt>replace</tt>
|
96
|
+
# method of the object if available or try the <tt>become</tt> method
|
97
|
+
# (see evil.rb). This will not work on immediate objects.
|
98
|
+
def []=(obj)
|
99
|
+
if @obj.respond_to?:replace
|
100
|
+
@obj.replace(obj)
|
101
|
+
else
|
102
|
+
@obj.become(obj) # need evil.rb
|
103
|
+
end
|
104
|
+
@obj
|
105
|
+
end
|
106
|
+
# Create a reference from this method (get) and this method + "=" (set).
|
107
|
+
# <i>args</i> will start the argument list. [] and []= calls from the
|
108
|
+
# reference will fill out the remainder of the argument list for these
|
109
|
+
# methods.
|
110
|
+
def method_missing(method,*args)
|
111
|
+
get = @obj.method(method)
|
112
|
+
set = @obj.method(method.to_s<<"=")
|
113
|
+
if args.size>0
|
114
|
+
getter = proc { |*a| get[*(args+a)] }
|
115
|
+
setter = proc { |*a| set[*(args+a)] }
|
116
|
+
else
|
117
|
+
getter = get
|
118
|
+
setter = set
|
119
|
+
end
|
120
|
+
Reference.new(getter,setter)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
# Provides an easy way to create a Reference. There are several ways to do
|
125
|
+
# it:
|
126
|
+
#
|
127
|
+
# * ref { <i>symbol</i> }
|
128
|
+
# * ref { <i>expression-string</i> }
|
129
|
+
# * <i>obj</i>.ref
|
130
|
+
# * <i>obj</i>.ref.<i>method</i>(<i>arguments</i>)
|
131
|
+
# * <i>obj</i>.ref(<i>getsymbol</i>,<i>putsymbol</i>,<i>arguments</i>)
|
132
|
+
# * <i>obj</i>.ref([<i>getsymbol</i>,<i>getargs</i>],[<i>putsymbol</i>,<i>putargs</i>],<i>more-args</i>)
|
133
|
+
#
|
134
|
+
# Here are some examples:
|
135
|
+
#
|
136
|
+
# require 'reference'
|
137
|
+
# a = ("a".."h").to_a # ["a", "b", "c", "d", "e", "f", "g", "h"]
|
138
|
+
# b = a # b and a have the same object
|
139
|
+
# p = ref{:a} # reference to the variable :a
|
140
|
+
# q = a.ref # reference to the object in a
|
141
|
+
# r = ref{"a[4]"} # reference to the assignable expression a[4]
|
142
|
+
# s = a.ref[4] # reference to the [4] attribute of a
|
143
|
+
# t = a.ref.[](4) # same
|
144
|
+
# u = a.ref(:"[]",:"[]=",4) # same except set/get method names are explicit
|
145
|
+
# v = a.ref([:"[]",4],[:"[]=",4]) # same except arguments are explicit
|
146
|
+
# p[] # ["a", "b", "c", "d", "e", "f", "g", "h"]
|
147
|
+
# p[] = (0..7).to_a # [0, 1, 2, 3, 4, 5, 6, 7]
|
148
|
+
# a # [0, 1, 2, 3, 4, 5, 6, 7]
|
149
|
+
# b # ["a", "b", "c", "d", "e", "f", "g", "h"]
|
150
|
+
# q[] # ["a", "b", "c", "d", "e", "f", "g", "h"]
|
151
|
+
# q[] = (-7..0).to_a # [-7, -6, -5, -4, -3, -2, -1, 0]
|
152
|
+
# a # [0, 1, 2, 3, 4, 5, 6, 7]
|
153
|
+
# b # [-7, -6, -5, -4, -3, -2, -1, 0]
|
154
|
+
# r[] # 4
|
155
|
+
# r[] = "r" # "r"
|
156
|
+
# a # [0, 1, 2, 3, "r", 5, 6, 7]
|
157
|
+
# b # [-7, -6, -5, -4, -3, -2, -1, 0]
|
158
|
+
# # extra arg is slice length
|
159
|
+
# s[2] # [-3, -2]
|
160
|
+
# s[2] = ["s"] # ["s"]
|
161
|
+
# a # [0, 1, 2, 3, "r", 5, 6, 7]
|
162
|
+
# b # [-7, -6, -5, -4, "s", -1, 0]
|
163
|
+
# t[] # "s"
|
164
|
+
# t[] = "t" # "t"
|
165
|
+
# a # [0, 1, 2, 3, "r", 5, 6, 7]
|
166
|
+
# b # [-7, -6, -5, -4, "t", -1, 0]
|
167
|
+
# u[] # "t"
|
168
|
+
# u[] = "t" # "u"
|
169
|
+
# a # [0, 1, 2, 3, "r", 5, 6, 7]
|
170
|
+
# b # [-7, -6, -5, -4, "u", -1, 0]
|
171
|
+
# v[] # "t"
|
172
|
+
# v[] = "t" # "v"
|
173
|
+
# a # [0, 1, 2, 3, "r", 5, 6, 7]
|
174
|
+
# b # [-7, -6, -5, -4, "v", -1, 0]
|
175
|
+
#
|
176
|
+
def reference(*args,&block)
|
177
|
+
if block
|
178
|
+
args.size==0 or raise(ArgumentError,"no arguments allowed when block given")
|
179
|
+
block.binding.variable_reference(block[])
|
180
|
+
elsif args.size>0
|
181
|
+
get,set,*args = *args
|
182
|
+
if get.kind_of?Array
|
183
|
+
get,*getargs = *(get+args)
|
184
|
+
else
|
185
|
+
getargs = args
|
186
|
+
end
|
187
|
+
set ||= get.to_s<<"="
|
188
|
+
if set.kind_of?Array
|
189
|
+
set,*setargs = *(set+args)
|
190
|
+
else
|
191
|
+
setargs = args
|
192
|
+
end
|
193
|
+
get = self.method(get)
|
194
|
+
set = self.method(set)
|
195
|
+
if getargs.size>0 then getter = proc { |*a| get[*(getargs+a)] }
|
196
|
+
else getter = get
|
197
|
+
end
|
198
|
+
if setargs.size>0 then setter = proc { |*a| set[*(setargs+a)] }
|
199
|
+
else setter = set
|
200
|
+
end
|
201
|
+
Reference.new(getter,setter)
|
202
|
+
else
|
203
|
+
ObjectReference.new(self)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
alias ref reference
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
|
metadata
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10
|
3
|
+
specification_version: 1
|
4
|
+
name: reference
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.5"
|
7
|
+
date: 2005-05-08
|
8
|
+
summary: provides reference/pointer functionality of other languages
|
9
|
+
require_paths:
|
10
|
+
- "."
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project: reference
|
14
|
+
description:
|
15
|
+
autorequire: reference
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Eric Mahurin
|
29
|
+
files:
|
30
|
+
- reference.rb
|
31
|
+
test_files: []
|
32
|
+
rdoc_options: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
requirements: []
|
37
|
+
dependencies: []
|