ua 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,284 @@
1
+ #
2
+ # = ostruct.rb: OpenStruct implementation
3
+ #
4
+ # Author:: Yukihiro Matsumoto
5
+ # Documentation:: Gavin Sinclair
6
+ #
7
+ # OpenStruct allows the creation of data objects with arbitrary attributes.
8
+ # See OpenStruct for an example.
9
+ #
10
+
11
+ #
12
+ # An OpenStruct is a data structure, similar to a Hash, that allows the
13
+ # definition of arbitrary attributes with their accompanying values. This is
14
+ # accomplished by using Ruby's metaprogramming to define methods on the class
15
+ # itself.
16
+ #
17
+ # == Examples:
18
+ #
19
+ # require 'ostruct'
20
+ #
21
+ # person = OpenStruct.new
22
+ # person.name = "John Smith"
23
+ # person.age = 70
24
+ # person.pension = 300
25
+ #
26
+ # puts person.name # -> "John Smith"
27
+ # puts person.age # -> 70
28
+ # puts person.address # -> nil
29
+ #
30
+ # An OpenStruct employs a Hash internally to store the methods and values and
31
+ # can even be initialized with one:
32
+ #
33
+ # australia = OpenStruct.new(:country => "Australia", :population => 20_000_000)
34
+ # p australia # -> <OpenStruct country="Australia" population=20000000>
35
+ #
36
+ # Hash keys with spaces or characters that would normally not be able to use for
37
+ # method calls (e.g. ()[]*) will not be immediately available on the
38
+ # OpenStruct object as a method for retrieval or assignment, but can be still be
39
+ # reached through the Object#send method.
40
+ #
41
+ # measurements = OpenStruct.new("length (in inches)" => 24)
42
+ # measurements.send("length (in inches)") # -> 24
43
+ #
44
+ # data_point = OpenStruct.new(:queued? => true)
45
+ # data_point.queued? # -> true
46
+ # data_point.send("queued?=",false)
47
+ # data_point.queued? # -> false
48
+ #
49
+ # Removing the presence of a method requires the execution the delete_field
50
+ # method as setting the property value to +nil+ will not remove the method.
51
+ #
52
+ # first_pet = OpenStruct.new(:name => 'Rowdy', :owner => 'John Smith')
53
+ # first_pet.owner = nil
54
+ # second_pet = OpenStruct.new(:name => 'Rowdy')
55
+ #
56
+ # first_pet == second_pet # -> false
57
+ #
58
+ # first_pet.delete_field(:owner)
59
+ # first_pet == second_pet # -> true
60
+ #
61
+ #
62
+ # == Implementation:
63
+ #
64
+ # An OpenStruct utilizes Ruby's method lookup structure to and find and define
65
+ # the necessary methods for properties. This is accomplished through the method
66
+ # method_missing and define_method.
67
+ #
68
+ # This should be a consideration if there is a concern about the performance of
69
+ # the objects that are created, as there is much more overhead in the setting
70
+ # of these properties compared to using a Hash or a Struct.
71
+ #
72
+ class OpenStruct
73
+ #
74
+ # Creates a new OpenStruct object. By default, the resulting OpenStruct
75
+ # object will have no attributes.
76
+ #
77
+ # The optional +hash+, if given, will generate attributes and values
78
+ # (can be a Hash, an OpenStruct or a Struct).
79
+ # For example:
80
+ #
81
+ # require 'ostruct'
82
+ # hash = { "country" => "Australia", :population => 20_000_000 }
83
+ # data = OpenStruct.new(hash)
84
+ #
85
+ # p data # -> <OpenStruct country="Australia" population=20000000>
86
+ #
87
+ def initialize(hash=nil)
88
+ @table = {}
89
+ if hash
90
+ hash.each_pair do |k, v|
91
+ k = k.to_sym
92
+ @table[k] = v
93
+ new_ostruct_member(k)
94
+ end
95
+ end
96
+ end
97
+
98
+ # Duplicate an OpenStruct object members.
99
+ def initialize_copy(orig)
100
+ super
101
+ @table = @table.dup
102
+ @table.each_key{|key| new_ostruct_member(key)}
103
+ end
104
+
105
+ #
106
+ # Converts the OpenStruct to a hash with keys representing
107
+ # each attribute (as symbols) and their corresponding values
108
+ # Example:
109
+ #
110
+ # require 'ostruct'
111
+ # data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
112
+ # data.to_h # => {:country => "Australia", :population => 20000000 }
113
+ #
114
+ def to_h
115
+ @table.dup
116
+ end
117
+
118
+ #
119
+ # Yields all attributes (as a symbol) along with the corresponding values
120
+ # or returns an enumerator if not block is given.
121
+ # Example:
122
+ #
123
+ # require 'ostruct'
124
+ # data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
125
+ # data.each_pair.to_a # => [[:country, "Australia"], [:population, 20000000]]
126
+ #
127
+ def each_pair
128
+ return to_enum __method__ unless block_given?
129
+ @table.each_pair{|p| yield p}
130
+ end
131
+
132
+ #
133
+ # Provides marshalling support for use by the Marshal library.
134
+ #
135
+ def marshal_dump
136
+ @table
137
+ end
138
+
139
+ #
140
+ # Provides marshalling support for use by the Marshal library.
141
+ #
142
+ def marshal_load(x)
143
+ @table = x
144
+ @table.each_key{|key| new_ostruct_member(key)}
145
+ end
146
+
147
+ #
148
+ # Used internally to check if the OpenStruct is able to be
149
+ # modified before granting access to the internal Hash table to be modified.
150
+ #
151
+ def modifiable
152
+ begin
153
+ @modifiable = true
154
+ rescue
155
+ raise TypeError, "can't modify frozen #{self.class}", caller(3)
156
+ end
157
+ @table
158
+ end
159
+ protected :modifiable
160
+
161
+ #
162
+ # Used internally to defined properties on the
163
+ # OpenStruct. It does this by using the metaprogramming function
164
+ # define_singleton_method for both the getter method and the setter method.
165
+ #
166
+ def new_ostruct_member(name)
167
+ name = name.to_sym
168
+ unless respond_to?(name)
169
+ define_singleton_method(name) { @table[name] }
170
+ define_singleton_method("#{name}=") { |x| modifiable[name] = x }
171
+ end
172
+ name
173
+ end
174
+ protected :new_ostruct_member
175
+
176
+ def method_missing(mid, *args) # :nodoc:
177
+ mname = mid.id2name
178
+ len = args.length
179
+ if mname.chomp!('=')
180
+ if len != 1
181
+ raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
182
+ end
183
+ modifiable[new_ostruct_member(mname)] = args[0]
184
+ elsif len == 0
185
+ @table[mid]
186
+ else
187
+ raise NoMethodError, "undefined method `#{mid}' for #{self}", caller(1)
188
+ end
189
+ end
190
+
191
+ # Returns the value of a member.
192
+ #
193
+ # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
194
+ # person[:age] # => 70, same as ostruct.age
195
+ #
196
+ def [](name)
197
+ @table[name.to_sym]
198
+ end
199
+
200
+ #
201
+ # Sets the value of a member.
202
+ #
203
+ # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
204
+ # person[:age] = 42 # => equivalent to ostruct.age = 42
205
+ # person.age # => 42
206
+ #
207
+ def []=(name, value)
208
+ modifiable[new_ostruct_member(name)] = value
209
+ end
210
+
211
+ #
212
+ # Remove the named field from the object. Returns the value that the field
213
+ # contained if it was defined.
214
+ #
215
+ # require 'ostruct'
216
+ #
217
+ # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
218
+ #
219
+ # person.delete_field('name') # => 'John Smith'
220
+ #
221
+ def delete_field(name)
222
+ sym = name.to_sym
223
+ singleton_class.__send__(:remove_method, sym, "#{name}=")
224
+ @table.delete sym
225
+ end
226
+
227
+ InspectKey = :__inspect_key__ # :nodoc:
228
+
229
+ #
230
+ # Returns a string containing a detailed summary of the keys and values.
231
+ #
232
+ def inspect
233
+ str = "#<#{self.class}"
234
+
235
+ ids = (Thread.current[InspectKey] ||= [])
236
+ if ids.include?(object_id)
237
+ return str << ' ...>'
238
+ end
239
+
240
+ ids << object_id
241
+ begin
242
+ first = true
243
+ for k,v in @table
244
+ str << "," unless first
245
+ first = false
246
+ str << " #{k}=#{v.inspect}"
247
+ end
248
+ return str << '>'
249
+ ensure
250
+ ids.pop
251
+ end
252
+ end
253
+ alias :to_s :inspect
254
+
255
+ attr_reader :table # :nodoc:
256
+ protected :table
257
+
258
+ #
259
+ # Compares this object and +other+ for equality. An OpenStruct is equal to
260
+ # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
261
+ # equal.
262
+ #
263
+ def ==(other)
264
+ return false unless other.kind_of?(OpenStruct)
265
+ @table == other.table
266
+ end
267
+
268
+ #
269
+ # Compares this object and +other+ for equality. An OpenStruct is eql? to
270
+ # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
271
+ # eql?.
272
+ #
273
+ def eql?(other)
274
+ return false unless other.kind_of?(OpenStruct)
275
+ @table.eql?(other.table)
276
+ end
277
+
278
+ # Compute a hash-code for this OpenStruct.
279
+ # Two hashes with the same content will have the same hash code
280
+ # (and will be eql?).
281
+ def hash
282
+ @table.hash
283
+ end
284
+ end
data/lib/ua/uadb.rb ADDED
@@ -0,0 +1,42 @@
1
+ module Ua
2
+ class SQLite3Table
3
+ def initialize(db, table)
4
+ require 'SQLite3'
5
+ @db, @table = db, table
6
+ @database = ::SQLite3::Database.new(@db + ".db")
7
+ end
8
+
9
+ def [](a)
10
+ case a
11
+ when lambda{|x| Integer(x) rescue false}
12
+ @database.execute "select * from #{@table} where id=?", a.to_i
13
+ when Hash
14
+ k = a.keys
15
+ x = k.map{|name| "#{name} = ?"}.join(" and ")
16
+ y = k.map{|name| a[name]}
17
+ @database.execute "select * from #{@table} where " + x, y
18
+ end
19
+ end
20
+ end
21
+
22
+ class SQLite3DB
23
+ def initialize(name)
24
+ @name = name
25
+ end
26
+ def [](a)
27
+ SQLite3Table.new(@name, a)
28
+ end
29
+ end
30
+
31
+ class SQLite3
32
+ def [](a)
33
+ SQLite3DB.new(a)
34
+ end
35
+ end
36
+
37
+ module SQLite3Support
38
+ def default_context
39
+ set "db3", SQLite3.new
40
+ end
41
+ end
42
+ end
data/lib/ua/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Ua
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ua.rb ADDED
@@ -0,0 +1,375 @@
1
+ require "ua/version"
2
+ require 'erb'
3
+ require 'ostruct'
4
+ module Ua
5
+ module Commands
6
+ end
7
+ class Application
8
+ module UAClass; end
9
+ module Apply; end
10
+ def initialize
11
+ @store = {}
12
+ @context = {}
13
+ end
14
+
15
+ def default_context
16
+ that = self
17
+ context Array, :app do |arr|
18
+ arr.map{|a| context(a, :app)}.join
19
+ end
20
+
21
+ context Apply, :app do |arr|
22
+ get(arr.stream_).map{|a|that.app a}.join
23
+ end
24
+
25
+ context String, :app do |str|
26
+ str
27
+ end
28
+
29
+ context UAClass, :app do |element|
30
+ element.render
31
+ end
32
+
33
+ context Array, :stream_add do |arr, *a|
34
+ arr.concat a
35
+ ""
36
+ end
37
+ context String, :get do |obj, *a|
38
+ context(get(obj), *a)
39
+ end
40
+
41
+ context UAClass, :stream_add do |obj, *a|
42
+ obj.stream_ ||= stream_generate
43
+ get(obj.stream_).concat a
44
+ obj.extend Apply
45
+ ""
46
+ end
47
+
48
+ context UAClass, :append_add do |obj, *a|
49
+ obj.stream_ ||= stream_generate
50
+ get(obj.stream_).concat a
51
+ ""
52
+ end
53
+ end
54
+
55
+ def make_context(a, b)
56
+ a[0] = get(a[0]).class if String === a[0] && has?(a[0])
57
+ a[0] = a[0].class unless Module === a[0]
58
+ @context[a] = b
59
+ end
60
+
61
+ def tmpid(prefix = "temp")
62
+ r = get(count = "#{prefix}.id") || 0
63
+ r += 1
64
+ set count, r
65
+ "#{prefix}.#{r}"
66
+ end
67
+
68
+ def output_by_context(a, b, *c)
69
+ r = a.singleton_class rescue a.class
70
+ r.ancestors.each{|i|
71
+ h = i.instance_method(:uacontext) rescue nil
72
+ catch(:continue){
73
+ return h.bind(a).call(b, *c) if h
74
+ }
75
+ }
76
+ r.ancestors.each{|i|
77
+ h = @context[[i, b]]
78
+ catch(:continue){
79
+ return a.instance_exec(a, *c, &h) if h
80
+ }
81
+ }
82
+ puts "Can't find a handler #{a.class} #{b}"
83
+ raise "Can't find a handler #{a.class} #{b}"
84
+ =begin
85
+ ensure
86
+
87
+ if $@
88
+ unless $@.index{|x| x=="UAException"}
89
+ $@.unshift("UAEnd")
90
+ $@.unshift("UAException")
91
+ end
92
+ l, r = $@.index("UAException"), $@.index("UAEnd")
93
+ u = $@.slice!(l..r)
94
+ u[-1, 0] = "context #{a.class} #{b}"
95
+ u += $@
96
+ $@.replace u
97
+ end
98
+ =end
99
+ end
100
+
101
+
102
+ #
103
+ # setup an output variable
104
+ #
105
+ def _parent(a)
106
+ u = @store
107
+ col = ""
108
+ arr = a.split(".")
109
+ arr[0..-2].each{|x|
110
+ col << "." << x
111
+ if u[x] == nil
112
+ u[x] = {}
113
+ elsif !u[x].respond_to?(:[])
114
+ raise "#{col} is not valid"
115
+ end
116
+ u = u[x]
117
+ }
118
+ [u, arr[-1]]
119
+ end
120
+
121
+ def set(a, b)
122
+ path, val = _parent(a)
123
+ path[val] = b
124
+ b
125
+ end
126
+
127
+ def get(a)
128
+ path, val = _parent(a)
129
+ path[val]
130
+ end
131
+
132
+ TOPLEVEL = "com.ua.root"
133
+ def go!(name = TOPLEVEL)
134
+ puts app(name)
135
+ end
136
+
137
+ def app(name = TOPLEVEL)
138
+ context(get(name), :app)
139
+ end
140
+
141
+
142
+ def context(a, b = Ua::Application.top.context, *c, &bl)
143
+ if block_given?
144
+ make_context([a, b], bl)
145
+ else
146
+ output_by_context(a, b, *c)
147
+ end
148
+ end
149
+
150
+
151
+
152
+ def make_uaclass(a, *ar, &block)
153
+ autoinit = false
154
+ block ||= begin
155
+ autoinit = true
156
+ lambda{
157
+ "<%= context(get(stream_), :app) %>"
158
+ }
159
+ end
160
+ that = self
161
+ code = block.call
162
+ codename = "proc.#{a}"
163
+ set codename, code
164
+ klass = Class.new(OpenStruct) do
165
+ include UAClass
166
+ include Enumerable
167
+ define_method(:initialize) do |*args|
168
+ begin
169
+ Ua::Application.push_app that
170
+ super(*args)
171
+ self.stream_ = that.stream_generate
172
+ self.id_ = that.tmpid("object")
173
+ that.set self.id_, self
174
+ ensure
175
+ Ua::Application.pop
176
+ end
177
+ end
178
+ def mapjoin
179
+ map{|x| yield x}.join
180
+ end
181
+ def each
182
+ get(stream_).each{|x|
183
+ yield x
184
+ }
185
+ end
186
+ define_method(:classid) do
187
+ a
188
+ end
189
+ define_method(:prototype) do
190
+ klass
191
+ end
192
+ define_method(:erb) do |text__|
193
+ begin
194
+ Ua::Application.push_app that
195
+ ERB.new(text__).result(binding)
196
+ ensure
197
+ Ua::Application.pop
198
+ end
199
+ end
200
+ define_method(:render) do
201
+ begin
202
+ Ua::Application.push_app that
203
+ erb get codename
204
+ ensure
205
+ Ua::Application.pop
206
+ end
207
+ end
208
+ define_singleton_method(:to_s) do
209
+ a
210
+ end
211
+ end
212
+ x = klass.new
213
+ klass.const_set :Singleton_, x
214
+ x
215
+ end
216
+
217
+
218
+
219
+ def stream_generate
220
+ u = tmpid
221
+ set u, []
222
+ u
223
+ end
224
+
225
+ def create(id, opt = {}, &b)
226
+ x = get(id).prototype.new
227
+ opt.each{|k, v| x.send "#{k}=", v }
228
+ x
229
+ end
230
+
231
+ def add(a = tmpid, *ar, &block)
232
+ set a, make_uaclass(a, *ar, &block)
233
+ get a
234
+ end
235
+
236
+ def delete(obj)
237
+ set obj.id_, nil
238
+ end
239
+
240
+ module ArgVoid; end
241
+
242
+ def self.push(app = ArgVoid, context = ArgVoid, controller = ArgVoid)
243
+ app = app == ArgVoid ? @app_stack.last.app : app
244
+ context = context == ArgVoid ? @app_stack.last.context : context
245
+ controller = controller == ArgVoid ? @app_stack.last.controller : controller
246
+ @app_stack.push StackFrame.new(app, context, controller)
247
+ end
248
+
249
+ def self.push_app(app)
250
+ self.push(app)
251
+ end
252
+
253
+
254
+ def self.pop
255
+ @app_stack.pop
256
+ end
257
+ def self.top
258
+ @app_stack.last
259
+ end
260
+ def self.top_app
261
+ top.app
262
+ end
263
+
264
+ app = SINGLETON_APP = new
265
+
266
+ StackFrame = Struct.new(:app, :context, :controller)
267
+ @app_stack = [StackFrame.new(app, :app, eval('self', TOPLEVEL_BINDING))]
268
+
269
+ def initialize
270
+ @store = {}
271
+ @context = {}
272
+ bootup
273
+ end
274
+
275
+ def bootup
276
+ default_context
277
+ add("com.ua.root").prototype.send :include, Ua::Application::Apply
278
+ end
279
+
280
+ app.bootup
281
+
282
+ def self.singleton
283
+ SINGLETON_APP
284
+ end
285
+
286
+ def stream(a, *b)
287
+ context(get(a), :stream_add, *b)
288
+ end
289
+
290
+ def append(a, *b)
291
+ context(get(a), :append_add, *b)
292
+ end
293
+
294
+ def self.export_commands(*names)
295
+ that = self
296
+ names.each{|name|
297
+ (Commands).send(:define_method, name) do |*a, &b|
298
+ that.top_app.send(name, *a, &b)
299
+ end
300
+ }
301
+ end
302
+
303
+ def has?(key)
304
+ get(key)
305
+ end
306
+
307
+ def stack_of(name)
308
+ stack = "stack.#{name}"
309
+ if has?(stack)
310
+ get(stack)
311
+ else
312
+ set stack, (a = [])
313
+ a
314
+ end
315
+ end
316
+
317
+
318
+ def get_local(name)
319
+ local = "local.#{name}"
320
+ return get local if has?(local)
321
+ add local
322
+ get local
323
+ end
324
+
325
+ def set_local(name, val)
326
+ local = "local.#{name}"
327
+ set local, val
328
+ val
329
+ end
330
+
331
+ def push_local(name, newval = add)
332
+ local = "local.#{name}"
333
+ stack_of(local).push get local
334
+ set local, newval
335
+ newval
336
+ end
337
+
338
+ def pop_local(name)
339
+ local = "local.#{name}"
340
+ r = get local
341
+ set local, stack_of(local).pop
342
+ r
343
+ end
344
+
345
+
346
+ export_commands :set, :go!, :add, :create,
347
+ :get, :stream, :append, :stream_generate,
348
+ :get_local, :set_local, :push_local, :pop_local, :delete
349
+
350
+ end
351
+ module Commands
352
+ def context(obj, ctxt = Ua::Application.top.context, &b)
353
+ Ua::Application.push(Ua::Application::ArgVoid,
354
+ ctxt,
355
+ self
356
+ )
357
+ Ua::Application.top_app.context(obj, ctxt, &b)
358
+ ensure
359
+ Ua::Application.pop
360
+ end
361
+ alias model add
362
+ alias view context
363
+ alias link stream
364
+ alias new create
365
+ end
366
+
367
+ end
368
+
369
+
370
+ require 'ua/uadb'
371
+ require 'ua/util'
372
+ if !(Ua.const_get(:NoConflict) rescue nil)
373
+ include Ua::Commands
374
+ include Ua::Util
375
+ end
data/test/Hello.cpp ADDED
@@ -0,0 +1,5 @@
1
+
2
+ extern "C" int __stdcall add(int a, int b){
3
+ return a + b;
4
+ }
5
+
data/test/a.db ADDED
Binary file