mirahd 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - jruby-18mode
4
+ script: bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'mirah'
4
+
5
+ group :test do
6
+ gem 'rspec'
7
+ gem 'jeweler'
8
+ end
@@ -0,0 +1,33 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ bitescript (0.1.0)
5
+ diff-lcs (1.1.3)
6
+ git (1.2.5)
7
+ jeweler (1.8.3)
8
+ bundler (~> 1.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rdoc
12
+ json (1.7.3-java)
13
+ mirah (0.0.11-java)
14
+ bitescript (>= 0.0.8)
15
+ rake (0.9.2.2)
16
+ rdoc (3.12)
17
+ json (~> 1.4)
18
+ rspec (2.9.0)
19
+ rspec-core (~> 2.9.0)
20
+ rspec-expectations (~> 2.9.0)
21
+ rspec-mocks (~> 2.9.0)
22
+ rspec-core (2.9.0)
23
+ rspec-expectations (2.9.1)
24
+ diff-lcs (~> 1.1.3)
25
+ rspec-mocks (2.9.0)
26
+
27
+ PLATFORMS
28
+ java
29
+
30
+ DEPENDENCIES
31
+ jeweler
32
+ mirah
33
+ rspec
@@ -0,0 +1,94 @@
1
+ mirahd
2
+ ======
3
+
4
+ **mirahd** is a Mirah Daemon listening for your requests to compile something.
5
+ When it receives one it does the job quickly. _Really quickly_.
6
+
7
+ [![Build Status](https://secure.travis-ci.org/jstepien/mirahd.png?branch=master)](http://travis-ci.org/jstepien/mirahd)
8
+
9
+ Usage
10
+ -----
11
+
12
+ We'll need:
13
+
14
+ * Bundler,
15
+ * Mirah, and as a result
16
+ * JRuby 1.6.
17
+
18
+ For your own comfort and sanity it is also advisable to install a Ruby
19
+ implementation with a reasonably short start up time. MRI or Rubinius
20
+ are good candidates.
21
+
22
+ jruby -S bundle install
23
+ jruby -S rspec test
24
+ jruby -rubygems -I lib -S bin/mirahd --daemon
25
+ ruby -I lib bin/mirahd test/hello.mirah
26
+
27
+ Rationale
28
+ ---------
29
+
30
+ Mirah is a lovely language but its low compilation speed might be discouraging.
31
+ Using it in development based on a lot of small _code, test, refactor_ cycles
32
+ might be problematic. JVM's start up time and a lag introduced by compilation
33
+ of Mirah's sources by JRuby add up to the sum we see below¹.
34
+
35
+ $ time mirahc test/hello.mirah > /dev/null # with disk's cache warmed up
36
+ 18.60user 0.45system 0:11.85elapsed
37
+
38
+ After the initial warm up JVM and JRuby are pretty fast. The goal of this
39
+ project is to make the JVM start once only and then reuse the existing process
40
+ for all subsequent compilation tasks.
41
+
42
+ Run the daemon.
43
+
44
+ $ jruby -rubygems -I lib -S bin/mirahd --daemon
45
+
46
+ The first compilation is already quite quick.
47
+
48
+ $ time ruby -I lib -S bin/mirahd test/hello.mirah
49
+ 0.05user 0.00system 0:00.89elapsed
50
+
51
+ Then JVM's JIT comes into play. Here's the tenth compilation.
52
+
53
+ $ time ruby -I lib -S bin/mirahd test/hello.mirah
54
+ 0.04user 0.00system 0:00.30elapsed
55
+
56
+ Todo
57
+ ----
58
+
59
+ * Security. By being able to access the port DRb is listening on you
60
+ can `eval` whatever you want to. `$SAFE` won't work as it's unsupported
61
+ by JRuby.
62
+ * Enable users to specify the port number.
63
+ * Write tests covering a server running in a different directory then the
64
+ client. It won't be possible without spawning 2 separate processes.
65
+ * Support `--help` et al. command line arguments.
66
+ * Concurrency. Two compilation requests might interfere with each other,
67
+ especially due to changing the current working directory.
68
+
69
+ Copyrights
70
+ ----------
71
+
72
+ Copyright (c) 2012 Jan Stępień
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ "Software"), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
88
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
89
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
90
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
91
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
92
+
93
+ ___
94
+ ¹ That's a 64-bit OpenJDK 6 on Intel Core 2 Duo with GNU/Linux 3.2.8.
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "mirahd"
18
+ gem.homepage = "https://github.com/jstepien/mirahd"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Mirah compilation daemon (in dire need of Javanese name)}
21
+ gem.description = File.read "README.md"
22
+ gem.email = "jstepien@users.sourceforge.net"
23
+ gem.authors = ["Jan Stępień"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['test/**/*_spec.rb']
32
+ end
33
+
34
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ if ARGV.include? '--daemon'
3
+ require 'mirahd/server'
4
+ server = MirahD::Server.new
5
+ server.start
6
+ puts 'Ready.' unless ARGV.include? '--quiet'
7
+ server.wait
8
+ else
9
+ require 'mirahd/client'
10
+ begin
11
+ puts MirahD::Client.new.compile ARGV
12
+ rescue => ex
13
+ $stderr.puts ex.message
14
+ exit 1
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ require 'drb/drb'
2
+ require 'fileutils'
3
+
4
+ module MirahD
5
+ class Client
6
+ URI = 'druby://localhost:8787'
7
+
8
+ def compile args
9
+ DRbObject.new_with_uri(URI).compile args, FileUtils.pwd
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ require 'drb/drb'
2
+ require 'stringio'
3
+ require 'mirah'
4
+
5
+ module MirahD
6
+ class Server
7
+ class Compiler
8
+ def compile args, dir = FileUtils.pwd
9
+ intercepting_stdout do
10
+ FileUtils.cd dir do
11
+ Mirah::Commands::Compile.new(args).execute
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def intercepting_stdout
19
+ orig_stdout = $stdout
20
+ $stdout = StringIO.new 'w'
21
+ yield
22
+ rescue Exception => ex
23
+ new_ex = StandardError.new $stdout.string
24
+ new_ex.set_backtrace ex.backtrace
25
+ raise new_ex
26
+ else
27
+ $stdout.string
28
+ ensure
29
+ $stdout = orig_stdout
30
+ end
31
+ end
32
+
33
+ URI = 'druby://localhost:8787'
34
+
35
+ def start
36
+ DRb.start_service URI, Compiler.new
37
+ true
38
+ end
39
+
40
+ def stop
41
+ raise 'The server has not been started yet' unless running?
42
+ DRb.stop_service
43
+ true
44
+ end
45
+
46
+ def wait
47
+ DRb.thread.join if running?
48
+ true
49
+ end
50
+
51
+ def running?
52
+ not DRb.thread.nil? and DRb.thread.alive?
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,51 @@
1
+ require 'test/common'
2
+ require 'mirahd/server'
3
+ require 'mirahd/client'
4
+
5
+ describe MirahD::Client do
6
+ before :all do
7
+ wait_for_the_port_to_become_free 8787
8
+ @server = MirahD::Server.new
9
+ @server.start
10
+ end
11
+
12
+ after :all do
13
+ @server.stop
14
+ end
15
+
16
+ before do
17
+ @client = MirahD::Client.new
18
+ end
19
+
20
+ after do
21
+ rm_f_temp_files
22
+ end
23
+
24
+ it 'can compile to Java source code' do
25
+ @client.compile(['--java', Source]).should_not be_nil
26
+ File.file?(JavaFile).should == true
27
+ end
28
+
29
+ it 'can compile a JVM class' do
30
+ @client.compile([Source]).should_not be_nil
31
+ File.file?(ClassFile).should == true
32
+ end
33
+
34
+ it 'receives compiler\'s standard output' do
35
+ @client.compile([Source]).should =~ /^Parsing.*Inferring.*Done!$/m
36
+ end
37
+
38
+ describe 'after failed compilation' do
39
+ it 'receives an exception' do
40
+ lambda { @client.compile([BadSource]) } .should raise_error StandardError
41
+ end
42
+
43
+ it 'receives error messages' do
44
+ begin
45
+ @client.compile([BadSource])
46
+ rescue => ex
47
+ ex.message.should =~ /^Parsing.*expected statement.*at line/m
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,32 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rspec'
4
+ require 'fileutils'
5
+ require 'socket'
6
+
7
+ Source = 'test/hello.mirah'
8
+ BadSource = 'Gemfile.lock'
9
+ JavaFile = 'test/Hello.java'
10
+ ClassFile = 'test/Hello.class'
11
+
12
+ def rm_f_temp_files
13
+ [JavaFile, ClassFile].each { |file| FileUtils.rm_f file }
14
+ end
15
+
16
+ # This function tries to connect to a given TCP port and close the socket
17
+ # immediately after getting connected. If TCPSocket#new raises an error it
18
+ # means that the port is free and we can begin testing.
19
+ #
20
+ # This function prevents spurious Errno::EADDRINUSE errors which happened from
21
+ # time to time when the port didn't get completely freed before proceeding to
22
+ # a next test.
23
+ def wait_for_the_port_to_become_free port
24
+ while true
25
+ begin
26
+ TCPSocket.new('localhost', port).close
27
+ rescue
28
+ return
29
+ end
30
+ sleep 0.1
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ class Hello
2
+ def hi
3
+ puts "Witaj, Świecie!"
4
+ end
5
+ end
6
+
7
+ Hello.new.hi
@@ -0,0 +1,93 @@
1
+ require 'test/common'
2
+ require 'drb/drb'
3
+ require 'mirahd/server'
4
+
5
+ describe MirahD::Server do
6
+ before do
7
+ wait_for_the_port_to_become_free 8787
8
+ @server = MirahD::Server.new
9
+ end
10
+
11
+ it 'can be started and stopped' do
12
+ @server.start.should == true
13
+ @server.stop.should == true
14
+ end
15
+
16
+ it 'is not running by default' do
17
+ @server.running?.should == false
18
+ end
19
+
20
+ it 'knows when it is stopped' do
21
+ @server.start
22
+ @server.stop
23
+ @server.running?.should == false
24
+ end
25
+
26
+ it 'cannot be stopped before being started' do
27
+ lambda { @server.stop } .should raise_error
28
+ end
29
+
30
+ describe 'when online' do
31
+ before do
32
+ @server.start
33
+ @remote = DRbObject.new_with_uri 'druby://localhost:8787'
34
+ end
35
+
36
+ after do
37
+ @server.stop if @server.running?
38
+ rm_f_temp_files
39
+ end
40
+
41
+ it 'knows that it is running' do
42
+ @server.running?.should == true
43
+ end
44
+
45
+ it 'cannot be started once again' do
46
+ lambda { @server.start } .should raise_error
47
+ end
48
+
49
+ it 'listens on port 8787' do
50
+ @remote.should respond_to :object_id
51
+ end
52
+
53
+ it 'responds to compile' do
54
+ @remote.should respond_to :compile
55
+ end
56
+
57
+ it 'the #wait method should keep it running' do
58
+ # FIXME: busy waiting is considered evil.
59
+ failed = false
60
+ thr = Thread.start do
61
+ @server.wait
62
+ failed = @server.running?
63
+ end
64
+ sleep 0.1 until @server.running?
65
+ @server.stop
66
+ thr.join
67
+ failed.should == false
68
+ end
69
+
70
+ describe 'and given a valid input file' do
71
+ it 'should compile it to Java' do
72
+ @remote.compile(['--java', Source]).should_not be_nil
73
+ File.file?(JavaFile).should == true
74
+ end
75
+
76
+ it 'should compile it to a JVM class' do
77
+ @remote.compile([Source]).should_not be_nil
78
+ File.file?(ClassFile).should == true
79
+ end
80
+ end
81
+
82
+ describe 'and given an invalid input file' do
83
+ it 'should fail' do
84
+ lambda { @remote.compile [BadSource] } .should raise_error
85
+ end
86
+
87
+ it 'should not be killed after handling it' do
88
+ lambda { @remote.compile [BadSource] } .should raise_error
89
+ @remote.should respond_to :compile
90
+ end
91
+ end
92
+ end
93
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mirahd
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.0
6
+ platform: ruby
7
+ authors:
8
+ - "Jan St\xC4\x99pie\xC5\x84"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-06-10 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mirah
17
+ version_requirements: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ requirement: *id001
24
+ prerelease: false
25
+ type: :runtime
26
+ description: "mirahd\n\
27
+ ======\n\n\
28
+ **mirahd** is a Mirah Daemon listening for your requests to compile something.\n\
29
+ When it receives one it does the job quickly. _Really quickly_.\n\n\
30
+ [![Build Status](https://secure.travis-ci.org/jstepien/mirahd.png?branch=master)](http://travis-ci.org/jstepien/mirahd)\n\n\
31
+ Usage\n\
32
+ -----\n\n\
33
+ We'll need:\n\n * Bundler,\n * Mirah, and as a result\n * JRuby 1.6.\n\n\
34
+ For your own comfort and sanity it is also advisable to install a Ruby\n\
35
+ implementation with a reasonably short start up time. MRI or Rubinius\n\
36
+ are good candidates.\n\n jruby -S bundle install\n jruby -S rspec test\n jruby -rubygems -I lib -S bin/mirahd --daemon\n ruby -I lib bin/mirahd test/hello.mirah\n\n\
37
+ Rationale\n\
38
+ ---------\n\n\
39
+ Mirah is a lovely language but its low compilation speed might be discouraging.\n\
40
+ Using it in development based on a lot of small _code, test, refactor_ cycles\n\
41
+ might be problematic. JVM's start up time and a lag introduced by compilation\n\
42
+ of Mirah's sources by JRuby add up to the sum we see below\xC2\xB9.\n\n $ time mirahc test/hello.mirah > /dev/null # with disk's cache warmed up\n 18.60user 0.45system 0:11.85elapsed\n\n\
43
+ After the initial warm up JVM and JRuby are pretty fast. The goal of this\n\
44
+ project is to make the JVM start once only and then reuse the existing process\n\
45
+ for all subsequent compilation tasks.\n\n\
46
+ Run the daemon.\n\n $ jruby -rubygems -I lib -S bin/mirahd --daemon\n\n\
47
+ The first compilation is already quite quick.\n\n $ time ruby -I lib -S bin/mirahd test/hello.mirah\n 0.05user 0.00system 0:00.89elapsed\n\n\
48
+ Then JVM's JIT comes into play. Here's the tenth compilation.\n\n $ time ruby -I lib -S bin/mirahd test/hello.mirah\n 0.04user 0.00system 0:00.30elapsed\n\n\
49
+ Todo\n\
50
+ ----\n\n * Security. By being able to access the port DRb is listening on you\n can `eval` whatever you want to. `$SAFE` won't work as it's unsupported\n by JRuby.\n * Enable users to specify the port number.\n * Write tests covering a server running in a different directory then the\n client. It won't be possible without spawning 2 separate processes.\n * Support `--help` et al. command line arguments.\n * Concurrency. Two compilation requests might interfere with each other,\n especially due to changing the current working directory.\n\n\
51
+ Copyrights\n\
52
+ ----------\n\n\
53
+ Copyright (c) 2012 Jan St\xC4\x99pie\xC5\x84\n\n\
54
+ Permission is hereby granted, free of charge, to any person obtaining\n\
55
+ a copy of this software and associated documentation files (the\n\
56
+ \"Software\"), to deal in the Software without restriction, including\n\
57
+ without limitation the rights to use, copy, modify, merge, publish,\n\
58
+ distribute, sublicense, and/or sell copies of the Software, and to\n\
59
+ permit persons to whom the Software is furnished to do so, subject to\n\
60
+ the following conditions:\n\n\
61
+ The above copyright notice and this permission notice shall be\n\
62
+ included in all copies or substantial portions of the Software.\n\n\
63
+ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\
64
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\
65
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\
66
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n\
67
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n\
68
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n\
69
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\
70
+ ___\n\
71
+ \xC2\xB9 That's a 64-bit OpenJDK 6 on Intel Core 2 Duo with GNU/Linux 3.2.8.\n"
72
+ email: jstepien@users.sourceforge.net
73
+ executables:
74
+ - mirahd
75
+ extensions: []
76
+
77
+ extra_rdoc_files:
78
+ - README.md
79
+ files:
80
+ - .rspec
81
+ - .travis.yml
82
+ - Gemfile
83
+ - Gemfile.lock
84
+ - README.md
85
+ - Rakefile
86
+ - VERSION
87
+ - bin/mirahd
88
+ - lib/mirahd/client.rb
89
+ - lib/mirahd/server.rb
90
+ - test/client_spec.rb
91
+ - test/common.rb
92
+ - test/hello.mirah
93
+ - test/server_spec.rb
94
+ homepage: https://github.com/jstepien/mirahd
95
+ licenses:
96
+ - MIT
97
+ post_install_message:
98
+ rdoc_options: []
99
+
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 2
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.15
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Mirah compilation daemon (in dire need of Javanese name)
124
+ test_files: []
125
+