duby 0.0.2-java
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/README.txt +39 -0
- data/Rakefile +13 -0
- data/bin/duby +9 -0
- data/bin/dubyc +9 -0
- data/bin/dubyp +9 -0
- data/examples/README +16 -0
- data/examples/appengine/Rakefile +72 -0
- data/examples/appengine/Readme +27 -0
- data/examples/appengine/config.ru +7 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
- data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
- data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
- data/examples/construction.duby +8 -0
- data/examples/edb.duby +3 -0
- data/examples/fib.duby +24 -0
- data/examples/fields.duby +22 -0
- data/examples/fractal.duby +57 -0
- data/examples/java_thing.duby +13 -0
- data/examples/simple_class.duby +12 -0
- data/examples/swing.duby +20 -0
- data/examples/tak.duby +15 -0
- data/examples/test.edb +9 -0
- data/javalib/JRubyParser.jar +0 -0
- data/lib/duby.rb +168 -0
- data/lib/duby/ast.rb +386 -0
- data/lib/duby/ast/call.rb +145 -0
- data/lib/duby/ast/class.rb +154 -0
- data/lib/duby/ast/flow.rb +332 -0
- data/lib/duby/ast/intrinsics.rb +56 -0
- data/lib/duby/ast/literal.rb +97 -0
- data/lib/duby/ast/local.rb +92 -0
- data/lib/duby/ast/method.rb +244 -0
- data/lib/duby/ast/structure.rb +62 -0
- data/lib/duby/ast/type.rb +93 -0
- data/lib/duby/c/compiler.rb +134 -0
- data/lib/duby/compiler.rb +282 -0
- data/lib/duby/jvm/compiler.rb +766 -0
- data/lib/duby/jvm/method_lookup.rb +193 -0
- data/lib/duby/jvm/source_compiler.rb +605 -0
- data/lib/duby/jvm/source_generator/builder.rb +387 -0
- data/lib/duby/jvm/source_generator/loops.rb +110 -0
- data/lib/duby/jvm/source_generator/precompile.rb +170 -0
- data/lib/duby/jvm/source_generator/typer.rb +11 -0
- data/lib/duby/jvm/typer.rb +131 -0
- data/lib/duby/jvm/types.rb +331 -0
- data/lib/duby/jvm/types/basic_types.rb +19 -0
- data/lib/duby/jvm/types/boolean.rb +11 -0
- data/lib/duby/jvm/types/enumerable.rb +63 -0
- data/lib/duby/jvm/types/factory.rb +155 -0
- data/lib/duby/jvm/types/floats.rb +70 -0
- data/lib/duby/jvm/types/integers.rb +110 -0
- data/lib/duby/jvm/types/intrinsics.rb +230 -0
- data/lib/duby/jvm/types/literals.rb +82 -0
- data/lib/duby/jvm/types/methods.rb +381 -0
- data/lib/duby/jvm/types/number.rb +92 -0
- data/lib/duby/nbcompiler.rb +29 -0
- data/lib/duby/old/compiler_old.rb +845 -0
- data/lib/duby/old/declaration.rb +72 -0
- data/lib/duby/old/mapper.rb +72 -0
- data/lib/duby/old/signature.rb +52 -0
- data/lib/duby/old/typer_old.rb +163 -0
- data/lib/duby/plugin/edb.rb +25 -0
- data/lib/duby/plugin/java.rb +42 -0
- data/lib/duby/plugin/math.rb +84 -0
- data/lib/duby/transform.rb +1028 -0
- data/lib/duby/typer.rb +369 -0
- data/test/TestUser.class +0 -0
- data/test/test_ast.rb +391 -0
- data/test/test_compilation.rb +98 -0
- data/test/test_java_typer.rb +199 -0
- data/test/test_javac_compiler.rb +58 -0
- data/test/test_jvm_compiler.rb +1770 -0
- data/test/test_math_plugin.rb +87 -0
- data/test/test_typer.rb +246 -0
- metadata +156 -0
data/History.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= duby
|
2
|
+
|
3
|
+
* http://kenai.com/projects/duby
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Duby is a customizable programming language featuring static types,
|
8
|
+
local type inference and a heavily Ruby-inspired syntax. Duby
|
9
|
+
currently includes a typer/compiler backend for the JVM which can
|
10
|
+
output either JVM bytecode or Java source files.
|
11
|
+
|
12
|
+
== FEATURES/PROBLEMS:
|
13
|
+
|
14
|
+
* Ruby syntax
|
15
|
+
* Compiles to .class or .java
|
16
|
+
* Fast as Java
|
17
|
+
|
18
|
+
== SYNOPSIS:
|
19
|
+
|
20
|
+
duby <script.duby>
|
21
|
+
duby -e "inline script"
|
22
|
+
dubyc <script.duby>
|
23
|
+
dubyc -e "inline script" # produces dash_e.class
|
24
|
+
dubyc -java <script.duby>
|
25
|
+
dubyc -java -e "inline script" # produces dash_e.java
|
26
|
+
|
27
|
+
== REQUIREMENTS:
|
28
|
+
|
29
|
+
* JRuby 1.4RC2 or higher.
|
30
|
+
* BiteScript 0.0.5 or higher
|
31
|
+
|
32
|
+
== INSTALL:
|
33
|
+
|
34
|
+
* gem install duby
|
35
|
+
|
36
|
+
To build from source you should have a checkout of both jruby and
|
37
|
+
bitescript in Duby's parent directory. Run "ant jar-complete" in
|
38
|
+
jruby, then in the duby directory "ant bootstrap" followed by "ant"
|
39
|
+
should build it.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'java'
|
4
|
+
|
5
|
+
task :default => :test
|
6
|
+
|
7
|
+
Rake::TestTask.new :test do |t|
|
8
|
+
t.libs << "lib"
|
9
|
+
# This is hacky, I know
|
10
|
+
t.libs.concat Dir["../bitescript*/lib"]
|
11
|
+
t.test_files = FileList["test/**/*.rb"]
|
12
|
+
java.lang.System.set_property("jruby.duby.enabled", "true")
|
13
|
+
end
|
data/bin/duby
ADDED
data/bin/dubyc
ADDED
data/bin/dubyp
ADDED
data/examples/README
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Duby: A Type-Inferred Ruby-Like JVM Language
|
2
|
+
|
3
|
+
Duby is an experimental project to create a JVM bytecode compiler for a
|
4
|
+
Ruby-like language that infers static types from argument declarations
|
5
|
+
and called methods. It is currently under development, but may eventually
|
6
|
+
be used to implement portions of JRuby, since Duby combines the terse,
|
7
|
+
neat syntax of Ruby with the performance of statically-typed Java
|
8
|
+
bytecode.
|
9
|
+
|
10
|
+
To compile the samples, run the following lines:
|
11
|
+
|
12
|
+
jruby lib/ruby/site_ruby/1.8/compiler/duby/compiler.rb <filename>
|
13
|
+
|
14
|
+
And to load and call them, use JRuby's Java integration:
|
15
|
+
|
16
|
+
CLASSPATH=. jruby -rjava -e "p Java::Foo.new.fib(35)"
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'appengine-sdk'
|
2
|
+
require 'appengine-tools/web-xml'
|
3
|
+
require 'appengine-tools/xml-formatter'
|
4
|
+
|
5
|
+
SRC = File.expand_path(File.dirname(__FILE__) + '/src')
|
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
|
12
|
+
|
13
|
+
WEB_INF_CLASSES = WAR + '/WEB-INF/classes'
|
14
|
+
WEB_XML = WAR + '/WEB-INF/web.xml'
|
15
|
+
AEWEB_XML = WAR + '/WEB-INF/appengine-web.xml'
|
16
|
+
|
17
|
+
MODEL = 'com/google/appengine/ext/duby/db/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
|
71
|
+
|
72
|
+
task :default => :server
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Run rake to compile the application and start the development server.
|
2
|
+
|
3
|
+
Requirements:
|
4
|
+
- Install the google-appengine gem (under MRI, not JRUBY)
|
5
|
+
- Have jruby on your path so dubyc can run.
|
6
|
+
|
7
|
+
Datastore API:
|
8
|
+
Model.get(key)
|
9
|
+
Model.delete(key)
|
10
|
+
Model.all -> Query
|
11
|
+
property foo, String # or any supported datastore type
|
12
|
+
# For numbers use Long or Double
|
13
|
+
|
14
|
+
instance.save
|
15
|
+
instance.key
|
16
|
+
|
17
|
+
instance.foo
|
18
|
+
instance.foo=
|
19
|
+
|
20
|
+
Query.count
|
21
|
+
Query.run -> Model[]
|
22
|
+
Query.first -> instance || nil
|
23
|
+
Query.sort(property_name)
|
24
|
+
Query.sort(property_name, true) # descending
|
25
|
+
Query.foo('foo').bar(3) # Only return instances where foo = 'foo' and bar = 3
|
26
|
+
Query.offset(10)
|
27
|
+
Query.limit(5)
|
@@ -0,0 +1,171 @@
|
|
1
|
+
class DatastorePlugin
|
2
|
+
@models = {}
|
3
|
+
|
4
|
+
class ModelState
|
5
|
+
include Duby::AST
|
6
|
+
attr_reader :kind, :query, :read, :save, :transformer
|
7
|
+
|
8
|
+
def initialize(transformer, klass, parent, position, ast)
|
9
|
+
@transformer = transformer
|
10
|
+
@kind = klass.name.split('.')[-1]
|
11
|
+
init_query(klass.name, parent, position, ast)
|
12
|
+
init_static(parent, ast)
|
13
|
+
init_read(parent, position, ast)
|
14
|
+
init_save(parent, position, ast)
|
15
|
+
end
|
16
|
+
|
17
|
+
def init_query(classname, parent, position, ast)
|
18
|
+
name = "#{classname}$Query"
|
19
|
+
@query = ClassDefinition.new(parent, position, name) do |classdef|
|
20
|
+
queryinit = <<-EOF
|
21
|
+
def initialize; end
|
22
|
+
|
23
|
+
def kind
|
24
|
+
"#{kind}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def first
|
28
|
+
it = _prepare.asIterator
|
29
|
+
if it.hasNext
|
30
|
+
e = Entity(it.next)
|
31
|
+
m = #{kind}.new
|
32
|
+
m._read_from(e)
|
33
|
+
m
|
34
|
+
else
|
35
|
+
#{kind}(nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
entities = _prepare.asList(_options)
|
41
|
+
models = #{kind}[entities.size]
|
42
|
+
it = entities.iterator
|
43
|
+
i = 0
|
44
|
+
while (it.hasNext)
|
45
|
+
e = Entity(it.next)
|
46
|
+
m = #{kind}.new
|
47
|
+
m._read_from(e)
|
48
|
+
models[i] = m
|
49
|
+
i += 1
|
50
|
+
end
|
51
|
+
models
|
52
|
+
end
|
53
|
+
EOF
|
54
|
+
[Duby::AST.type('com.google.appengine.ext.duby.db.DQuery'),
|
55
|
+
eval(classdef, queryinit)]
|
56
|
+
end
|
57
|
+
ast.children << @query
|
58
|
+
end
|
59
|
+
|
60
|
+
def init_read(parent, position, ast)
|
61
|
+
@read = eval(parent, <<-EOF)
|
62
|
+
def _read_from(e:Entity)
|
63
|
+
end
|
64
|
+
EOF
|
65
|
+
@read.body = @read.children[2] = Body.new(@read, position) {[]}
|
66
|
+
ast.children << @read
|
67
|
+
end
|
68
|
+
|
69
|
+
def init_save(parent, position, ast)
|
70
|
+
@save = eval(parent, <<-EOF)
|
71
|
+
def _save_to(e:Entity)
|
72
|
+
end
|
73
|
+
EOF
|
74
|
+
@save.body = @save.children[2] = Body.new(@save, position) {[]}
|
75
|
+
ast.children << @save
|
76
|
+
end
|
77
|
+
|
78
|
+
def init_static(parent, ast)
|
79
|
+
ast.children << eval(parent, <<-EOF)
|
80
|
+
import com.google.appengine.api.datastore.Entity
|
81
|
+
import com.google.appengine.api.datastore.Blob
|
82
|
+
import com.google.appengine.api.datastore.Category
|
83
|
+
import com.google.appengine.api.datastore.Email
|
84
|
+
import com.google.appengine.api.datastore.GeoPt
|
85
|
+
import com.google.appengine.api.datastore.IMHandle
|
86
|
+
import com.google.appengine.api.datastore.Key
|
87
|
+
import com.google.appengine.api.datastore.Link
|
88
|
+
import com.google.appengine.api.datastore.PhoneNumber
|
89
|
+
import com.google.appengine.api.datastore.PostalAddress
|
90
|
+
import com.google.appengine.api.datastore.Rating
|
91
|
+
import com.google.appengine.api.datastore.ShortBlob
|
92
|
+
import com.google.appengine.api.datastore.Text
|
93
|
+
import '#{kind}__Query__', '#{kind}$Query'
|
94
|
+
|
95
|
+
def self.get(key:Key)
|
96
|
+
m = #{kind}.new
|
97
|
+
m._read_from(Model._datastore.get(key))
|
98
|
+
m
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.all
|
102
|
+
#{kind}__Query__.new
|
103
|
+
end
|
104
|
+
EOF
|
105
|
+
end
|
106
|
+
|
107
|
+
def eval(parent, src)
|
108
|
+
ast = Duby::AST.parse_ruby(src, __FILE__)
|
109
|
+
transformer.transform(ast.body_node, parent)
|
110
|
+
end
|
111
|
+
|
112
|
+
def extend_query(code)
|
113
|
+
query.body.children << eval(query.body, code)
|
114
|
+
end
|
115
|
+
|
116
|
+
def extend_read(code)
|
117
|
+
code = 'e=nil;' + code
|
118
|
+
read.body.children.concat eval(read.body, code).children[1..-1]
|
119
|
+
end
|
120
|
+
|
121
|
+
def extend_save(code)
|
122
|
+
code = 'e=nil;' + code
|
123
|
+
save.body.children.concat eval(save.body, code).children[1..-1]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.find_class(node)
|
128
|
+
node = node.parent until Duby::AST::ClassDefinition === node
|
129
|
+
node
|
130
|
+
end
|
131
|
+
|
132
|
+
Duby::AST.defmacro("property") do |transformer, fcall, parent|
|
133
|
+
result = Duby::AST::Body.new(parent, fcall.position) {[]}
|
134
|
+
klass = find_class(parent)
|
135
|
+
unless @models[klass]
|
136
|
+
@models[klass] = ModelState.new(
|
137
|
+
transformer, klass, parent, fcall.position, result)
|
138
|
+
end
|
139
|
+
model = @models[klass]
|
140
|
+
|
141
|
+
name = fcall.args_node.get(0).name
|
142
|
+
type = fcall.args_node.get(1).name
|
143
|
+
|
144
|
+
model.extend_query(<<-EOF)
|
145
|
+
def #{name}(value:#{type})
|
146
|
+
returns :void
|
147
|
+
_query.addFilter("#{name}", _eq_op, value)
|
148
|
+
end
|
149
|
+
EOF
|
150
|
+
|
151
|
+
model.extend_read(<<-EOF)
|
152
|
+
@#{name} = #{type}(e.getProperty("#{name}"))
|
153
|
+
EOF
|
154
|
+
|
155
|
+
model.extend_save(<<-EOF)
|
156
|
+
e.setProperty("#{name}", @#{name})
|
157
|
+
EOF
|
158
|
+
|
159
|
+
result.children << model.eval(parent, <<-EOF)
|
160
|
+
def #{name}
|
161
|
+
@#{name}
|
162
|
+
end
|
163
|
+
|
164
|
+
def #{name}=(value:#{type})
|
165
|
+
@#{name} = value
|
166
|
+
end
|
167
|
+
EOF
|
168
|
+
|
169
|
+
result
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import com.google.appengine.api.datastore.DatastoreServiceFactory
|
2
|
+
import com.google.appengine.api.datastore.Entity
|
3
|
+
import com.google.appengine.api.datastore.EntityNotFoundException
|
4
|
+
import com.google.appengine.api.datastore.Key
|
5
|
+
import com.google.appengine.api.datastore.KeyFactory
|
6
|
+
import com.google.appengine.api.datastore.Query
|
7
|
+
import 'Builder', 'com.google.appengine.api.datastore.FetchOptions$Builder'
|
8
|
+
import 'FilterOperator', 'com.google.appengine.api.datastore.Query$FilterOperator'
|
9
|
+
import 'SortDirection', 'com.google.appengine.api.datastore.Query$SortDirection'
|
10
|
+
|
11
|
+
class DQuery
|
12
|
+
def initialize
|
13
|
+
@query = Query.new(kind)
|
14
|
+
end
|
15
|
+
|
16
|
+
def kind
|
17
|
+
"foo"
|
18
|
+
end
|
19
|
+
|
20
|
+
def limit(l:int)
|
21
|
+
returns :void
|
22
|
+
if @options
|
23
|
+
@options.limit(l)
|
24
|
+
else
|
25
|
+
@options = Builder.withLimit(l)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def offset(o:int)
|
30
|
+
returns :void
|
31
|
+
if @options
|
32
|
+
@options.offset(o)
|
33
|
+
else
|
34
|
+
@options = Builder.withOffset(o)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def sort(name:String)
|
39
|
+
sort(name, false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def sort(name:String, descending:boolean)
|
43
|
+
returns :void
|
44
|
+
if descending
|
45
|
+
@query.addSort(name, _desc)
|
46
|
+
else
|
47
|
+
@query.addSort(name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def count
|
52
|
+
_prepare.countEntities
|
53
|
+
end
|
54
|
+
|
55
|
+
def _query
|
56
|
+
@query
|
57
|
+
end
|
58
|
+
|
59
|
+
def _options
|
60
|
+
if @options.nil?
|
61
|
+
@options = Builder.withOffset(0)
|
62
|
+
end
|
63
|
+
@options
|
64
|
+
end
|
65
|
+
|
66
|
+
def _prepare
|
67
|
+
Model._datastore.prepare(@query)
|
68
|
+
end
|
69
|
+
|
70
|
+
def _eq_op
|
71
|
+
FilterOperator.valueOf("EQUAL")
|
72
|
+
end
|
73
|
+
|
74
|
+
def _desc
|
75
|
+
SortDirection.valueOf("DESCENDING")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Model
|
80
|
+
def initialize
|
81
|
+
end
|
82
|
+
|
83
|
+
def self._datastore
|
84
|
+
unless @service
|
85
|
+
@service = DatastoreServiceFactory.getDatastoreService
|
86
|
+
end
|
87
|
+
@service
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.delete(key:Key)
|
91
|
+
returns :void
|
92
|
+
keys = Key[1]
|
93
|
+
keys[0] = key
|
94
|
+
Model._datastore.delete(keys)
|
95
|
+
end
|
96
|
+
|
97
|
+
def kind
|
98
|
+
getClass.getSimpleName
|
99
|
+
end
|
100
|
+
|
101
|
+
def key
|
102
|
+
if @entity
|
103
|
+
@entity.getKey
|
104
|
+
else
|
105
|
+
Key(nil)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def save
|
110
|
+
Model._datastore.put(to_entity)
|
111
|
+
end
|
112
|
+
|
113
|
+
def delete
|
114
|
+
returns :void
|
115
|
+
Model.delete(key)
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_entity
|
119
|
+
unless @entity
|
120
|
+
@entity = Entity.new(kind)
|
121
|
+
end
|
122
|
+
_save_to(@entity)
|
123
|
+
@entity
|
124
|
+
end
|
125
|
+
|
126
|
+
# protected
|
127
|
+
def _save_to(e:Entity)
|
128
|
+
end
|
129
|
+
|
130
|
+
def _read_from(e:Entity)
|
131
|
+
end
|
132
|
+
end
|