typesafe-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 Dario Rexin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ require 'rubygems'
7
+ require 'rake'
8
+ require 'rake/clean'
9
+ require 'rake/gempackagetask'
10
+ require 'rake/rdoctask'
11
+ require 'rake/testtask'
12
+ require 'rspec/core/rake_task'
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = 'typesafe-ruby'
16
+ s.version = '0.0.1'
17
+ s.has_rdoc = true
18
+ s.extra_rdoc_files = ['LICENSE']
19
+ s.summary = 'Adds typesafe macro to class Module, to provide type safe method declarations.'
20
+ s.description = s.summary
21
+ s.author = 'Dario Rexin'
22
+ s.email = 'dario.rexin@r3-tech.de'
23
+ # s.executables = ['your_executable_here']
24
+ s.files = %w(LICENSE Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
25
+ s.require_path = "lib"
26
+ s.bindir = "bin"
27
+ end
28
+
29
+ Rake::RDocTask.new do |rdoc|
30
+ files =['LICENSE', 'lib/**/*.rb']
31
+ rdoc.rdoc_files.add(files)
32
+ #rdoc.main = "README" # page to start on
33
+ rdoc.title = "typesafe-ruby Docs"
34
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
35
+ rdoc.options << '--line-numbers'
36
+ end
37
+
38
+ desc "Run all specs"
39
+ RSpec::Core::RakeTask.new('spec') do |t|
40
+ t.rspec_opts = ["--color"]
41
+ end
data/lib/array.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Array
2
+
3
+ class ArrayType
4
+ def initialize type
5
+ @type = type
6
+ end
7
+
8
+ def is_type_of? obj
9
+ obj.kind_of? @type
10
+ end
11
+
12
+ def to_s
13
+ "Array[#{@type}]"
14
+ end
15
+ end
16
+
17
+ alias_method :orig_kind_of?, :kind_of?
18
+
19
+ def kind_of? type
20
+ if type.kind_of?(ArrayType) or type.kind_of?(VarArgs)
21
+ self.each do |e|
22
+ return false if not type.is_type_of?(e)
23
+ end
24
+ else
25
+ orig_kind_of? type
26
+ end
27
+ end
28
+
29
+ def self.[] type
30
+ ArrayType.new(type)
31
+ end
32
+ end
data/lib/hash.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Hash
2
+ class HashType
3
+ def initialize key_type, value_type
4
+ @key_type = key_type
5
+ @value_type = value_type
6
+ end
7
+
8
+ def is_type_of? k, v
9
+ k.kind_of?(@key_type) and v.kind_of?(@value_type)
10
+ end
11
+
12
+ def to_s
13
+ "Hash[#{@key_type}, #{@value_type}]"
14
+ end
15
+ end
16
+
17
+ alias_method :orig_kind_of?, :kind_of?
18
+
19
+ def kind_of? type
20
+ if type.kind_of? HashType
21
+ self.each do |k,v|
22
+ return false if not type.is_type_of?(k, v)
23
+ end
24
+ else
25
+ orig_kind_of? type
26
+ end
27
+ end
28
+
29
+ def self.[] key_type, value_type
30
+ HashType.new key_type, value_type
31
+ end
32
+ end
data/lib/module.rb ADDED
@@ -0,0 +1,35 @@
1
+ class Module
2
+
3
+ class << self
4
+ private
5
+ attr_accessor :method_types
6
+ end
7
+
8
+ def method_added(name)
9
+ unless @typesafe.nil?
10
+ @typesafe = nil
11
+ alias_method "__typeunsafe_#{name}__", name
12
+ module_eval do
13
+ method_types = {} if method_types.nil?
14
+ method_types[name] = @types
15
+ define_method name do |*args, &block|
16
+ tmp = args
17
+ if method_types[name].last.kind_of?(VarArgs)
18
+ tmp = args.slice(0, method_types[name].size-1) + [args.slice(method_types[name].size-1,args.size)]
19
+ end
20
+ tmp.size.times do |i|
21
+ raise ArgumentError.new("for argument #{i+1} expected type #{method_types[name][i]}") if not tmp[i].kind_of?(method_types[name][i])
22
+ end
23
+ send(:"__typeunsafe_#{name}__",*args,&block)
24
+ end
25
+ alias_method "__typesafe_#{name}__", name
26
+ end
27
+ @types = nil
28
+ end
29
+ end
30
+
31
+ def typesafe(*types)
32
+ @typesafe = true
33
+ @types = types
34
+ end
35
+ end
data/lib/typesafe.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.join(File.dirname(__FILE__),'module')
2
+ require File.join(File.dirname(__FILE__),'hash')
3
+ require File.join(File.dirname(__FILE__),'array')
4
+ require File.join(File.dirname(__FILE__),'var_args')
data/lib/var_args.rb ADDED
@@ -0,0 +1,19 @@
1
+ class VarArgs
2
+
3
+ def is_type_of? obj
4
+ obj.kind_of? @type
5
+ end
6
+
7
+ def self.[] type
8
+ self.new(type)
9
+ end
10
+
11
+ def to_s
12
+ "VarArgs[#{@type}]"
13
+ end
14
+
15
+ private
16
+ def initialize type
17
+ @type = type
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ gem 'rspec'
3
+ require 'spec/autorun'
@@ -0,0 +1,55 @@
1
+ require 'typesafe'
2
+
3
+ describe "typesafe macro" do
4
+ context "typesafe(Integer)" do
5
+ it "should only allow integers as argument" do
6
+ class Foo
7
+ typesafe(Integer)
8
+ def bar a
9
+ a
10
+ end
11
+ end
12
+ lambda{Foo.new.bar(1)}.should_not raise_error(ArgumentError)
13
+ lambda{Foo.new.bar("baz")}.should raise_error(ArgumentError, "for argument 1 expected type Integer")
14
+ end
15
+ end
16
+
17
+ context "typesafe(Array[Integer])" do
18
+ it "should only allow arrays of integers as arguments" do
19
+ class Foo
20
+ typesafe(Array[Integer])
21
+ def bar a
22
+ a
23
+ end
24
+ end
25
+ lambda{Foo.new.bar([1,2,3])}.should_not raise_error(ArgumentError)
26
+ lambda{Foo.new.bar([1,2,3,"baz"])}.should raise_error(ArgumentError, "for argument 1 expected type Array[Integer]")
27
+ end
28
+ end
29
+
30
+ context "typesafe(VarArgs[Integer])" do
31
+ it "should only allow varargs of integers as arguments" do
32
+ class Foo
33
+ typesafe(VarArgs[Integer])
34
+ def bar *a
35
+ a
36
+ end
37
+ end
38
+ lambda{Foo.new.bar(1,2,3)}.should_not raise_error(ArgumentError)
39
+ lambda{Foo.new.bar(1,2,3,"baz")}.should raise_error(ArgumentError, "for argument 1 expected type VarArgs[Integer]")
40
+ end
41
+ end
42
+
43
+ context "typesafe(Hash[String, Integer])" do
44
+ it "should only allow hashes of symbol => integer as arguments" do
45
+ class Foo
46
+ typesafe(Hash[Symbol, Integer])
47
+ def bar a
48
+ a
49
+ end
50
+ end
51
+ lambda{Foo.new.bar(:foo => 3, :bar => 2)}.should_not raise_error(ArgumentError)
52
+ lambda{Foo.new.bar(:foo => 3, "baz" => 1)}.should raise_error(ArgumentError, "for argument 1 expected type Hash[Symbol, Integer]")
53
+ end
54
+ end
55
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typesafe-ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Dario Rexin
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-13 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ description: Adds typesafe macro to class Module, to provide type safe method declarations.
34
+ email: dario.rexin@r3-tech.de
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - LICENSE
41
+ files:
42
+ - LICENSE
43
+ - Rakefile
44
+ - lib/array.rb
45
+ - lib/hash.rb
46
+ - lib/module.rb
47
+ - lib/typesafe.rb
48
+ - lib/var_args.rb
49
+ - spec/spec_helper.rb
50
+ - spec/typesafe/typesafe_spec.rb
51
+ has_rdoc: true
52
+ homepage:
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Adds typesafe macro to class Module, to provide type safe method declarations.
83
+ test_files: []
84
+