mirah 0.0.5-java → 0.0.6-java

Sign up to get free protection for your applications and to get access to all the features.
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