duby 0.0.2-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 (77) hide show
  1. data/History.txt +8 -0
  2. data/README.txt +39 -0
  3. data/Rakefile +13 -0
  4. data/bin/duby +9 -0
  5. data/bin/dubyc +9 -0
  6. data/bin/dubyp +9 -0
  7. data/examples/README +16 -0
  8. data/examples/appengine/Rakefile +72 -0
  9. data/examples/appengine/Readme +27 -0
  10. data/examples/appengine/config.ru +7 -0
  11. data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
  12. data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
  13. data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
  14. data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
  15. data/examples/construction.duby +8 -0
  16. data/examples/edb.duby +3 -0
  17. data/examples/fib.duby +24 -0
  18. data/examples/fields.duby +22 -0
  19. data/examples/fractal.duby +57 -0
  20. data/examples/java_thing.duby +13 -0
  21. data/examples/simple_class.duby +12 -0
  22. data/examples/swing.duby +20 -0
  23. data/examples/tak.duby +15 -0
  24. data/examples/test.edb +9 -0
  25. data/javalib/JRubyParser.jar +0 -0
  26. data/lib/duby.rb +168 -0
  27. data/lib/duby/ast.rb +386 -0
  28. data/lib/duby/ast/call.rb +145 -0
  29. data/lib/duby/ast/class.rb +154 -0
  30. data/lib/duby/ast/flow.rb +332 -0
  31. data/lib/duby/ast/intrinsics.rb +56 -0
  32. data/lib/duby/ast/literal.rb +97 -0
  33. data/lib/duby/ast/local.rb +92 -0
  34. data/lib/duby/ast/method.rb +244 -0
  35. data/lib/duby/ast/structure.rb +62 -0
  36. data/lib/duby/ast/type.rb +93 -0
  37. data/lib/duby/c/compiler.rb +134 -0
  38. data/lib/duby/compiler.rb +282 -0
  39. data/lib/duby/jvm/compiler.rb +766 -0
  40. data/lib/duby/jvm/method_lookup.rb +193 -0
  41. data/lib/duby/jvm/source_compiler.rb +605 -0
  42. data/lib/duby/jvm/source_generator/builder.rb +387 -0
  43. data/lib/duby/jvm/source_generator/loops.rb +110 -0
  44. data/lib/duby/jvm/source_generator/precompile.rb +170 -0
  45. data/lib/duby/jvm/source_generator/typer.rb +11 -0
  46. data/lib/duby/jvm/typer.rb +131 -0
  47. data/lib/duby/jvm/types.rb +331 -0
  48. data/lib/duby/jvm/types/basic_types.rb +19 -0
  49. data/lib/duby/jvm/types/boolean.rb +11 -0
  50. data/lib/duby/jvm/types/enumerable.rb +63 -0
  51. data/lib/duby/jvm/types/factory.rb +155 -0
  52. data/lib/duby/jvm/types/floats.rb +70 -0
  53. data/lib/duby/jvm/types/integers.rb +110 -0
  54. data/lib/duby/jvm/types/intrinsics.rb +230 -0
  55. data/lib/duby/jvm/types/literals.rb +82 -0
  56. data/lib/duby/jvm/types/methods.rb +381 -0
  57. data/lib/duby/jvm/types/number.rb +92 -0
  58. data/lib/duby/nbcompiler.rb +29 -0
  59. data/lib/duby/old/compiler_old.rb +845 -0
  60. data/lib/duby/old/declaration.rb +72 -0
  61. data/lib/duby/old/mapper.rb +72 -0
  62. data/lib/duby/old/signature.rb +52 -0
  63. data/lib/duby/old/typer_old.rb +163 -0
  64. data/lib/duby/plugin/edb.rb +25 -0
  65. data/lib/duby/plugin/java.rb +42 -0
  66. data/lib/duby/plugin/math.rb +84 -0
  67. data/lib/duby/transform.rb +1028 -0
  68. data/lib/duby/typer.rb +369 -0
  69. data/test/TestUser.class +0 -0
  70. data/test/test_ast.rb +391 -0
  71. data/test/test_compilation.rb +98 -0
  72. data/test/test_java_typer.rb +199 -0
  73. data/test/test_javac_compiler.rb +58 -0
  74. data/test/test_jvm_compiler.rb +1770 -0
  75. data/test/test_math_plugin.rb +87 -0
  76. data/test/test_typer.rb +246 -0
  77. metadata +156 -0
@@ -0,0 +1,8 @@
1
+ === 0.0.2 / 2010-02-15
2
+
3
+ * More language features added
4
+
5
+ === 0.0.1 / 2009-10-27
6
+
7
+ * First gem release
8
+ * Most things necessary for simple apps, scripts, servlets are working
@@ -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.
@@ -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
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env jruby
2
+ begin
3
+ require 'duby'
4
+ rescue LoadError
5
+ $: << File.dirname(File.dirname(__FILE__)) + '/lib'
6
+ require 'duby'
7
+ end
8
+
9
+ Duby.run(*ARGV)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env jruby
2
+ begin
3
+ require 'duby'
4
+ rescue LoadError
5
+ $: << File.dirname(File.dirname(__FILE__)) + '/lib'
6
+ require 'duby'
7
+ end
8
+
9
+ Duby.compile(*ARGV)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env jruby
2
+ begin
3
+ require 'duby'
4
+ rescue LoadError
5
+ $: << File.dirname(File.dirname(__FILE__)) + '/lib'
6
+ require 'duby'
7
+ end
8
+
9
+ puts Duby.parse(*ARGV).inspect
@@ -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,7 @@
1
+ require 'appengine-rack'
2
+ require 'appengine-rack/java'
3
+
4
+ # TODO: Fill in your app id
5
+ AppEngine::Rack.app.configure(:application => '', :version => '1')
6
+
7
+ run JavaServlet.new('com.ribrdb.DubyApp')
@@ -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