ua 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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