mirah 0.0.5-java → 0.0.6-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 (63) hide show
  1. data/History.txt +33 -0
  2. data/README.txt +2 -3
  3. data/Rakefile +5 -0
  4. data/bin/duby +0 -0
  5. data/bin/dubyc +0 -0
  6. data/bin/dubyp +0 -0
  7. data/bin/jrubyp +0 -0
  8. data/bin/mirah +0 -0
  9. data/bin/mirah.cmd +14 -14
  10. data/bin/mirahc +0 -0
  11. data/bin/mirahc.cmd +14 -14
  12. data/bin/mirahp +0 -0
  13. data/bin/mirahp.cmd +14 -14
  14. data/examples/Dynamic.class +0 -0
  15. data/examples/SizeThing.class +0 -0
  16. data/examples/plugins/appengine/Rakefile +3 -1
  17. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +385 -0
  18. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +58 -15
  19. data/examples/wiki/war/public/javascripts/prettify.js +0 -0
  20. data/examples/wiki/war/public/stylesheets/prettify.css +0 -0
  21. data/javalib/dynalink-0.1.jar +0 -0
  22. data/javalib/jsr292-mock.jar +0 -0
  23. data/javalib/mirah-bootstrap.jar +0 -0
  24. data/javalib/mirah-parser.jar +0 -0
  25. data/lib/mirah.rb +45 -25
  26. data/lib/mirah/ast.rb +81 -27
  27. data/lib/mirah/ast/call.rb +62 -71
  28. data/lib/mirah/ast/class.rb +23 -26
  29. data/lib/mirah/ast/flow.rb +38 -62
  30. data/lib/mirah/ast/intrinsics.rb +59 -37
  31. data/lib/mirah/ast/literal.rb +16 -14
  32. data/lib/mirah/ast/local.rb +8 -8
  33. data/lib/mirah/ast/method.rb +33 -19
  34. data/lib/mirah/ast/structure.rb +54 -13
  35. data/lib/mirah/ast/type.rb +8 -11
  36. data/lib/mirah/compiler.rb +86 -0
  37. data/lib/mirah/errors.rb +60 -0
  38. data/lib/mirah/jvm/base.rb +5 -11
  39. data/lib/mirah/jvm/compiler.rb +12 -1
  40. data/lib/mirah/jvm/source_compiler.rb +10 -2
  41. data/lib/mirah/jvm/source_generator/builder.rb +3 -1
  42. data/lib/mirah/jvm/source_generator/precompile.rb +6 -0
  43. data/lib/mirah/jvm/typer.rb +6 -1
  44. data/lib/mirah/jvm/types.rb +8 -0
  45. data/lib/mirah/jvm/types/factory.rb +34 -10
  46. data/lib/mirah/jvm/types/intrinsics.rb +12 -5
  47. data/lib/mirah/jvm/types/methods.rb +5 -9
  48. data/lib/mirah/plugin/gwt.rb +3 -2
  49. data/lib/mirah/transform.rb +68 -10
  50. data/lib/mirah/transform2.rb +10 -1
  51. data/lib/mirah/typer.rb +5 -10
  52. data/lib/mirah/version.rb +1 -1
  53. data/test/test_compilation.rb +1 -1
  54. data/test/test_java_typer.rb +10 -0
  55. data/test/test_javac_compiler.rb +4 -2
  56. data/test/test_jvm_compiler.rb +132 -9
  57. data/test/test_macros.rb +51 -0
  58. data/test/test_typer.rb +29 -25
  59. metadata +13 -21
  60. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +0 -390
  61. data/javalib/JRubyParser.jar +0 -0
  62. data/javalib/dynalang-invoke-0.1.jar +0 -0
  63. data/lib/mirah/nbcompiler.rb +0 -44
data/History.txt CHANGED
@@ -1,3 +1,36 @@
1
+ === 0.0.6 / 2011-03-20
2
+
3
+ ce9b740 Update dynalink stuff, add JSR292 mock to enable compiling/including invokedynamic logic.
4
+ 2898b87 Remove unused JRubyParser jar.
5
+ b1cb2e0 Clean up --help output for normal and MirahCommand-based command lines.
6
+ 94000eb Add .redcar dir to .gitignore
7
+ c450943 Get Maven artifacts building again and add an "else" case to MirahCommand for running from jar.
8
+ 92f723c Move more files out that are specific to the NB plugin.
9
+ 48777a6 Move NetBeans plugin to mirah-netbeans-plugin project.
10
+ b3979b7 Fix poms to reference parent.
11
+ d23ec2c Add support for using Colon2Const as a fully-qualified type name
12
+ f1fe06b Save method arguments into the binding if necessary
13
+ 929fbdf Merge branch 'master' of git@github.com:mirah/mirah
14
+ b230d94 Fix parsing of long constants
15
+ 935031b Body of void methods is not an expression
16
+ 372e1a4 Don't require compatible types for an if statement unless the statement is an expression.
17
+ cc861f4 Fix java.lang.VerifyError: Attempt to split long or double on the stack
18
+ 789ec6e Get rid of .class files left behind by test_javac_compiler.rb
19
+ e1a5828 Body of void methods is not an expression
20
+ 7fa9c62 Don't require compatible types for an if statement unless the statement is an expression.
21
+ 2346c9e Fix java.lang.VerifyError: Attempt to split long or double on the stack
22
+ a0b1de4 fix typo in errors.rb
23
+ 638f326 Replace the ruby portion of the datastore plugin with mirah code
24
+ 35f3936 Hygenic macros
25
+ b455e90 - Try to differentiate between errors from compiler bugs and errors in user code. - Fix a bunch of ma
26
+ 6032830 Try to clean up error handling, and avoid having compiler bugs show up as InferenceErrors
27
+ 2dc85ad Fix scoping unquotes
28
+ f35eb86 Fix duplicate extracted values with -V
29
+ 8911a66 Fix parent on Unquotes used as a name
30
+ 4d75d84 Add --no-save-extensions flag, and use it in tests.
31
+ 97a705a Merge branch 'master' of git@github.com:mirah/mirah
32
+ 3298ff0 Merge branch 'my' of https://github.com/markokocic/mirah into markokocic-my
33
+
1
34
  === 0.0.5 / 2010-12-22
2
35
 
3
36
  8e00222 Update mirah-parser.jar to one built from mirah-parser project.
data/README.txt CHANGED
@@ -27,8 +27,8 @@ mirahc -java -e "inline script" # produces DashE.java
27
27
 
28
28
  == REQUIREMENTS:
29
29
 
30
- * JRuby 1.5.0 or higher.
31
- * BiteScript 0.0.5 or higher
30
+ * JRuby 1.6.0 or higher.
31
+ * BiteScript 0.0.8 or higher
32
32
 
33
33
  == INSTALL:
34
34
 
@@ -49,7 +49,6 @@ $ rake gem
49
49
  $ gem install pkg/mirah-*
50
50
  $ cd -
51
51
 
52
-
53
52
  == For Java tools:
54
53
 
55
54
  To build the Mirah jars from source you should have a checkout of both jruby and
data/Rakefile CHANGED
@@ -77,6 +77,11 @@ task :compile => :init do
77
77
  'mirah'
78
78
  )
79
79
  end
80
+
81
+ # compile invokedynamic stuff
82
+ ant.javac :destdir => 'build', :srcdir => 'src',
83
+ :includes => 'org/mirah/DynalangBootstrap.java',
84
+ :classpath => 'javalib/dynalink-0.1.jar:javalib/jsr292-mock.jar'
80
85
  end
81
86
 
82
87
  desc "build basic jar for distribution"
data/bin/duby CHANGED
File without changes
data/bin/dubyc CHANGED
File without changes
data/bin/dubyp CHANGED
File without changes
data/bin/jrubyp CHANGED
File without changes
data/bin/mirah CHANGED
File without changes
data/bin/mirah.cmd CHANGED
@@ -1,16 +1,16 @@
1
- REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- REM All contributing project authors may be found in the NOTICE file.
3
- REM
4
- REM Licensed under the Apache License, Version 2.0 (the "License");
5
- REM you may not use this file except in compliance with the License.
6
- REM You may obtain a copy of the License at
7
- REM
8
- REM http://www.apache.org/licenses/LICENSE-2.0
9
- REM
10
- REM Unless required by applicable law or agreed to in writing, software
11
- REM distributed under the License is distributed on an "AS IS" BASIS,
12
- REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- REM See the License for the specific language governing permissions and
14
- REM limitations under the License.
1
+ @REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
+ @REM All contributing project authors may be found in the NOTICE file.
3
+ @REM
4
+ @REM Licensed under the Apache License, Version 2.0 (the "License");
5
+ @REM you may not use this file except in compliance with the License.
6
+ @REM You may obtain a copy of the License at
7
+ @REM
8
+ @REM http://www.apache.org/licenses/LICENSE-2.0
9
+ @REM
10
+ @REM Unless required by applicable law or agreed to in writing, software
11
+ @REM distributed under the License is distributed on an "AS IS" BASIS,
12
+ @REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ @REM See the License for the specific language governing permissions and
14
+ @REM limitations under the License.
15
15
 
16
16
  @jruby "%~dpn0" %*
data/bin/mirahc CHANGED
File without changes
data/bin/mirahc.cmd CHANGED
@@ -1,16 +1,16 @@
1
- REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- REM All contributing project authors may be found in the NOTICE file.
3
- REM
4
- REM Licensed under the Apache License, Version 2.0 (the "License");
5
- REM you may not use this file except in compliance with the License.
6
- REM You may obtain a copy of the License at
7
- REM
8
- REM http://www.apache.org/licenses/LICENSE-2.0
9
- REM
10
- REM Unless required by applicable law or agreed to in writing, software
11
- REM distributed under the License is distributed on an "AS IS" BASIS,
12
- REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- REM See the License for the specific language governing permissions and
14
- REM limitations under the License.
1
+ @REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
+ @REM All contributing project authors may be found in the NOTICE file.
3
+ @REM
4
+ @REM Licensed under the Apache License, Version 2.0 (the "License");
5
+ @REM you may not use this file except in compliance with the License.
6
+ @REM You may obtain a copy of the License at
7
+ @REM
8
+ @REM http://www.apache.org/licenses/LICENSE-2.0
9
+ @REM
10
+ @REM Unless required by applicable law or agreed to in writing, software
11
+ @REM distributed under the License is distributed on an "AS IS" BASIS,
12
+ @REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ @REM See the License for the specific language governing permissions and
14
+ @REM limitations under the License.
15
15
 
16
16
  @jruby "%~dpn0" %*
data/bin/mirahp CHANGED
File without changes
data/bin/mirahp.cmd CHANGED
@@ -1,16 +1,16 @@
1
- REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- REM All contributing project authors may be found in the NOTICE file.
3
- REM
4
- REM Licensed under the Apache License, Version 2.0 (the "License");
5
- REM you may not use this file except in compliance with the License.
6
- REM You may obtain a copy of the License at
7
- REM
8
- REM http://www.apache.org/licenses/LICENSE-2.0
9
- REM
10
- REM Unless required by applicable law or agreed to in writing, software
11
- REM distributed under the License is distributed on an "AS IS" BASIS,
12
- REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- REM See the License for the specific language governing permissions and
14
- REM limitations under the License.
1
+ @REM Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
+ @REM All contributing project authors may be found in the NOTICE file.
3
+ @REM
4
+ @REM Licensed under the Apache License, Version 2.0 (the "License");
5
+ @REM you may not use this file except in compliance with the License.
6
+ @REM You may obtain a copy of the License at
7
+ @REM
8
+ @REM http://www.apache.org/licenses/LICENSE-2.0
9
+ @REM
10
+ @REM Unless required by applicable law or agreed to in writing, software
11
+ @REM distributed under the License is distributed on an "AS IS" BASIS,
12
+ @REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ @REM See the License for the specific language governing permissions and
14
+ @REM limitations under the License.
15
15
 
16
16
  @jruby "%~dpn0" %*
Binary file
Binary file
@@ -41,7 +41,9 @@ end
41
41
  task :compile => :init do
42
42
  # build the Mirah sources
43
43
  puts "Compiling Mirah sources"
44
- mirahc 'com/google/appengine', :dir => 'src', :dest => 'build'
44
+ mirahc 'com/google/appengine/ext/duby/db/MetaModel.mirah', :dir => 'src', :dest => 'build'
45
+ mirahc 'com/google/appengine/ext/duby/db/Model.duby', :dir => 'src', :dest => 'build',
46
+ :options => ['--classpath', Dir.pwd + '/build/']
45
47
  end
46
48
 
47
49
  task :compile_test => :jar do
@@ -0,0 +1,385 @@
1
+ import duby.lang.compiler.*
2
+ import java.lang.ref.WeakReference
3
+ import java.util.Collections
4
+ import java.util.WeakHashMap
5
+
6
+ class DubyDatastorePlugin
7
+ def initialize(mirah:Compiler)
8
+ @mirah = WeakReference.new(mirah)
9
+ @models = {}
10
+
11
+ @type_map = {
12
+ 'Category' => 'String',
13
+ 'Email' => 'String',
14
+ 'Link' => 'String',
15
+ 'PhoneNumber' => 'String',
16
+ 'PostalAddress' => 'String',
17
+ 'Text' => 'String',
18
+ 'Blob' => 'byte[]',
19
+ 'ShortBlob' => 'byte[]',
20
+ 'Rating' => 'int',
21
+ 'Long' => 'long',
22
+ 'Double' => 'double',
23
+ 'Boolean' => 'boolean'
24
+ }
25
+
26
+ @primitives = ['Long', 'Double', 'Boolean', 'Rating']
27
+
28
+ @boxes = {
29
+ 'int' => 'Integer',
30
+ 'boolean' => 'Boolean',
31
+ 'long' => 'Long',
32
+ 'double' => 'Double',
33
+ }
34
+
35
+ @defaults = {
36
+ 'Rating' => mirah.fixnum(0),
37
+ 'Long' => mirah.quote { long(0) },
38
+ 'Double' => mirah.quote { 0.0 },
39
+ 'Boolean' => mirah.quote { false },
40
+ 'Blob' => mirah.quote { byte[].cast(nil) },
41
+ 'ShortBlob' => mirah.quote { byte[].cast(nil) },
42
+ }
43
+ end
44
+
45
+ def mirah:Compiler
46
+ Compiler(@mirah.get)
47
+ end
48
+
49
+ def add_property(name_node:Node, type_node:Node, call:Call)
50
+ parent = call.parent
51
+ name = name_node.string_value
52
+ ds_type = type_node.string_value
53
+ ds_type = 'Long' if ds_type == 'Integer'
54
+
55
+ # create an empty body
56
+ result = Body(mirah.quote { nil; nil })
57
+
58
+ klass = find_class(call.parent)
59
+ model = find_model(klass, result)
60
+
61
+ type_name = String(@type_map[ds_type]) || ds_type
62
+ if type_name.endsWith('[]')
63
+ array = true
64
+ type_name = type_name.replace('[]', '')
65
+ else
66
+ array = false
67
+ nil
68
+ end
69
+ coercion = "coerce_#{type_name.toLowerCase}#{array ? 's' : ''}"
70
+ loader = "load_#{ds_type.toLowerCase}"
71
+ duby_type = mirah.constant(type_name, array)
72
+
73
+ name_string = mirah.string(name)
74
+ update_query(model, name, ds_type, duby_type)
75
+ model.read << mirah.quote do
76
+ `name` = `'e'`.getProperty(`name_string`)
77
+ @`name` = self.`loader`(`name`)
78
+ end
79
+
80
+ model.save << mirah.quote do
81
+ e.setProperty(`name_string`, `to_datastore(ds_type, "@#{name}")`)
82
+ end
83
+
84
+ setter = "#{name}_set"
85
+ model.update << mirah.quote do
86
+ self.`setter`(properties.get(`name_string`)) if properties.containsKey(`name_string`)
87
+ end
88
+
89
+ value = maybe_box(type_name, mirah.quote {self.`name`})
90
+ model.get_properties << mirah.quote do
91
+ result.put(`name_string`, `value`)
92
+ end
93
+
94
+ result << mirah.quote do
95
+ def `name`
96
+ @`name`
97
+ end
98
+
99
+ def `setter`(value:`duby_type`)
100
+ @`name` = value
101
+ end
102
+
103
+ def `setter`(value:Object) #`
104
+ @`name` = self.`coercion`(value)
105
+ end
106
+ end
107
+
108
+ result
109
+ end
110
+
111
+ def find_class(node:Node):ClassDefinition
112
+ while node && !node.kind_of?(ClassDefinition)
113
+ node = node.parent
114
+ end
115
+ ClassDefinition(node)
116
+ end
117
+
118
+ def find_model(klass:ClassDefinition, ast:Body):ModelState
119
+ unless @models[klass]
120
+ @models[klass] = ModelState.new(mirah, klass, ast)
121
+ end
122
+ ModelState(@models[klass])
123
+ end
124
+
125
+ def to_datastore(type:String, value:Object):Object
126
+ if @primitives.contains(type)
127
+ Object(mirah.quote { `type`.new(`value`) })
128
+ elsif @type_map.containsKey(type)
129
+ Object(mirah.quote { (`value` ? `type`.new(`value`) : nil) })
130
+ else
131
+ value
132
+ end
133
+ end
134
+
135
+ def maybe_box(duby_type:String, value:Object):Object
136
+ if @boxes.containsKey(duby_type)
137
+ Object(mirah.quote do
138
+ `@boxes[duby_type]`.valueOf(`value`)
139
+ end)
140
+ else
141
+ value
142
+ end
143
+ end
144
+
145
+ # Generate the query filtering method for a property.
146
+ def update_query(model:ModelState, property_name:String, type:String, duby_type:Node)
147
+ name_node = mirah.string(property_name)
148
+ if 'List'.equals type
149
+ # We don't know what's in the list, so just use Object
150
+ model.query << mirah.quote do
151
+ def `property_name`(value:Object):void #`
152
+ _query.addFilter(`name_node`, FilterOperator.EQUAL, value)
153
+ end
154
+ end
155
+ else
156
+ model.query << mirah.quote do
157
+ def `property_name`(value:`duby_type`):void #`
158
+ _query.addFilter(`name_node`,
159
+ FilterOperator.EQUAL,
160
+ `to_datastore(type, 'value')`)
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ def self.initialize:void
167
+ @@instances = Collections.synchronizedMap(WeakHashMap.new)
168
+ end
169
+
170
+ def self.get(mirah:Compiler)
171
+ instance = @@instances[mirah]
172
+ if (instance.nil?)
173
+ instance = DubyDatastorePlugin.new(mirah)
174
+ @@instances[mirah] = instance
175
+ end
176
+ DubyDatastorePlugin(instance)
177
+ end
178
+ end
179
+
180
+ class ModelState
181
+ macro def attr_reader(name)
182
+ quote do
183
+ def `name` #`
184
+ @`name`
185
+ end
186
+ end
187
+ end
188
+ attr_reader :kind
189
+ attr_reader :query
190
+ attr_reader :read
191
+ attr_reader :save
192
+ attr_reader :update
193
+ attr_reader :get_properties
194
+
195
+ def initialize(mirah:Compiler, klass:ClassDefinition, ast:Body)
196
+ @mirah = WeakReference.new(mirah)
197
+ path = klass.name.split('\\.')
198
+ @kind = path[path.length - 1]
199
+ init_query(klass.name)
200
+ init_static(ast)
201
+
202
+ # The nodes we add to ast will get dup'ed before being inserted, but
203
+ # we need to be able to update some methods when add_property gets
204
+ # called again. So we insert these directly into the class definition.
205
+ class_body = Body(klass.body)
206
+ init_read(class_body)
207
+ init_save(class_body)
208
+ end
209
+
210
+ def mirah:Compiler
211
+ Compiler(@mirah.get)
212
+ end
213
+
214
+ def init_query(classname:String)
215
+ name = "#{classname}$Query"
216
+ superclass = 'com.google.appengine.ext.duby.db.DQuery'
217
+ @query = Body(mirah.defineClass(name, superclass).body)
218
+ array_size = mirah.quote { entities.size }
219
+ @query << mirah.quote do
220
+ import com.google.appengine.api.datastore.Entity
221
+ import com.google.appengine.api.datastore.Query.FilterOperator
222
+
223
+ def initialize; end
224
+
225
+ def kind
226
+ `mirah.string kind`
227
+ end
228
+
229
+ def first
230
+ it = _prepare.asIterator
231
+ if it.hasNext
232
+ e = Entity(it.next)
233
+ m = `kind`.new
234
+ m._read_from(e)
235
+ m
236
+ else
237
+ `mirah.cast(kind, mirah.quote {nil})`
238
+ end
239
+ end
240
+
241
+ def run
242
+ entities = _prepare.asList(_options)
243
+ models = `mirah.empty_array(mirah.constant(kind), array_size)`
244
+ it = entities.iterator
245
+ i = 0
246
+ while (it.hasNext)
247
+ e = Entity(it.next)
248
+ m = `kind`.new
249
+ m._read_from(e)
250
+ models[i] = m
251
+ i += 1
252
+ end
253
+ models
254
+ end
255
+ end
256
+ end
257
+
258
+ def init_static(ast:Body)
259
+ # # TODO These imports don't work any more. Figure out how to fix that.
260
+ # scope = ast.static_scope
261
+ # package = "#{scope.package}." unless scope.package.empty?
262
+ # scope.import('java.util.Map', 'Map')
263
+ # scope.import("#{package}#{kind}$Query", "#{kind}__Query__")
264
+ # %w( Entity Blob Category Email GeoPt IMHandle Key
265
+ # Link PhoneNumber PostalAddress Rating ShortBlob
266
+ # Text KeyFactory EntityNotFoundException ).each do |name|
267
+ # scope.import("com.google.appengine.api.datastore.#{name}", name)
268
+ # end
269
+ kind_string = mirah.string(kind)
270
+ ast << mirah.quote do
271
+ import com.google.appengine.api.datastore.Entity
272
+ import com.google.appengine.api.datastore.EntityNotFoundException
273
+ import com.google.appengine.api.datastore.Key
274
+ import com.google.appengine.api.datastore.KeyFactory
275
+ import com.google.appengine.ext.duby.db.Model
276
+ import java.util.Map
277
+
278
+ def initialize
279
+ super
280
+ end
281
+
282
+ def initialize(key_name:String)
283
+ super
284
+ end
285
+
286
+ def initialize(parent:Model)
287
+ super
288
+ end
289
+
290
+ def initialize(parent:Key)
291
+ super
292
+ end
293
+
294
+ def initialize(parent:Model, key_name:String)
295
+ super
296
+ end
297
+
298
+ def initialize(parent:Key, key_name:String)
299
+ super
300
+ end
301
+
302
+ def self.get(key:Key)
303
+ begin
304
+ m = `kind`.new
305
+ m._read_from(Model._datastore.get(key))
306
+ m
307
+ rescue EntityNotFoundException
308
+ nil
309
+ end
310
+ end
311
+
312
+ def self.get(key_name:String)
313
+ get(KeyFactory.createKey(`kind_string`, key_name))
314
+ end
315
+
316
+ def self.get(id:long)
317
+ get(KeyFactory.createKey(`kind_string`, id))
318
+ end
319
+
320
+ def self.get(parent:Key, key_name:String)
321
+ get(KeyFactory.createKey(parent, `kind_string`, key_name))
322
+ end
323
+
324
+ def self.get(parent:Key, id:long)
325
+ get(KeyFactory.createKey(parent, `kind_string`, id))
326
+ end
327
+
328
+ def self.get(parent:Model, key_name:String)
329
+ get(KeyFactory.createKey(parent.key, `kind_string`, key_name))
330
+ end
331
+
332
+ def self.get(parent:Model, id:long)
333
+ get(KeyFactory.createKey(parent.key, `kind_string`, id))
334
+ end
335
+
336
+ def self.all
337
+ `kind`.Query.new
338
+ end
339
+ end
340
+ end
341
+
342
+ def init_read(ast:Body)
343
+ # We're in the main class scope instead of the one we created earlier,
344
+ # so we can't use our imports.
345
+ entity = mirah.constant('com.google.appengine.api.datastore.Entity')
346
+ map = mirah.constant('java.util.Map')
347
+ mdef = mirah.quote do
348
+ def _read_from(e:`entity`):void
349
+ self.entity = e
350
+ nil # We need to statements to make sure we get a Body node.
351
+ end
352
+ end
353
+ ast << mdef
354
+ @read = Body(mdef.child_nodes.get(2))
355
+
356
+ mdef = mirah.quote do
357
+ def properties
358
+ result = super()
359
+ `mirah.body`
360
+ result
361
+ end
362
+ end
363
+ ast << mdef
364
+ @get_properties = Body(Node(mdef.child_nodes.get(2)).child_nodes.get(1))
365
+
366
+ mdef = mirah.quote do
367
+ def update(properties:`map`):void
368
+ nil;nil
369
+ end
370
+ end
371
+ ast << mdef
372
+ @update = Body(mdef.child_nodes.get(2))
373
+ end
374
+
375
+ def init_save(ast:Body)
376
+ entity = mirah.constant('com.google.appengine.api.datastore.Entity')
377
+ mdef = mirah.quote do
378
+ def _save_to(e:`entity`):void
379
+ nil; nil
380
+ end
381
+ end
382
+ ast << mdef
383
+ @save = Body(mdef.child_nodes.get(2))
384
+ end
385
+ end