haskell 0.2.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f7af12f3fa2dceabef05ccb39a3f7853c69ab0a
4
- data.tar.gz: 93808939d0d3e5a156f03e826a6a79bdbb548b59
3
+ metadata.gz: ac0c087788b1e471523aed86d8dfd0c42be2503d
4
+ data.tar.gz: 610eff264b8bdc1903ea519e857a5346f461aad6
5
5
  SHA512:
6
- metadata.gz: e1e2484689e7c753b2910b936391a3bcea009a48832855b8999ee2a74092215d50fb0747533e61fce8cc7895087539112ba38705f8d2336a03f01c16b2ff62c0
7
- data.tar.gz: 00ffb2cb3a0786ca43a3701b396214cc29465573125bf949af52b210c9081d90338f48635924a23639f3e18c184bb6a0650ff7c05058e0c888a44b24c1a28c88
6
+ metadata.gz: 788e9b367f36ec0420f44fa89166768073332e8748aab5acd65f9c1796e1953367a2e9ed9bc5b738e0fdf53f6eb329237205e6a6dd819851f437b92264f7ccd5
7
+ data.tar.gz: ae3aa09d9fd3af02d5361bccc45f33d27f6e153b5f9a2a2810693493bd18c5fc8a33f4d35ccd5e19f6be4ff179346376f9533753fad70665614055f42081f174
data/README.md CHANGED
@@ -1,107 +1,17 @@
1
- # Ruby with Type.
2
-
3
- Matz has mentioned Ruby3.0 with static type at some confluences. But almost all rubyists(include me) are not sure how typed Ruby is.
4
-
5
- But it's worth thinking more. This gem is kind of trial without so much side-effect.
1
+ # Haskell On Ruby
6
2
 
7
3
  ```rb
8
4
  require 'haskell'
9
-
10
- # ex1
11
- class MyClass
12
- def sum(x, y)
13
- x + y
14
- end
15
- typesig sum: [Numeric, Numeric => Numeric]
16
-
17
- def wrong_sum(x, y)
18
- 'string'
19
- end
20
- typesig wrong_sum: [Numeric, Numeric => Numeric]
5
+ Haskell.compile %{
6
+ add :: Integer -> Integer -> Integer
7
+ add x y = x + y
8
+ result = add 1 2
9
+ }
10
+
11
+ while Haskell.compiling?
12
+ ...
21
13
  end
22
14
 
23
- MyClass.new.sum(1, 2)
15
+ p Haskell.execute
24
16
  #=> 3
25
-
26
- MyClass.new.sum(1, 'string')
27
- #=> ArgumentError: Wrong type of argument, type of "str" should be Numeric
28
-
29
- MyClass.new.wrong_sum(1, 2)
30
- #=> TypeError: Expected wrong_sum to return Numeric but got "str" instead
31
-
32
-
33
- # ex2
34
- class People
35
- type People >= Any, def marry(people)
36
- # Your Ruby code as usual
37
- end
38
- end
39
- typesig marry: [People => Any]
40
-
41
- People.new.marry(People.new)
42
- #=> no error
43
-
44
- People.new.marry('non people')
45
- #=> ArgumentError: Wrong type of argument, type of "non people" should be People
46
17
  ```
47
-
48
- ## Feature
49
- ### Typed method can coexist with non-typed method
50
-
51
- ```ruby
52
- # It's totally OK!!
53
- class MyClass
54
- def sum(x, y)
55
- x + y
56
- end
57
- typesig sum: [Numeric, Numeric => Numeric]
58
-
59
- def sum_without_type(x, y)
60
- 'string'
61
- end
62
- end
63
- ```
64
-
65
- ### Duck typing
66
-
67
- ```ruby
68
-
69
- class MyClass
70
- def foo(any_obj)
71
- 1
72
- end
73
- typesig sum: [Any => Numeric]
74
- end
75
-
76
- # It's totally OK!!
77
- MyClass.new.foo(1)
78
- # It's totally OK!!
79
- MyClass.new.foo('str')
80
- ```
81
-
82
- ## Installation
83
-
84
- gem install haskell or add gem 'haskell' to your Gemfile.
85
-
86
- This gem requires Ruby 2.0.0+.
87
-
88
- ### Contributing
89
-
90
- Fork it ( https://github.com/[my-github-username]/haskell/fork )
91
-
92
- Create your feature branch (`git checkout -b my-new-feature`)
93
-
94
- $ bundle install --path vendor/bundle
95
-
96
- Commit your changes (`git commit -am 'Add some feature'`)
97
-
98
- $ bundle exec rake test
99
-
100
- > 5 runs, 39 assertions, 0 failures, 0 errors, 0 skips
101
-
102
- Push to the branch (`git push origin my-new-feature`)
103
-
104
- Create a new Pull Request
105
-
106
- ## Credits
107
- [@chancancode](https://github.com/chancancode) first brought this to my attention. I've stolen some idea from him.
data/lib/haskell.rb CHANGED
@@ -1,48 +1,73 @@
1
- # Builtin Contracts
2
- class Any; end
3
- module Boolean; end
4
- TrueClass.send(:include, Boolean)
5
- FalseClass.send(:include, Boolean)
6
-
7
- class Module
8
- private
9
- def __haskell__
10
- prepend (@__haskell__ = Module.new) unless @__haskell__
11
- @__haskell__
12
- end
1
+ module Haskell
2
+ # TODO:
3
+ class HaskellCompileError < StandardError; end
13
4
 
14
- def typesig(hash)
15
- meth = hash.keys.first
16
- *arg_types, type_pair = hash.values.first
5
+ class << self
6
+ def invoke_sandbox!
7
+ file_path = File.expand_path('../', __FILE__)
8
+ $sandbox_path = "#{file_path}/haskell_executing_sandbox"
9
+ FileUtils.mkdir($sandbox_path) unless Dir.exist?($sandbox_path)
10
+ end
17
11
 
18
- __haskell__.send(:define_method, meth) do |*args, &block|
19
- ::Haskell.assert_arg_type(meth, args, arg_types << type_pair.keys.first)
20
- rtn = super(*args, &block)
21
- ::Haskell.assert_trn_type(meth, rtn, type_pair.values.first)
22
- rtn
12
+ def revoke_sandbox!
13
+ FileUtils.rm_rf($sandbox_path)
23
14
  end
24
- self
25
- end
26
- end
27
15
 
28
- module Haskell
29
- class << self
30
- def assert_arg_type(meth, args, klasses)
31
- args.each_with_index do |arg, i|
32
- if wrong_type?(arg, klasses[i])
33
- raise ArgumentError, "Wrong type of argument, type of #{arg.inspect} should be #{klasses[i]}"
16
+ def compile(hs_code)
17
+ FileUtils.touch("#{$sandbox_path}/COMPILING")
18
+ #TODO: need inform user prefer message
19
+ Thread.abort_on_exception = true
20
+ Thread.new do
21
+ begin
22
+ executable_code = executable_code(hs_code)
23
+ puts_notation(executable_code)
24
+ File.write("#{$sandbox_path}/tmp.hs", executable_code)
25
+ Kernel.system("ghc #{$sandbox_path}/tmp.hs")
26
+ raise HaskellCompileError unless compiled?
27
+ ensure
28
+ FileUtils.rm("#{$sandbox_path}/COMPILING")
34
29
  end
35
30
  end
31
+ rescue
32
+ raise "Something wrong...https://github.com/Azabuhs/Ruby/issues"
36
33
  end
37
34
 
38
- def assert_trn_type(meth, rtn, klass)
39
- if wrong_type?(rtn, klass)
40
- raise TypeError, "Expected #{meth} to return #{klass} but got #{rtn.inspect} instead"
41
- end
35
+ def compiling?
36
+ File.exist?("#{$sandbox_path}/COMPILING")
42
37
  end
43
38
 
44
- def wrong_type?(obj, klass)
45
- !(obj.is_a?(klass) || klass == Any)
39
+ def compiled?
40
+ File.exist?("#{$sandbox_path}/tmp")
41
+ end
42
+
43
+ def execute
44
+ `#{$sandbox_path}/tmp`.gsub(/\n\z/, '')
45
+ end
46
+
47
+ private
48
+
49
+ def executable_code(hs_code)
50
+ # TODO: other white space
51
+ hs_code =~/\A\n( *)/
52
+ hs_code.gsub!(/\n#{$1}/, "\n")
53
+ <<-HASKELL_CODE
54
+ module Main where
55
+ #{hs_code}
56
+ main = do putStrLn $ show result
57
+ HASKELL_CODE
58
+ end
59
+
60
+ def puts_notation(executable_code)
61
+ puts <<-NOTATION
62
+ # GHC will compile below code
63
+ ###############################
64
+ NOTATION
65
+
66
+ puts '# ' + executable_code.gsub("\n", "\n# ")
67
+
68
+ puts <<-NOTATION
69
+ ###############################
70
+ NOTATION
46
71
  end
47
72
  end
48
73
  end
@@ -1,3 +1,3 @@
1
1
  module Haskell
2
- VERSION = "0.2.3"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,46 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestHaskell < MiniTest::Unit::TestCase
4
+ def test_main
5
+ assert_equal_execute('3') {"
6
+ add :: Integer -> Integer -> Integer
7
+ add x y = x + y
8
+ result = add 1 2
9
+ "}
10
+
11
+ assert_equal_execute('[3.1415927,4.0]') {"
12
+ data Point = Pt Float Float deriving (Show)
13
+ data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
14
+ surface :: Shape -> Float
15
+ surface (Circle _ r) | r > 0 = pi * r ^ 2
16
+ | otherwise = 0
17
+
18
+ surface (Rectangle (Pt x1 y1) (Pt x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
19
+
20
+ result = [surface (Circle (Pt 0 0) 1), surface (Rectangle (Pt 2 3) (Pt 4 5))]
21
+ "}
22
+
23
+ assert_raise_compile_error {"
24
+ Error
25
+ "}
26
+ end
27
+
28
+ private
29
+ def assert_equal_execute(str, &block)
30
+ Haskell.invoke_sandbox!
31
+ Haskell.compile(block.call)
32
+ nil while Haskell.compiling?
33
+ assert_equal str, Haskell.execute
34
+ Haskell.revoke_sandbox!
35
+ end
36
+
37
+ def assert_raise_compile_error(&block)
38
+ Haskell.invoke_sandbox!
39
+ Haskell.compile(block.call)
40
+ nil while Haskell.compiling?
41
+ # TODO: more prefer test
42
+ rescue Haskell::HaskellCompileError
43
+ assert(true)
44
+ Haskell.revoke_sandbox!
45
+ end
46
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haskell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gogotanaka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-07 00:00:00.000000000 Z
11
+ date: 2014-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,7 +85,7 @@ files:
85
85
  - lib/haskell/version.rb
86
86
  - rubype.gemspec
87
87
  - test/minitest_helper.rb
88
- - test/test_rubype.rb
88
+ - test/test_haskell.rb
89
89
  homepage: http://gogotanaka.me/
90
90
  licenses:
91
91
  - MIT
@@ -112,4 +112,4 @@ specification_version: 4
112
112
  summary: Ruby with type.
113
113
  test_files:
114
114
  - test/minitest_helper.rb
115
- - test/test_rubype.rb
115
+ - test/test_haskell.rb
data/test/test_rubype.rb DELETED
@@ -1,107 +0,0 @@
1
- require 'minitest_helper'
2
- class TypePair
3
- def to_s
4
- "#{last_arg_type} => #{rtn_type}"
5
- end
6
- end
7
- class TestHaskell < MiniTest::Unit::TestCase
8
- def setup
9
- @string = 'str'
10
- @numeric = 1
11
- @symbol = :test
12
- @array = [1, 2, 3]
13
- @hash = { test: :hash }
14
- end
15
-
16
- def test_correct_type
17
- assert_correct_type [Numeric => Numeric], [@numeric], @numeric
18
- assert_correct_type [Numeric => Array ], [@numeric], @array
19
- assert_correct_type [Numeric => String ], [@numeric], @string
20
- assert_correct_type [Numeric => Hash ], [@numeric], @hash
21
- assert_correct_type [Numeric => Symbol ], [@numeric], @symbol
22
- assert_correct_type [Numeric => Boolean], [@numeric], true
23
- assert_correct_type [Numeric => Boolean], [@numeric], false
24
-
25
- assert_correct_type [Boolean, Numeric => Numeric], [true, @numeric], @numeric
26
- assert_correct_type [Boolean, Array => Array ], [true, @array ], @array
27
- assert_correct_type [Boolean, String => String ], [true, @string ], @string
28
- assert_correct_type [Boolean, Hash => Hash ], [true, @hash ], @hash
29
- assert_correct_type [Boolean, Symbol => Symbol ], [true, @symbol ], @symbol
30
- end
31
-
32
- def test_wrong_return_type
33
- assert_wrong_rtn [Numeric => Numeric], [@numeric], @array
34
- assert_wrong_rtn [Numeric => Numeric], [@numeric], @string
35
- assert_wrong_rtn [Numeric => Numeric], [@numeric], @hash
36
- assert_wrong_rtn [Numeric => Numeric], [@numeric], @symbol
37
- assert_wrong_rtn [Numeric => Numeric], [@numeric], true
38
-
39
- assert_wrong_rtn [Numeric, Numeric => Numeric], [@numeric, @numeric], @array
40
- assert_wrong_rtn [Numeric, Numeric => Numeric], [@numeric, @numeric], @string
41
- assert_wrong_rtn [Numeric, Numeric => Numeric], [@numeric, @numeric], @hash
42
- assert_wrong_rtn [Numeric, Numeric => Numeric], [@numeric, @numeric], @symbol
43
- assert_wrong_rtn [Numeric, Numeric => Numeric], [@numeric, @numeric], true
44
- end
45
-
46
- def test_wrong_args_type
47
- assert_wrong_arg [Numeric => Numeric], [@array ], @numeric
48
- assert_wrong_arg [Numeric => Numeric], [@string], @numeric
49
- assert_wrong_arg [Numeric => Numeric], [@hash ], @numeric
50
- assert_wrong_arg [Numeric => Numeric], [@symbol], @numeric
51
- assert_wrong_arg [Numeric => Numeric], [true ], @numeric
52
-
53
- assert_wrong_arg [Numeric, Numeric => Numeric], [@numeric, @array ], @numeric
54
- assert_wrong_arg [Numeric, Numeric => Numeric], [@numeric, @string], @numeric
55
- assert_wrong_arg [Numeric, Numeric => Numeric], [@numeric, @hash ], @numeric
56
- assert_wrong_arg [Numeric, Numeric => Numeric], [@numeric, @symbol], @numeric
57
- assert_wrong_arg [Numeric, Numeric => Numeric], [@numeric, true ], @numeric
58
- end
59
-
60
- def test_any
61
- assert_correct_type [Any => Any], [@array ], @numeric
62
- assert_correct_type [Any => Any], [@string], @numeric
63
- assert_correct_type [Any => Any], [@hash ], @numeric
64
- assert_correct_type [Any => Any], [@symbol], @numeric
65
-
66
- assert_correct_type [Any, Any => Any], [@numeric, @array ], @numeric
67
- assert_correct_type [Any, Any => Any], [@numeric, @string], @numeric
68
- assert_correct_type [Any, Any => Any], [@numeric, @hash ], @numeric
69
- assert_correct_type [Any, Any => Any], [@numeric, @symbol], @numeric
70
- end
71
-
72
- private
73
- def assert_equal_to_s(str, val)
74
- assert_equal str, val.to_s
75
- end
76
-
77
- def assert_correct_type(type_list, args, val)
78
- assert_equal val, define_test_method(type_list, args, val).call(*args)
79
- end
80
-
81
- def assert_wrong_arg(type_list, args, val)
82
- assert_raises(ArgumentError) { define_test_method(type_list, args, val).call(*args) }
83
- end
84
-
85
- def assert_wrong_rtn(type_list, args, val)
86
- assert_raises(TypeError) { define_test_method(type_list, args, val).call(*args) }
87
- end
88
-
89
- def define_test_method(type_list, args, val)
90
- klass = Class.new.class_eval <<-RUBY_CODE
91
- def call(#{arg_literal(args.count)})
92
- #{obj_literal(val)}
93
- end
94
- typesig call: #{obj_literal(type_list)}
95
- RUBY_CODE
96
-
97
- klass.new
98
- end
99
-
100
- def obj_literal(obj)
101
- "ObjectSpace._id2ref(#{obj.__id__})"
102
- end
103
-
104
- def arg_literal(count)
105
- ('a'..'z').to_a[0..count-1].join(',')
106
- end
107
- end