mirah 0.0.4-java

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.
Files changed (141) hide show
  1. data/History.txt +15 -0
  2. data/README.txt +51 -0
  3. data/Rakefile +86 -0
  4. data/bin/duby +10 -0
  5. data/bin/dubyc +10 -0
  6. data/bin/dubyp +10 -0
  7. data/bin/jrubyp +36 -0
  8. data/bin/mirah +9 -0
  9. data/bin/mirah.cmd +1 -0
  10. data/bin/mirahc +9 -0
  11. data/bin/mirahc.cmd +1 -0
  12. data/bin/mirahp +9 -0
  13. data/bin/mirahp.cmd +1 -0
  14. data/examples/ant/example-build.xml +7 -0
  15. data/examples/appengine/Rakefile +19 -0
  16. data/examples/appengine/Readme +29 -0
  17. data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
  18. data/examples/appengine/src/org/mirah/list.dhtml +15 -0
  19. data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
  20. data/examples/bintrees.mirah +66 -0
  21. data/examples/construction.mirah +8 -0
  22. data/examples/dynamic.mirah +17 -0
  23. data/examples/edb.mirah +3 -0
  24. data/examples/fib.mirah +16 -0
  25. data/examples/fields.mirah +22 -0
  26. data/examples/fractal.mirah +55 -0
  27. data/examples/java_thing.mirah +13 -0
  28. data/examples/plugins/appengine/Rakefile +55 -0
  29. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
  30. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
  31. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
  32. data/examples/simple_class.mirah +12 -0
  33. data/examples/sort_closure.mirah +7 -0
  34. data/examples/swing.mirah +20 -0
  35. data/examples/tak.mirah +15 -0
  36. data/examples/test.edb +9 -0
  37. data/examples/wiki/Rakefile +18 -0
  38. data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
  39. data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
  40. data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
  41. data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
  42. data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
  43. data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
  44. data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
  45. data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
  46. data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
  47. data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
  48. data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
  49. data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
  50. data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
  51. data/examples/wiki/war/app.yaml +21 -0
  52. data/examples/wiki/war/public/favicon.ico +0 -0
  53. data/examples/wiki/war/public/images/appengine_duby.png +0 -0
  54. data/examples/wiki/war/public/images/back.gif +0 -0
  55. data/examples/wiki/war/public/images/dir.gif +0 -0
  56. data/examples/wiki/war/public/images/file.gif +0 -0
  57. data/examples/wiki/war/public/javascripts/prettify.js +61 -0
  58. data/examples/wiki/war/public/robots.txt +0 -0
  59. data/examples/wiki/war/public/stylesheets/main.css +156 -0
  60. data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
  61. data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
  62. data/examples/wiki/war/public/stylesheets/source.css +21 -0
  63. data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
  64. data/examples/wiki/war/public/wmd/images/bg.png +0 -0
  65. data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
  66. data/examples/wiki/war/public/wmd/images/bold.png +0 -0
  67. data/examples/wiki/war/public/wmd/images/code.png +0 -0
  68. data/examples/wiki/war/public/wmd/images/h1.png +0 -0
  69. data/examples/wiki/war/public/wmd/images/hr.png +0 -0
  70. data/examples/wiki/war/public/wmd/images/img.png +0 -0
  71. data/examples/wiki/war/public/wmd/images/italic.png +0 -0
  72. data/examples/wiki/war/public/wmd/images/link.png +0 -0
  73. data/examples/wiki/war/public/wmd/images/ol.png +0 -0
  74. data/examples/wiki/war/public/wmd/images/redo.png +0 -0
  75. data/examples/wiki/war/public/wmd/images/separator.png +0 -0
  76. data/examples/wiki/war/public/wmd/images/ul.png +0 -0
  77. data/examples/wiki/war/public/wmd/images/undo.png +0 -0
  78. data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
  79. data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
  80. data/examples/wiki/war/public/wmd/showdown.js +421 -0
  81. data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
  82. data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
  83. data/examples/wiki/war/public/wmd/wmd.js +73 -0
  84. data/javalib/JRubyParser.jar +0 -0
  85. data/javalib/dynalang-invoke-0.1.jar +0 -0
  86. data/javalib/mirah-bootstrap.jar +0 -0
  87. data/javalib/mirah-parser.jar +0 -0
  88. data/lib/duby.rb +2 -0
  89. data/lib/mirah.rb +338 -0
  90. data/lib/mirah/appengine_tasks.rb +146 -0
  91. data/lib/mirah/ast.rb +615 -0
  92. data/lib/mirah/ast/call.rb +307 -0
  93. data/lib/mirah/ast/class.rb +311 -0
  94. data/lib/mirah/ast/flow.rb +364 -0
  95. data/lib/mirah/ast/intrinsics.rb +470 -0
  96. data/lib/mirah/ast/literal.rb +154 -0
  97. data/lib/mirah/ast/local.rb +89 -0
  98. data/lib/mirah/ast/method.rb +360 -0
  99. data/lib/mirah/ast/scope.rb +208 -0
  100. data/lib/mirah/ast/structure.rb +226 -0
  101. data/lib/mirah/ast/type.rb +130 -0
  102. data/lib/mirah/compiler.rb +341 -0
  103. data/lib/mirah/env.rb +33 -0
  104. data/lib/mirah/jvm/base.rb +258 -0
  105. data/lib/mirah/jvm/compiler.rb +885 -0
  106. data/lib/mirah/jvm/method_lookup.rb +203 -0
  107. data/lib/mirah/jvm/source_compiler.rb +737 -0
  108. data/lib/mirah/jvm/source_generator/builder.rb +444 -0
  109. data/lib/mirah/jvm/source_generator/loops.rb +110 -0
  110. data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
  111. data/lib/mirah/jvm/source_generator/typer.rb +11 -0
  112. data/lib/mirah/jvm/typer.rb +151 -0
  113. data/lib/mirah/jvm/types.rb +416 -0
  114. data/lib/mirah/jvm/types/basic_types.rb +33 -0
  115. data/lib/mirah/jvm/types/boolean.rb +17 -0
  116. data/lib/mirah/jvm/types/enumerable.rb +65 -0
  117. data/lib/mirah/jvm/types/extensions.rb +86 -0
  118. data/lib/mirah/jvm/types/factory.rb +186 -0
  119. data/lib/mirah/jvm/types/floats.rb +86 -0
  120. data/lib/mirah/jvm/types/integers.rb +171 -0
  121. data/lib/mirah/jvm/types/intrinsics.rb +376 -0
  122. data/lib/mirah/jvm/types/literals.rb +74 -0
  123. data/lib/mirah/jvm/types/methods.rb +614 -0
  124. data/lib/mirah/jvm/types/number.rb +143 -0
  125. data/lib/mirah/nbcompiler.rb +29 -0
  126. data/lib/mirah/plugin/edb.rb +29 -0
  127. data/lib/mirah/plugin/gwt.rb +173 -0
  128. data/lib/mirah/plugin/java.rb +55 -0
  129. data/lib/mirah/transform.rb +266 -0
  130. data/lib/mirah/transform2.rb +728 -0
  131. data/lib/mirah/typer.rb +407 -0
  132. data/lib/mirah_task.rb +107 -0
  133. data/test/test_ast.rb +359 -0
  134. data/test/test_compilation.rb +112 -0
  135. data/test/test_env.rb +42 -0
  136. data/test/test_gwt.rb +58 -0
  137. data/test/test_java_typer.rb +183 -0
  138. data/test/test_javac_compiler.rb +63 -0
  139. data/test/test_jvm_compiler.rb +2607 -0
  140. data/test/test_typer.rb +221 -0
  141. metadata +235 -0
@@ -0,0 +1,8 @@
1
+ import "java.lang.StringBuffer"
2
+ import "java.util.ArrayList"
3
+
4
+ list = ArrayList.new
5
+ sb = StringBuffer.new("Hello")
6
+ sb.append(", world")
7
+ list.add(sb)
8
+ puts list
@@ -0,0 +1,17 @@
1
+ # Example of using a dynamic type in a method definition
2
+ def foo(a:dynamic)
3
+ puts "I got a #{a.getClass.getName} of size #{a.size}"
4
+ end
5
+
6
+ class SizeThing
7
+ def initialize(size:int)
8
+ @size = size
9
+ end
10
+
11
+ def size
12
+ @size
13
+ end
14
+ end
15
+
16
+ foo([1,2,3])
17
+ foo(SizeThing.new(12))
@@ -0,0 +1,3 @@
1
+ def_edb :render, 'test.edb'
2
+ @message = "Hello"
3
+ puts render
@@ -0,0 +1,16 @@
1
+ def fib(a:int)
2
+ if a < 2
3
+ a
4
+ else
5
+ fib(a - 1) + fib(a - 2)
6
+ end
7
+ end
8
+
9
+ def bench(n:int)
10
+ n.times do
11
+ time_start = System.currentTimeMillis
12
+ puts "fib(45): #{fib(45)}\nTotal time: #{System.currentTimeMillis - time_start}"
13
+ end
14
+ end
15
+
16
+ bench 10
@@ -0,0 +1,22 @@
1
+ import 'java.util.ArrayList'
2
+
3
+ class Bar
4
+ def initialize
5
+ @a = ArrayList(nil)
6
+ end
7
+
8
+ def list(a:ArrayList)
9
+ @a = a
10
+ end
11
+
12
+ def foo
13
+ puts @a
14
+ end
15
+ end
16
+
17
+ b = Bar.new
18
+ list = ArrayList.new
19
+ list.add('hello')
20
+ list.add('world')
21
+ b.list(list)
22
+ b.foo
@@ -0,0 +1,55 @@
1
+ def run
2
+ puts "Rendering"
3
+ y = -39.0
4
+ while y <= 39.0
5
+ puts
6
+ x = -39.0
7
+ while x <= 39.0
8
+ i = iterate(x/40.0,y/40.0)
9
+ if (i == 0)
10
+ print "*"
11
+ else
12
+ print " "
13
+ end
14
+ x += 1
15
+ end
16
+ y += 1
17
+ end
18
+ puts
19
+ end
20
+
21
+ def iterate(x:double,y:double)
22
+ cr = y-0.5
23
+ ci = x
24
+ zi = 0.0
25
+ zr = 0.0
26
+ i = 0
27
+
28
+ result = 0
29
+ while true
30
+ i += 1
31
+ temp = zr * zi
32
+ zr2 = zr * zr
33
+ zi2 = zi * zi
34
+ zr = zr2 - zi2 + cr
35
+ zi = temp + temp + ci
36
+ if (zi2 + zr2 > 16)
37
+ result = i
38
+ break
39
+ end
40
+ if (i > 1000)
41
+ result = 0
42
+ break
43
+ end
44
+ end
45
+
46
+ result
47
+ end
48
+
49
+ i = 0
50
+ while i < 10
51
+ start = System.currentTimeMillis
52
+ run
53
+ puts "Time: #{(System.currentTimeMillis - start) / 1000.0}"
54
+ i += 1
55
+ end
@@ -0,0 +1,13 @@
1
+ import "java.lang.System"
2
+
3
+ def foo
4
+ home = System.getProperty "java.home"
5
+ System.setProperty "hello.world", "something"
6
+ hello = System.getProperty "hello.world"
7
+
8
+ puts home
9
+ puts hello
10
+ end
11
+
12
+ puts "Hello world!"
13
+ foo
@@ -0,0 +1,55 @@
1
+ require 'ant'
2
+ require 'appengine-sdk'
3
+
4
+ $: << '../../../lib'
5
+ require 'mirah_task'
6
+
7
+ JUNIT_JAR = '../../../javalib/junit.jar'
8
+ TESTING_JARS = [AppEngine::SDK::API_JAR, AppEngine::SDK::LABS_JAR, JUNIT_JAR] +
9
+ AppEngine::SDK::RUNTIME_JARS.reject {|j| j =~ /appengine-local-runtime/}
10
+ TESTING_JARS.each {|jar| $CLASSPATH << jar}
11
+
12
+ # Duby.compiler_options = ['-V']
13
+
14
+ task :default => :test
15
+
16
+ task :init do
17
+ mkdir_p 'dist'
18
+ mkdir_p 'build'
19
+ end
20
+
21
+ task :clean do
22
+ ant.delete :quiet => true, :dir => 'build'
23
+ ant.delete :quiet => true, :dir => 'dist'
24
+ end
25
+
26
+ task :compile => :init do
27
+ # build the Duby sources
28
+ puts "Compiling Duby sources"
29
+ mirahc 'com/google/appengine', :dir => 'src', :dest => 'build'
30
+ end
31
+
32
+ task :compile_test => :jar do
33
+ puts "Compiling Duby tests"
34
+ mirahc 'com/google/appengine', :dir => 'test', :dest => 'test',
35
+ :options => ['--classpath', Dir.pwd + "/dist/dubydatastore.jar"]
36
+ end
37
+
38
+ task :jar => :compile do
39
+ ant.jar :jarfile => 'dist/dubydatastore.jar' do
40
+ fileset :dir => 'lib'
41
+ fileset :dir => 'build'
42
+ end
43
+ end
44
+
45
+ task :test => :compile_test do
46
+ ant.junit :haltonfailure => 'true', :fork => 'true' do
47
+ classpath :path => (TESTING_JARS + ['build', 'test']).join(":")
48
+ batchtest do
49
+ fileset :dir => "test" do
50
+ include :name => '**/*Test.class'
51
+ end
52
+ formatter :type => 'plain', :usefile => 'false'
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,375 @@
1
+ module AppEngine
2
+ class DubyDatastorePlugin
3
+ @models = {}
4
+
5
+ TypeMap = {
6
+ 'Category' => 'String',
7
+ 'Email' => 'String',
8
+ 'Link' => 'String',
9
+ 'PhoneNumber' => 'String',
10
+ 'PostalAddress' => 'String',
11
+ 'Text' => 'String',
12
+ 'Blob' => 'byte[]',
13
+ 'ShortBlob' => 'byte[]',
14
+ 'Rating' => 'int',
15
+ 'Long' => 'long',
16
+ 'Double' => 'double',
17
+ 'Boolean' => 'boolean'
18
+ }
19
+
20
+ Primitives = ['Long', 'Double', 'Boolean', 'Rating']
21
+
22
+ Boxes = {
23
+ 'int' => 'Integer',
24
+ 'boolean' => 'Boolean',
25
+ 'long' => 'Long',
26
+ 'double' => 'Double',
27
+ }
28
+
29
+ Defaults = {
30
+ 'Rating' => '0',
31
+ 'Long' => 'long(0)',
32
+ 'Double' => '0.0',
33
+ 'Boolean' => 'false',
34
+ 'Blob' => 'byte[].cast(nil)',
35
+ 'ShortBlob' => 'byte[].cast(nil)',
36
+ }
37
+
38
+ Conversions = {
39
+ 'Category' => 'getCategory',
40
+ 'Email' => 'getEmail',
41
+ 'Link' => 'getValue',
42
+ 'PhoneNumber' => 'getNumber',
43
+ 'PostalAddress' => 'getAddress',
44
+ 'Text' => 'getValue',
45
+ 'Blob' => 'getBytes',
46
+ 'ShortBlob' => 'getBytes',
47
+ 'Long' => 'longValue',
48
+ 'Double' => 'doubleValue',
49
+ 'Boolean' => 'booleanValue',
50
+ 'Rating' => 'getRating',
51
+ }
52
+
53
+ class ModelState
54
+ include Duby::AST
55
+ attr_reader :kind, :query, :read, :save, :transformer
56
+
57
+ def initialize(transformer, klass, parent, position, ast)
58
+ @transformer = transformer
59
+ @kind = klass.name.split('.')[-1]
60
+ init_query(klass.name, parent, position, ast)
61
+ init_static(parent, ast)
62
+ init_read(parent, position, ast)
63
+ init_save(parent, position, ast)
64
+ end
65
+
66
+ def init_query(classname, parent, position, ast)
67
+ name = "#{classname}$Query"
68
+ @query = ClassDefinition.new(parent, position, name) do |classdef|
69
+ queryinit = <<-EOF
70
+ def initialize; end
71
+
72
+ def kind
73
+ "#{kind}"
74
+ end
75
+
76
+ def first
77
+ it = _prepare.asIterator
78
+ if it.hasNext
79
+ e = Entity(it.next)
80
+ m = #{kind}.new
81
+ m._read_from(e)
82
+ m
83
+ else
84
+ #{kind}(nil)
85
+ end
86
+ end
87
+
88
+ def run
89
+ entities = _prepare.asList(_options)
90
+ models = #{kind}[entities.size]
91
+ it = entities.iterator
92
+ i = 0
93
+ while (it.hasNext)
94
+ e = Entity(it.next)
95
+ m = #{kind}.new
96
+ m._read_from(e)
97
+ models[i] = m
98
+ i += 1
99
+ end
100
+ models
101
+ end
102
+
103
+ def sort(name:String)
104
+ sort(name, false)
105
+ end
106
+
107
+ def sort(name:String, descending:boolean)
108
+ _sort(name, descending)
109
+ self
110
+ end
111
+ EOF
112
+ [Duby::AST.type(nil, 'com.google.appengine.ext.duby.db.DQuery'),
113
+ eval(classdef, queryinit)]
114
+ end
115
+ ast << @query
116
+ end
117
+
118
+ def init_read(parent, position, ast)
119
+ @read = eval(parent, <<-EOF)
120
+ def _read_from(e:Entity)
121
+ self.entity = e
122
+ nil
123
+ end
124
+ EOF
125
+ ast << @read
126
+ get_properties = eval(parent, <<-EOF)
127
+ def properties
128
+ result = super()
129
+ nil
130
+ result
131
+ end
132
+ EOF
133
+ @get_properties = get_properties.body.children[1] =
134
+ Duby::AST::Body.new(get_properties.body, position)
135
+ ast << get_properties
136
+ update = eval(parent, <<-EOF)
137
+ def update(properties:Map)
138
+ nil
139
+ self
140
+ end
141
+ EOF
142
+ @update = update.body.children[0] = Body.new(update.body, position) {[]}
143
+ ast << update
144
+ end
145
+
146
+ def init_save(parent, position, ast)
147
+ @save = eval(parent, <<-EOF)
148
+ def _save_to(e:Entity)
149
+ end
150
+ EOF
151
+ @save.body = Body.new(@save, position) {[]}
152
+ ast << @save
153
+ end
154
+
155
+ def init_static(parent, ast)
156
+ # TODO These imports don't work any more. Figure out how to fix that.
157
+ scope = ast.static_scope
158
+ package = "#{scope.package}." unless scope.package.empty?
159
+ scope.import('java.util.Map', 'Map')
160
+ scope.import("#{package}#{kind}$Query", "#{kind}__Query__")
161
+ %w( Entity Blob Category Email GeoPt IMHandle Key
162
+ Link PhoneNumber PostalAddress Rating ShortBlob
163
+ Text KeyFactory EntityNotFoundException ).each do |name|
164
+ scope.import("com.google.appengine.api.datastore.#{name}", name)
165
+ end
166
+ ast << eval(parent, <<-EOF)
167
+ def initialize
168
+ super
169
+ end
170
+
171
+ def initialize(key_name:String)
172
+ super
173
+ end
174
+
175
+ def initialize(parent:Model)
176
+ super
177
+ end
178
+
179
+ def initialize(parent:Key)
180
+ super
181
+ end
182
+
183
+ def initialize(parent:Model, key_name:String)
184
+ super
185
+ end
186
+
187
+ def initialize(parent:Key, key_name:String)
188
+ super
189
+ end
190
+
191
+ def self.get(key:Key)
192
+ begin
193
+ m = #{kind}.new
194
+ m._read_from(Model._datastore.get(key))
195
+ m
196
+ rescue EntityNotFoundException
197
+ nil
198
+ end
199
+ end
200
+
201
+ def self.get(key_name:String)
202
+ get(KeyFactory.createKey("#{kind}", key_name))
203
+ end
204
+
205
+ def self.get(id:long)
206
+ get(KeyFactory.createKey("#{kind}", id))
207
+ end
208
+
209
+ def self.get(parent:Key, key_name:String)
210
+ get(KeyFactory.createKey(parent, "#{kind}", key_name))
211
+ end
212
+
213
+ def self.get(parent:Key, id:long)
214
+ get(KeyFactory.createKey(parent, "#{kind}", id))
215
+ end
216
+
217
+ def self.get(parent:Model, key_name:String)
218
+ get(KeyFactory.createKey(parent.key, "#{kind}", key_name))
219
+ end
220
+
221
+ def self.get(parent:Model, id:long)
222
+ get(KeyFactory.createKey(parent.key, "#{kind}", id))
223
+ end
224
+
225
+ def self.all
226
+ #{kind}__Query__.new
227
+ end
228
+ EOF
229
+ end
230
+
231
+ def eval(parent, src)
232
+ transformer.eval(src, __FILE__, parent)
233
+ end
234
+
235
+ def extend_query(code)
236
+ query.body << eval(query.body, code)
237
+ end
238
+
239
+ def extend_update(code)
240
+ @update << eval(@update, code)
241
+ end
242
+
243
+ def extend_get_properties(code)
244
+ @get_properties << eval(@get_properties, code)
245
+ end
246
+
247
+ def extend_read(code)
248
+ code = 'e=nil;' + code
249
+ eval(read.body, code).children[1..-1].each do |node|
250
+ read.body << node
251
+ end
252
+ end
253
+
254
+ def extend_save(code)
255
+ code = 'e=nil;' + code
256
+ eval(save.body, code).children[1..-1].each do |node|
257
+ save.body << node
258
+ end
259
+ end
260
+ end
261
+
262
+ def self.find_class(node)
263
+ node = node.parent until Duby::AST::ClassDefinition === node
264
+ node
265
+ end
266
+
267
+ def self.to_datastore(type, value)
268
+ if Primitives.include?(type)
269
+ "#{type}.new(#{value})"
270
+ elsif TypeMap.include?(type)
271
+ "(#{value} ? #{type}.new(#{value}) : nil)"
272
+ else
273
+ value
274
+ end
275
+ end
276
+
277
+ def self.from_datastore(type, value)
278
+ duby_type = TypeMap[type]
279
+ if duby_type
280
+ default = Defaults.fetch(type, "#{duby_type}(nil)")
281
+ conversion = Conversions[type]
282
+ "(#{value} ? #{type}(#{value}).#{conversion} : #{default})"
283
+ else
284
+ "#{type}(#{value})"
285
+ end
286
+ end
287
+
288
+
289
+ def self.add_property(name, type, transformer, fcall)
290
+ if transformer.state != @state
291
+ reset
292
+ @state = transformer.state
293
+ end
294
+ parent = fcall.parent
295
+ name = name.literal
296
+ type = type.name
297
+ type = 'Long' if type == 'Integer'
298
+
299
+ result = Duby::AST::ScopedBody.new(parent, fcall.position) {[]}
300
+ result.static_scope = fcall.scope.static_scope
301
+ klass = find_class(parent)
302
+ unless @models[klass]
303
+ @models[klass] = ModelState.new(
304
+ transformer, klass, parent, fcall.position, result)
305
+ end
306
+ model = @models[klass]
307
+
308
+ duby_type = TypeMap.fetch(type, type)
309
+ coercion = "coerce_" + duby_type.downcase.sub("[]", "s")
310
+
311
+ if duby_type == 'List'
312
+ model.extend_query(<<-EOF)
313
+ def #{name}(value:Object)
314
+ returns :void
315
+ _query.addFilter("#{name}", _eq_op, value)
316
+ end
317
+ EOF
318
+ else
319
+ model.extend_query(<<-EOF)
320
+ def #{name}(value:#{duby_type})
321
+ returns :void
322
+ _query.addFilter("#{name}", _eq_op, #{to_datastore(type, 'value')})
323
+ end
324
+ EOF
325
+ end
326
+ temp = transformer.tmp
327
+
328
+ model.extend_read(<<-EOF)
329
+ #{temp} = e.getProperty("#{name}")
330
+ @#{name} = #{from_datastore(type, temp)}
331
+ EOF
332
+
333
+ model.extend_save(<<-EOF)
334
+ e.setProperty("#{name}", #{to_datastore(type, '@' + name)})
335
+ EOF
336
+
337
+ model.extend_update(<<-EOF)
338
+ self.#{name} = properties.get("#{name}") if properties.containsKey("#{name}")
339
+ EOF
340
+
341
+ model.extend_get_properties(<<-EOF)
342
+ result.put("#{name}", #{maybe_box(duby_type, 'self.' + name)})
343
+ EOF
344
+
345
+ result << model.eval(parent, <<-EOF)
346
+ def #{name}
347
+ @#{name}
348
+ end
349
+
350
+ def #{name}=(value:#{duby_type})
351
+ @#{name} = value
352
+ end
353
+
354
+ def #{name}=(value:Object)
355
+ self.#{name} = #{coercion}(value)
356
+ end
357
+ EOF
358
+
359
+ result
360
+ end
361
+
362
+ def self.maybe_box(duby_type, value)
363
+ if Boxes.include?(duby_type)
364
+ "#{Boxes[duby_type]}.valueOf(#{value})"
365
+ else
366
+ value
367
+ end
368
+ end
369
+
370
+ def self.reset
371
+ @models = {}
372
+ end
373
+ end
374
+ ::Duby.plugins << DubyDatastorePlugin
375
+ end