duby 0.0.2-java → 0.0.3-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.
- data/History.txt +7 -0
- data/README.txt +18 -7
- data/Rakefile +72 -0
- data/examples/ant/example-build.xml +7 -0
- data/examples/appengine/Rakefile +8 -67
- data/examples/appengine/Readme +4 -3
- data/examples/appengine/lib/duby/appengine_tasks.rb +173 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +92 -31
- data/examples/appengine/lib/duby_task.rb +61 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +32 -6
- data/examples/appengine/src/com/ribrdb/list.dhtml +2 -2
- data/examples/appengine/{config.ru → src/config.ru} +0 -0
- data/examples/bintrees.duby +66 -0
- data/examples/dynamic.duby +17 -0
- data/examples/fib.duby +3 -11
- data/examples/fields.duby +3 -3
- data/examples/fractal.duby +1 -3
- data/examples/sort_closure.duby +7 -0
- data/examples/swing.duby +11 -11
- data/javalib/duby-bootstrap.jar +0 -0
- data/javalib/dynalang-invoke-0.1.jar +0 -0
- data/lib/duby.rb +168 -35
- data/lib/duby/ast.rb +224 -27
- data/lib/duby/ast/call.rb +85 -25
- data/lib/duby/ast/class.rb +112 -28
- data/lib/duby/ast/flow.rb +65 -44
- data/lib/duby/ast/intrinsics.rb +223 -21
- data/lib/duby/ast/literal.rb +67 -16
- data/lib/duby/ast/local.rb +36 -40
- data/lib/duby/ast/method.rb +83 -67
- data/lib/duby/ast/structure.rb +105 -23
- data/lib/duby/compiler.rb +83 -28
- data/lib/duby/env.rb +33 -0
- data/lib/duby/jvm/base.rb +210 -0
- data/lib/duby/jvm/compiler.rb +293 -219
- data/lib/duby/jvm/method_lookup.rb +77 -67
- data/lib/duby/jvm/source_compiler.rb +250 -157
- data/lib/duby/jvm/source_generator/builder.rb +53 -49
- data/lib/duby/jvm/source_generator/loops.rb +9 -9
- data/lib/duby/jvm/source_generator/precompile.rb +35 -25
- data/lib/duby/jvm/typer.rb +19 -10
- data/lib/duby/jvm/types.rb +127 -68
- data/lib/duby/jvm/types/basic_types.rb +26 -13
- data/lib/duby/jvm/types/enumerable.rb +6 -4
- data/lib/duby/jvm/types/factory.rb +49 -13
- data/lib/duby/jvm/types/floats.rb +16 -0
- data/lib/duby/jvm/types/integers.rb +63 -2
- data/lib/duby/jvm/types/intrinsics.rb +43 -21
- data/lib/duby/jvm/types/methods.rb +326 -86
- data/lib/duby/jvm/types/number.rb +3 -0
- data/lib/duby/nbcompiler.rb +1 -1
- data/lib/duby/plugin/edb.rb +1 -1
- data/lib/duby/plugin/java.rb +10 -1
- data/lib/duby/transform.rb +134 -46
- data/lib/duby/typer.rb +75 -50
- data/test/test_ast.rb +106 -106
- data/test/test_compilation.rb +46 -32
- data/test/test_env.rb +42 -0
- data/test/test_java_typer.rb +35 -51
- data/test/test_javac_compiler.rb +4 -1
- data/test/test_jvm_compiler.rb +564 -133
- data/test/test_typer.rb +68 -92
- metadata +37 -21
- data/examples/README +0 -16
- data/lib/duby/c/compiler.rb +0 -134
- data/lib/duby/old/compiler_old.rb +0 -845
- data/lib/duby/old/declaration.rb +0 -72
- data/lib/duby/old/mapper.rb +0 -72
- data/lib/duby/old/signature.rb +0 -52
- data/lib/duby/old/typer_old.rb +0 -163
- data/lib/duby/plugin/math.rb +0 -84
- data/test/test_math_plugin.rb +0 -87
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -20,20 +20,31 @@ output either JVM bytecode or Java source files.
|
|
20
20
|
duby <script.duby>
|
21
21
|
duby -e "inline script"
|
22
22
|
dubyc <script.duby>
|
23
|
-
dubyc -e "inline script" # produces
|
23
|
+
dubyc -e "inline script" # produces DashE.class
|
24
24
|
dubyc -java <script.duby>
|
25
|
-
dubyc -java -e "inline script" # produces
|
25
|
+
dubyc -java -e "inline script" # produces DashE.java
|
26
26
|
|
27
27
|
== REQUIREMENTS:
|
28
28
|
|
29
|
-
* JRuby 1.
|
29
|
+
* JRuby 1.5.0 or higher.
|
30
30
|
* BiteScript 0.0.5 or higher
|
31
31
|
|
32
32
|
== INSTALL:
|
33
33
|
|
34
|
+
If your "gem" command is the one from JRuby:
|
35
|
+
|
34
36
|
* gem install duby
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
jruby
|
39
|
-
|
38
|
+
Otherwise:
|
39
|
+
|
40
|
+
* jruby -S gem install duby
|
41
|
+
|
42
|
+
Only JRuby is supported at this time.
|
43
|
+
|
44
|
+
== For Java tools:
|
45
|
+
|
46
|
+
To build the Duby jars from source you should have a checkout of both jruby and
|
47
|
+
bitescript in Duby's parent directory. Run "ant jar-complete" in jruby, then in
|
48
|
+
the duby directory "../jruby/bin/jruby -S rake jar" to build the Duby jar. Use
|
49
|
+
"jar:complete" instead to produce a free-standing jar file with JRuby and the
|
50
|
+
JRubyParser libraries included.
|
data/Rakefile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'java'
|
4
|
+
$: << './lib'
|
5
|
+
require 'duby'
|
6
|
+
require 'jruby/compiler'
|
7
|
+
require 'ant'
|
4
8
|
|
5
9
|
task :default => :test
|
6
10
|
|
@@ -11,3 +15,71 @@ Rake::TestTask.new :test do |t|
|
|
11
15
|
t.test_files = FileList["test/**/*.rb"]
|
12
16
|
java.lang.System.set_property("jruby.duby.enabled", "true")
|
13
17
|
end
|
18
|
+
|
19
|
+
task :init do
|
20
|
+
mkdir_p 'dist'
|
21
|
+
mkdir_p 'build'
|
22
|
+
end
|
23
|
+
|
24
|
+
task :clean do
|
25
|
+
ant.delete :quiet => true, :dir => 'build'
|
26
|
+
ant.delete :quiet => true, :dir => 'dist'
|
27
|
+
end
|
28
|
+
|
29
|
+
task :compile => :init do
|
30
|
+
# build the Ruby sources
|
31
|
+
puts "Compiling Ruby sources"
|
32
|
+
JRuby::Compiler.compile_argv([
|
33
|
+
'-t', 'build',
|
34
|
+
'--javac',
|
35
|
+
'src/org/jruby/duby/duby_command.rb'
|
36
|
+
])
|
37
|
+
|
38
|
+
# build the Duby sources
|
39
|
+
puts "Compiling Duby sources"
|
40
|
+
Dir.chdir 'src' do
|
41
|
+
classpath = Duby::Env.encode_paths([
|
42
|
+
'javalib/jruby-complete.jar',
|
43
|
+
'javalib/JRubyParser.jar',
|
44
|
+
'dist/duby.jar',
|
45
|
+
'build',
|
46
|
+
'/usr/share/ant/lib/ant.jar'
|
47
|
+
])
|
48
|
+
Duby.compile(
|
49
|
+
'-c', classpath,
|
50
|
+
'-d', '../build',
|
51
|
+
'org/jruby/duby',
|
52
|
+
'duby/lang')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
task :jar => :compile do
|
57
|
+
ant.jar :jarfile => 'dist/duby.jar' do
|
58
|
+
fileset :dir => 'lib'
|
59
|
+
fileset :dir => 'build'
|
60
|
+
fileset :dir => '.', :includes => 'bin/*'
|
61
|
+
fileset :dir => '../bitescript/lib'
|
62
|
+
manifest do
|
63
|
+
attribute :name => 'Main-Class', :value => 'org.jruby.duby.DubyCommand'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
namespace :jar do
|
69
|
+
task :complete => :jar do
|
70
|
+
ant.jar :jarfile => 'dist/duby-complete.jar' do
|
71
|
+
zipfileset :src => 'dist/duby.jar'
|
72
|
+
zipfileset :src => 'javalib/jruby-complete.jar'
|
73
|
+
zipfileset :src => 'javalib/JRubyParser.jar'
|
74
|
+
manifest do
|
75
|
+
attribute :name => 'Main-Class', :value => 'org.jruby.duby.DubyCommand'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
task :bootstrap => :compile do
|
81
|
+
ant.jar :jarfile => 'javalib/duby-bootstrap.jar' do
|
82
|
+
fileset :dir => 'build'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/examples/appengine/Rakefile
CHANGED
@@ -1,72 +1,13 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require 'appengine-tools/xml-formatter'
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/lib')
|
2
|
+
require 'duby/appengine_tasks'
|
4
3
|
|
5
|
-
|
6
|
-
LIB = File.expand_path(File.dirname(__FILE__) + '/lib')
|
7
|
-
WAR = File.expand_path(File.dirname(__FILE__) + '/war')
|
8
|
-
CONFIG_RU = File.expand_path(File.dirname(__FILE__) + '/config.ru')
|
9
|
-
SERVLET = AppEngine::SDK::SDK_ROOT +
|
10
|
-
'/lib/shared/geronimo-servlet_2.5_spec-1.2.jar'
|
11
|
-
APIS = AppEngine::SDK::API_JAR
|
4
|
+
appengine_app :app
|
12
5
|
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
DUBY_APP = "#{Duby.dest_path}/com/ribrdb/DubyApp.class"
|
7
|
+
MODEL = "#{Duby.dest_path}/com/google/appengine/ext/duby/db/Model.class"
|
8
|
+
LIST = "#{Duby.source_path}/com/ribrdb/list.dhtml"
|
16
9
|
|
17
|
-
MODEL
|
18
|
-
DUBY_APP = 'com/ribrdb/DubyApp'
|
19
|
-
|
20
|
-
MODEL_DUBY = "#{SRC}/#{MODEL}.duby"
|
21
|
-
MODEL_CLASS = "#{WEB_INF_CLASSES}/#{MODEL}.class"
|
22
|
-
DUBY_APP_DUBY = "#{SRC}/#{DUBY_APP}.duby"
|
23
|
-
DUBY_APP_CLASS = "#{WEB_INF_CLASSES}/#{DUBY_APP}.class"
|
24
|
-
LIST = "#{SRC}/com/ribrdb/list.dhtml"
|
25
|
-
|
26
|
-
def dubyc(*files)
|
27
|
-
chdir(File.dirname(__FILE__) + '/src') do
|
28
|
-
files = files.join ' '
|
29
|
-
dest = '-d ../war/WEB-INF/classes'
|
30
|
-
dubyc = '../../../bin/dubyc'
|
31
|
-
options = "-I #{LIB} -p datastore"
|
32
|
-
orig_classpath = ENV['CLASSPATH']
|
33
|
-
ENV['CLASSPATH'] ||= ''
|
34
|
-
ENV['CLASSPATH'] += ":#{SERVLET}:#{APIS}:#{WEB_INF_CLASSES}"
|
35
|
-
sh %{#{dubyc} #{dest} #{options} #{files}}
|
36
|
-
ENV['CLASSPATH'] = orig_classpath
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
directory WEB_INF_CLASSES
|
41
|
-
|
42
|
-
file MODEL_CLASS => MODEL_DUBY do
|
43
|
-
dubyc("#{MODEL}.duby")
|
44
|
-
end
|
45
|
-
|
46
|
-
file DUBY_APP_CLASS => [DUBY_APP_DUBY, LIST, MODEL_CLASS] do
|
47
|
-
dubyc("#{DUBY_APP}.duby")
|
48
|
-
end
|
49
|
-
|
50
|
-
file WEB_XML => [WEB_INF_CLASSES, CONFIG_RU] do
|
51
|
-
builder = WebXmlBuilder.new do
|
52
|
-
eval IO.read(CONFIG_RU), nil, 'config.ru', 1
|
53
|
-
end
|
54
|
-
open(WEB_XML, 'w') do |webxml|
|
55
|
-
xml = AppEngine::Rack::XmlFormatter.format(builder.to_xml)
|
56
|
-
webxml.write(xml)
|
57
|
-
end
|
58
|
-
open(AEWEB_XML, 'w') do |aeweb|
|
59
|
-
xml = AppEngine::Rack::XmlFormatter.format(AppEngine::Rack.app.to_xml)
|
60
|
-
aeweb.write(xml)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
task :server => [WEB_XML, DUBY_APP_CLASS] do
|
65
|
-
sh "dev_appserver.rb #{WAR}"
|
66
|
-
end
|
67
|
-
|
68
|
-
task :upload => [WEB_XML, DUBY_APP_CLASS] do
|
69
|
-
sh "appcfg.rb update #{WAR}"
|
70
|
-
end
|
10
|
+
Rake::Task[DUBY_APP].enhance([LIST, MODEL])
|
71
11
|
|
12
|
+
task :app => DUBY_APP
|
72
13
|
task :default => :server
|
data/examples/appengine/Readme
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
Run rake to compile the application and start the development server
|
1
|
+
Run rake to compile the application and start the development server:
|
2
|
+
|
3
|
+
$ jruby -I `pwd`/../../lib -S rake
|
2
4
|
|
3
5
|
Requirements:
|
4
|
-
-
|
5
|
-
- Have jruby on your path so dubyc can run.
|
6
|
+
- jruby -S gem install google-appengine bitescript
|
6
7
|
|
7
8
|
Datastore API:
|
8
9
|
Model.get(key)
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'appengine-sdk'
|
2
|
+
require 'appengine-tools/appcfg'
|
3
|
+
require 'appengine-tools/dev_appserver'
|
4
|
+
require 'appengine-tools/web-xml'
|
5
|
+
require 'appengine-tools/xml-formatter'
|
6
|
+
require 'duby_task'
|
7
|
+
require 'java'
|
8
|
+
require 'open-uri'
|
9
|
+
require 'rake'
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
Duby.compiler_options.concat %w"-p datastore"
|
13
|
+
AppEngine::Development::JRubyDevAppserver::ARGV = []
|
14
|
+
module AppEngine::Rake
|
15
|
+
SERVLET = AppEngine::SDK::SDK_ROOT +
|
16
|
+
'/lib/shared/geronimo-servlet_2.5_spec-1.2.jar'
|
17
|
+
APIS = AppEngine::SDK::API_JAR
|
18
|
+
|
19
|
+
$CLASSPATH << SERVLET
|
20
|
+
$CLASSPATH << APIS
|
21
|
+
|
22
|
+
class AppEngineTask < Rake::Task
|
23
|
+
def initialize(*args, &block)
|
24
|
+
super
|
25
|
+
AppEngineTask.tasks << self
|
26
|
+
end
|
27
|
+
|
28
|
+
def init(src, war)
|
29
|
+
@src = src
|
30
|
+
@war = war
|
31
|
+
unless $CLASSPATH.include?(webinf_classes)
|
32
|
+
$CLASSPATH << webinf_classes
|
33
|
+
end
|
34
|
+
Duby.source_path = src
|
35
|
+
Duby.dest_path = webinf_classes
|
36
|
+
directory(webinf_classes)
|
37
|
+
directory(generated)
|
38
|
+
file_create dummy_config_ru do |t|
|
39
|
+
touch t.name
|
40
|
+
end
|
41
|
+
file_create gemfile do |t|
|
42
|
+
open(t.name, 'w') do |gems|
|
43
|
+
gems.puts('bundle_path ".gems/bundler_gems"')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
file web_xml => [webinf_classes, real_config_ru] do
|
47
|
+
config_ru = IO.read(real_config_ru)
|
48
|
+
builder = WebXmlBuilder.new do
|
49
|
+
eval config_ru, nil, 'config.ru', 1
|
50
|
+
end
|
51
|
+
open(web_xml, 'w') do |webxml|
|
52
|
+
xml = AppEngine::Rack::XmlFormatter.format(builder.to_xml)
|
53
|
+
webxml.write(xml)
|
54
|
+
end
|
55
|
+
open(aeweb_xml, 'w') do |aeweb|
|
56
|
+
xml = AppEngine::Rack::XmlFormatter.format(AppEngine::Rack.app.to_xml)
|
57
|
+
aeweb.write(xml)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
file build_status => [web_xml, dummy_config_ru, aeweb_xml, generated] do
|
61
|
+
open(build_status, 'w') do |status_file|
|
62
|
+
status = {
|
63
|
+
:config_ru => File.stat(dummy_config_ru).mtime,
|
64
|
+
:web_xml => File.stat(web_xml).mtime,
|
65
|
+
:aeweb_xml => File.stat(aeweb_xml).mtime,
|
66
|
+
}
|
67
|
+
status_file.write(status.to_yaml)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
task :server => [name, build_status] do
|
72
|
+
# Begin horrible hacks
|
73
|
+
if AppEngine::Development::JRubyDevAppserver::ARGV.empty?
|
74
|
+
AppEngine::Development::JRubyDevAppserver::ARGV << @war
|
75
|
+
end
|
76
|
+
class << AppEngine::Development::JRubyDevAppserver
|
77
|
+
def exec(*args)
|
78
|
+
sh *args
|
79
|
+
end
|
80
|
+
end
|
81
|
+
# End horrible hacks
|
82
|
+
check_for_updates
|
83
|
+
AppEngine::Development::JRubyDevAppserver.run([@war])
|
84
|
+
@done = true
|
85
|
+
@update_thread.join
|
86
|
+
end
|
87
|
+
task :upload => [name, build_status] do
|
88
|
+
AppEngine::Admin::JRubyAppCfg.main(['update', @war])
|
89
|
+
end
|
90
|
+
|
91
|
+
enhance([web_xml])
|
92
|
+
end
|
93
|
+
|
94
|
+
def real_prerequisites
|
95
|
+
prerequisites.map {|n| application[n, scope]}
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_for_updates
|
99
|
+
@update_thread = Thread.new do
|
100
|
+
# Give the server time to start
|
101
|
+
next_time = Time.now + 5
|
102
|
+
until @done
|
103
|
+
sleep_time = next_time - Time.now
|
104
|
+
sleep(sleep_time) if sleep_time > 0
|
105
|
+
next_time = Time.now + 1
|
106
|
+
update
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def update
|
112
|
+
updated = false
|
113
|
+
real_prerequisites.each do |dep|
|
114
|
+
if dep.needed?
|
115
|
+
dep.execute
|
116
|
+
updated = true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
if updated
|
120
|
+
#touch aeweb_xml
|
121
|
+
open('http://localhost:8080/_ah/reloadwebapp')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def webinf_classes
|
126
|
+
@war + '/WEB-INF/classes'
|
127
|
+
end
|
128
|
+
|
129
|
+
def aeweb_xml
|
130
|
+
@war + '/WEB-INF/appengine-web.xml'
|
131
|
+
end
|
132
|
+
|
133
|
+
def web_xml
|
134
|
+
@war + '/WEB-INF/web.xml'
|
135
|
+
end
|
136
|
+
|
137
|
+
def real_config_ru
|
138
|
+
@src + '/config.ru'
|
139
|
+
end
|
140
|
+
|
141
|
+
def dummy_config_ru
|
142
|
+
@war + '/config.ru'
|
143
|
+
end
|
144
|
+
|
145
|
+
def generated
|
146
|
+
@war + '/WEB-INF/appengine-generated'
|
147
|
+
end
|
148
|
+
|
149
|
+
def build_status
|
150
|
+
generated + '/build_status.yaml'
|
151
|
+
end
|
152
|
+
|
153
|
+
def gemfile
|
154
|
+
@war + '/Gemfile'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def appengine_app(*args, &block)
|
160
|
+
deps = []
|
161
|
+
if args[-1].kind_of?(Hash)
|
162
|
+
hash = args.pop
|
163
|
+
arg = hash.keys[0]
|
164
|
+
deps = hash[arg]
|
165
|
+
args << arg
|
166
|
+
end
|
167
|
+
name, src, war = args
|
168
|
+
task = AppEngine::Rake::AppEngineTask.define_task(name => deps, &block)
|
169
|
+
src = File.expand_path(src || 'src')
|
170
|
+
war = File.expand_path(war || 'war')
|
171
|
+
task.init(src, war)
|
172
|
+
task
|
173
|
+
end
|
@@ -1,10 +1,42 @@
|
|
1
1
|
class DatastorePlugin
|
2
2
|
@models = {}
|
3
|
-
|
3
|
+
|
4
|
+
TypeMap = {
|
5
|
+
'Category' => 'String',
|
6
|
+
'Email' => 'String',
|
7
|
+
'Link' => 'String',
|
8
|
+
'PhoneNumber' => 'String',
|
9
|
+
'PostalAddress' => 'String',
|
10
|
+
'Text' => 'String',
|
11
|
+
'Blob' => 'byte[]',
|
12
|
+
'ShortBlob' => 'byte[]',
|
13
|
+
'Rating' => 'int',
|
14
|
+
'Integer' => 'int',
|
15
|
+
'Double' => 'double',
|
16
|
+
}
|
17
|
+
|
18
|
+
Defaults = {
|
19
|
+
'Rating' => '0',
|
20
|
+
'int' => '0',
|
21
|
+
'double' => '0.0',
|
22
|
+
}
|
23
|
+
|
24
|
+
Conversions = {
|
25
|
+
'Category' => 'getCategory',
|
26
|
+
'Email' => 'getEmail',
|
27
|
+
'Link' => 'getValue',
|
28
|
+
'PhoneNumber' => 'getNumber',
|
29
|
+
'PostalAddress' => 'getAddress',
|
30
|
+
'Text' => 'getValue',
|
31
|
+
'Blob' => 'getBytes',
|
32
|
+
'Integer' => 'intValue',
|
33
|
+
'Double' => 'doubleValue',
|
34
|
+
}
|
35
|
+
|
4
36
|
class ModelState
|
5
37
|
include Duby::AST
|
6
38
|
attr_reader :kind, :query, :read, :save, :transformer
|
7
|
-
|
39
|
+
|
8
40
|
def initialize(transformer, klass, parent, position, ast)
|
9
41
|
@transformer = transformer
|
10
42
|
@kind = klass.name.split('.')[-1]
|
@@ -13,13 +45,13 @@ class DatastorePlugin
|
|
13
45
|
init_read(parent, position, ast)
|
14
46
|
init_save(parent, position, ast)
|
15
47
|
end
|
16
|
-
|
48
|
+
|
17
49
|
def init_query(classname, parent, position, ast)
|
18
50
|
name = "#{classname}$Query"
|
19
51
|
@query = ClassDefinition.new(parent, position, name) do |classdef|
|
20
52
|
queryinit = <<-EOF
|
21
53
|
def initialize; end
|
22
|
-
|
54
|
+
|
23
55
|
def kind
|
24
56
|
"#{kind}"
|
25
57
|
end
|
@@ -54,29 +86,29 @@ class DatastorePlugin
|
|
54
86
|
[Duby::AST.type('com.google.appengine.ext.duby.db.DQuery'),
|
55
87
|
eval(classdef, queryinit)]
|
56
88
|
end
|
57
|
-
ast
|
89
|
+
ast << @query
|
58
90
|
end
|
59
|
-
|
91
|
+
|
60
92
|
def init_read(parent, position, ast)
|
61
93
|
@read = eval(parent, <<-EOF)
|
62
94
|
def _read_from(e:Entity)
|
63
95
|
end
|
64
96
|
EOF
|
65
|
-
@read.body =
|
66
|
-
ast
|
97
|
+
@read.body = Body.new(@read, position) {[]}
|
98
|
+
ast << @read
|
67
99
|
end
|
68
|
-
|
100
|
+
|
69
101
|
def init_save(parent, position, ast)
|
70
102
|
@save = eval(parent, <<-EOF)
|
71
103
|
def _save_to(e:Entity)
|
72
104
|
end
|
73
105
|
EOF
|
74
|
-
@save.body =
|
75
|
-
ast
|
106
|
+
@save.body = Body.new(@save, position) {[]}
|
107
|
+
ast << @save
|
76
108
|
end
|
77
|
-
|
109
|
+
|
78
110
|
def init_static(parent, ast)
|
79
|
-
ast
|
111
|
+
ast << eval(parent, <<-EOF)
|
80
112
|
import com.google.appengine.api.datastore.Entity
|
81
113
|
import com.google.appengine.api.datastore.Blob
|
82
114
|
import com.google.appengine.api.datastore.Category
|
@@ -97,7 +129,7 @@ class DatastorePlugin
|
|
97
129
|
m._read_from(Model._datastore.get(key))
|
98
130
|
m
|
99
131
|
end
|
100
|
-
|
132
|
+
|
101
133
|
def self.all
|
102
134
|
#{kind}__Query__.new
|
103
135
|
end
|
@@ -105,30 +137,48 @@ class DatastorePlugin
|
|
105
137
|
end
|
106
138
|
|
107
139
|
def eval(parent, src)
|
108
|
-
|
109
|
-
transformer.transform(ast.body_node, parent)
|
140
|
+
transformer.eval(src, __FILE__, parent)
|
110
141
|
end
|
111
142
|
|
112
143
|
def extend_query(code)
|
113
|
-
query.body
|
144
|
+
query.body << eval(query.body, code)
|
114
145
|
end
|
115
146
|
|
116
147
|
def extend_read(code)
|
117
148
|
code = 'e=nil;' + code
|
118
149
|
read.body.children.concat eval(read.body, code).children[1..-1]
|
119
150
|
end
|
120
|
-
|
151
|
+
|
121
152
|
def extend_save(code)
|
122
153
|
code = 'e=nil;' + code
|
123
154
|
save.body.children.concat eval(save.body, code).children[1..-1]
|
124
155
|
end
|
125
156
|
end
|
126
|
-
|
157
|
+
|
127
158
|
def self.find_class(node)
|
128
159
|
node = node.parent until Duby::AST::ClassDefinition === node
|
129
160
|
node
|
130
161
|
end
|
131
|
-
|
162
|
+
|
163
|
+
def self.to_datastore(type, value)
|
164
|
+
if TypeMap.include?(type)
|
165
|
+
"(#{value} ? #{type}.new(#{value}) : nil)"
|
166
|
+
else
|
167
|
+
value
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.from_datastore(type, value)
|
172
|
+
duby_type = TypeMap[type]
|
173
|
+
if duby_type
|
174
|
+
default = Defaults.fetch(type, "#{duby_type}(nil)")
|
175
|
+
conversion = Conversions[type]
|
176
|
+
"(#{value} ? #{type}(#{value}).#{conversion} : #{default})"
|
177
|
+
else
|
178
|
+
"#{type}(#{value})"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
132
182
|
Duby::AST.defmacro("property") do |transformer, fcall, parent|
|
133
183
|
result = Duby::AST::Body.new(parent, fcall.position) {[]}
|
134
184
|
klass = find_class(parent)
|
@@ -141,31 +191,42 @@ class DatastorePlugin
|
|
141
191
|
name = fcall.args_node.get(0).name
|
142
192
|
type = fcall.args_node.get(1).name
|
143
193
|
|
194
|
+
duby_type = TypeMap.fetch(type, type)
|
195
|
+
|
144
196
|
model.extend_query(<<-EOF)
|
145
|
-
def #{name}(value:#{
|
197
|
+
def #{name}(value:#{duby_type})
|
146
198
|
returns :void
|
147
|
-
_query.addFilter("#{name}", _eq_op, value)
|
199
|
+
_query.addFilter("#{name}", _eq_op, #{to_datastore(type, 'value')})
|
148
200
|
end
|
149
201
|
EOF
|
150
|
-
|
202
|
+
|
203
|
+
temp = transformer.tmp
|
204
|
+
|
151
205
|
model.extend_read(<<-EOF)
|
152
|
-
|
206
|
+
#{temp} = e.getProperty("#{name}")
|
207
|
+
@#{name} = #{from_datastore(type, temp)}
|
153
208
|
EOF
|
154
|
-
|
209
|
+
|
155
210
|
model.extend_save(<<-EOF)
|
156
|
-
e.setProperty("#{name}",
|
211
|
+
e.setProperty("#{name}", #{to_datastore(type, '@' + name)})
|
157
212
|
EOF
|
158
|
-
|
159
|
-
result
|
213
|
+
|
214
|
+
result << model.eval(parent, <<-EOF)
|
160
215
|
def #{name}
|
161
216
|
@#{name}
|
162
217
|
end
|
163
|
-
|
164
|
-
def #{name}=(value:#{
|
218
|
+
|
219
|
+
def #{name}=(value:#{duby_type})
|
165
220
|
@#{name} = value
|
166
221
|
end
|
167
222
|
EOF
|
168
223
|
|
169
224
|
result
|
170
225
|
end
|
171
|
-
|
226
|
+
|
227
|
+
def self.reset
|
228
|
+
@models = {}
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
Duby.plugins << DatastorePlugin
|