typed.rb 0.0.15 → 0.0.16
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.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/typed/language.rb +3 -2
- data/lib/typed/prelude_existential_registry.bin +0 -0
- data/lib/typed/prelude_generic_registry.bin +0 -0
- data/lib/typed/prelude_registry.bin +0 -0
- data/lib/typed/runtime.rb +16 -0
- data/lib/typed/runtime/normalization.rb +12 -9
- data/lib/typed/runtime/type_registry.rb +4 -4
- data/lib/typed/runtime/type_signature_processor.rb +6 -4
- data/lib/typed/types/polymorphism/generic_comparisons.rb +3 -1
- data/lib/typed/types/ty_generic_object.rb +7 -6
- data/lib/typed/types/ty_generic_singleton_object.rb +3 -1
- data/lib/typed/types/ty_object.rb +1 -1
- data/lib/typed/types/ty_singleton_object.rb +1 -1
- data/lib/typed/version.rb +1 -1
- data/spec/lib/examples/monoid2.rb +34 -0
- data/spec/lib/language_spec.rb +12 -0
- data/spec/lib/prelude/array_spec.rb +4 -2
- data/spec/lib/runtime/normalization_spec.rb +35 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac43557e5bdf48bfa8082e5526b798e7a2fc3aca
|
4
|
+
data.tar.gz: ed3a52ee31070c01b9dff44e8decd67bbabac035
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06c43f6cc812fa5b98a53e4d5e556fce63492746241f618ead568a04bcb018ec83a239891484168b692927699eb4fc7fa8793bf514cb3bf2bbcce790ee902e3f
|
7
|
+
data.tar.gz: 9fa398a80e4c0e57807df2ae73538176e2ffb1d9b1c2387a3c4aba0a28e43898df5c82fc0ce715f9318c3f249fecffeab4529792981676b7c109cf2f06c56868
|
data/README.md
CHANGED
@@ -94,7 +94,7 @@ The method receives a string with the type signature and returns unit. At run-ti
|
|
94
94
|
A type signature for a method is composed of the following parts:
|
95
95
|
|
96
96
|
```
|
97
|
-
Type?(#/.)method[T]* / ArgumentType? (-> ArgumentType)* -> &BlockType? -> ReturnType
|
97
|
+
Type?(#/.)method[T]* / ArgumentType? (-> ArgumentType)* (-> &BlockType)? -> ReturnType
|
98
98
|
```
|
99
99
|
|
100
100
|
For example, the type signature of the ```#ts``` method itself is ```BasicObject#ts / String -> unit```.
|
@@ -148,6 +148,7 @@ Typed.rb will try to perform automatic type inference for the following language
|
|
148
148
|
- instance variables
|
149
149
|
- local variables
|
150
150
|
- constants
|
151
|
+
- lambda functions
|
151
152
|
|
152
153
|
To know more about the type inferance mechanism, check the implementation of the unification algorithm used by the type checker in ```lib/typed/types/polymorphism/unification.rb```.
|
153
154
|
|
data/lib/typed/language.rb
CHANGED
@@ -142,10 +142,11 @@ module TypedRb
|
|
142
142
|
puts "\n"
|
143
143
|
puts error.message.red
|
144
144
|
end
|
145
|
+
warnings_accum= {}
|
145
146
|
warnings_for_file.each do |warning|
|
146
147
|
hash = warning.to_s.hash
|
147
|
-
unless
|
148
|
-
|
148
|
+
unless warnings_accum[hash]
|
149
|
+
warnings_accum[hash] = true
|
149
150
|
puts "\n"
|
150
151
|
puts warning.message.yellow
|
151
152
|
end
|
Binary file
|
Binary file
|
Binary file
|
data/lib/typed/runtime.rb
CHANGED
@@ -34,4 +34,20 @@ class Class
|
|
34
34
|
def call(*_types)
|
35
35
|
self
|
36
36
|
end
|
37
|
+
|
38
|
+
ts_ignore
|
39
|
+
def meta_ancestors
|
40
|
+
singleton_class = class << self
|
41
|
+
self
|
42
|
+
end
|
43
|
+
singleton_class.ancestors
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Module
|
48
|
+
|
49
|
+
ts_ignore
|
50
|
+
def meta_ancestors
|
51
|
+
[self] + self.class.ancestors
|
52
|
+
end
|
37
53
|
end
|
@@ -28,7 +28,11 @@ module TypedRb
|
|
28
28
|
ts '#check_super_type_annotations / -> unit'
|
29
29
|
def check_super_type_annotations
|
30
30
|
@generic_types_registry.values.each do |type|
|
31
|
-
|
31
|
+
if type.super_type
|
32
|
+
type.super_type.each do |super_type|
|
33
|
+
super_type.self_materialize
|
34
|
+
end
|
35
|
+
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -44,16 +48,15 @@ module TypedRb
|
|
44
48
|
|
45
49
|
def check_generic_super_type(type_info)
|
46
50
|
_, info = type_info
|
47
|
-
super_type =
|
48
|
-
|
51
|
+
@generic_types_registry[info[:type]].super_type = (info[:super_type] || []).map do |super_type_spec|
|
52
|
+
build_generic_super_type(info[:type], super_type_spec)
|
53
|
+
end
|
49
54
|
end
|
50
55
|
|
51
|
-
def build_generic_super_type(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
build_generic_singleton_object([info[:super_type][:type], info[:super_type]])
|
56
|
-
end
|
56
|
+
def build_generic_super_type(type, super_type)
|
57
|
+
valid_super_type?(type, super_type)
|
58
|
+
TypedRb.log(binding, :debug, "Normalising generic super type: #{super_type[:type]} for #{type}")
|
59
|
+
build_generic_singleton_object([super_type[:type], super_type])
|
57
60
|
end
|
58
61
|
|
59
62
|
def valid_super_type?(base_class, super_type_info)
|
@@ -28,12 +28,12 @@ class BasicObject
|
|
28
28
|
end
|
29
29
|
|
30
30
|
ts '.register_generic_type_information / Hash[Object][Object] -> Hash[Object][Object] -> unit'
|
31
|
-
def register_generic_type_information(generic_type_information,
|
31
|
+
def register_generic_type_information(generic_type_information, generic_super_types_information)
|
32
32
|
unless generic_type_information.is_a?(String) # TODO: String when super annotations for non-generic types
|
33
|
-
generic_type_information[:super_type] =
|
33
|
+
generic_type_information[:super_type] = generic_super_types_information
|
34
34
|
if generic_types_parser_registry[generic_type_information[:type]]
|
35
|
-
|
36
|
-
|
35
|
+
super_type = (generic_types_parser_registry[generic_type_information[:type]][:super_type] || [])
|
36
|
+
generic_types_parser_registry[generic_type_information[:type]][:super_type]= super_type.concat(generic_type_information[:super_type])
|
37
37
|
else
|
38
38
|
generic_types_parser_registry[generic_type_information[:type]] = generic_type_information
|
39
39
|
end
|
@@ -10,14 +10,16 @@ module TypedRb
|
|
10
10
|
def process(signature)
|
11
11
|
type_signature = signature.split(PARAMETRIC_TYPE_PREFIX).last
|
12
12
|
|
13
|
-
type_signature,
|
13
|
+
type_signature, super_type_signatures = parse_generic_supertype(type_signature)
|
14
14
|
|
15
15
|
generic_type = ::TypedRb::TypeSignature::Parser.parse(type_signature)
|
16
|
-
if
|
17
|
-
|
16
|
+
if super_type_signatures
|
17
|
+
generic_super_types = super_type_signatures.split(/\s*,\s*/).map do |super_type_signature|
|
18
|
+
::TypedRb::TypeSignature::Parser.parse(super_type_signature)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
|
-
BasicObject::TypeRegistry.register_generic_type_information(generic_type,
|
22
|
+
BasicObject::TypeRegistry.register_generic_type_information(generic_type, generic_super_types)
|
21
23
|
end
|
22
24
|
|
23
25
|
private
|
@@ -48,8 +48,10 @@ module TypedRb
|
|
48
48
|
else
|
49
49
|
false
|
50
50
|
end
|
51
|
-
|
51
|
+
elsif other_type.is_a?(TyObject)
|
52
52
|
check_generic_type_relation(other_type.ruby_type, relation)
|
53
|
+
else
|
54
|
+
other_type.compatible?(self, relation == :lt ? :gt : :lt)
|
53
55
|
end
|
54
56
|
rescue ArgumentError
|
55
57
|
raise TypedRb::Types::UncomparableTypes.new(self, other_type)
|
@@ -18,9 +18,9 @@ module TypedRb
|
|
18
18
|
def find_function_type(message, num_args, block)
|
19
19
|
function_klass_type, function_type = find_function_type_in_hierarchy(:instance, message, num_args, block)
|
20
20
|
if function_klass_type != ruby_type && ancestor_of_super_type?(generic_singleton_object.super_type, function_klass_type)
|
21
|
-
|
22
|
-
|
23
|
-
target_type_vars =
|
21
|
+
target_class = ancestor_of_super_type?(generic_singleton_object.super_type, function_klass_type)
|
22
|
+
TypedRb.log binding, :debug, "Found message '#{message}', generic function: #{function_type}, explicit super type #{target_class}"
|
23
|
+
target_type_vars = target_class.type_vars
|
24
24
|
materialize_super_type_found_function(message, num_args, block, target_class, target_type_vars)
|
25
25
|
elsif function_klass_type != ruby_type && BasicObject::TypeRegistry.find_generic_type(function_klass_type)
|
26
26
|
TypedRb.log binding, :debug, "Found message '#{message}', generic function: #{function_type}, implict super type #{function_klass_type}"
|
@@ -99,9 +99,10 @@ module TypedRb
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
def ancestor_of_super_type?(
|
103
|
-
|
104
|
-
|
102
|
+
def ancestor_of_super_type?(super_type_klasses, function_klass_type)
|
103
|
+
super_type_klasses.detect do |super_type_klass|
|
104
|
+
super_type_klass.ruby_type.ancestors.include?(function_klass_type)
|
105
|
+
end
|
105
106
|
end
|
106
107
|
|
107
108
|
def materialize_found_function_arg(arg)
|
@@ -35,7 +35,9 @@ module TypedRb
|
|
35
35
|
|
36
36
|
def self_materialize
|
37
37
|
TypedRb.log binding, :debug, "Materialising self for generic singleton object '#{self}'"
|
38
|
-
BasicObject::TypeRegistry.find_generic_type(ruby_type)
|
38
|
+
generic_type = BasicObject::TypeRegistry.find_generic_type(ruby_type)
|
39
|
+
fail TypeCheckError.new("Missing generic type annotation for #{ruby_type}", node) if generic_type.nil?
|
40
|
+
generic_type.materialize(type_vars)
|
39
41
|
end
|
40
42
|
|
41
43
|
# materialize will be invoked by the logic handling invocations like:
|
@@ -86,7 +86,7 @@ module TypedRb
|
|
86
86
|
if generic_type.nil?
|
87
87
|
return klass, function # generic method in non-generic class
|
88
88
|
elsif generic_type.type_vars.size == 1
|
89
|
-
generic_type.materialize([self]).find_function_type(message, num_args, block)
|
89
|
+
generic_type.materialize([self]).as_object_type.find_function_type(message, num_args, block)
|
90
90
|
else
|
91
91
|
fail "Undeclared generic type variables for #{ruby_type} super class/mix-in #{klass.class} #{klass}##{message}, please add a 'super' type annotation"
|
92
92
|
end
|
@@ -19,7 +19,7 @@ module TypedRb
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def find_function_type_in_metaclass_hierarchy(message, num_args, block)
|
22
|
-
hierarchy =
|
22
|
+
hierarchy = ruby_type.meta_ancestors
|
23
23
|
initial_value = select_matching_function_in_class(hierarchy.first, :instance, message, num_args, block)
|
24
24
|
hierarchy.drop(1).inject([hierarchy.first, initial_value]) do |(klass, acc), type|
|
25
25
|
if acc.nil? || acc.is_a?(TyDynamicFunction)
|
data/lib/typed/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'typed/runtime'
|
2
|
+
|
3
|
+
module Monoid
|
4
|
+
|
5
|
+
ts 'type Monoid::Instance[T]'
|
6
|
+
module Instance
|
7
|
+
ts '#mappend / [T] -> [T]'
|
8
|
+
abstract(:mappend)
|
9
|
+
end
|
10
|
+
|
11
|
+
ts 'type Monoid::Class[T]'
|
12
|
+
module Class
|
13
|
+
ts '#mempty / -> [T]'
|
14
|
+
abstract(:mempty)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
ts 'type Array[T] super Monoid::Instance[Array[T]]'
|
19
|
+
class Array
|
20
|
+
|
21
|
+
extend Monoid::Class
|
22
|
+
include Monoid::Instance
|
23
|
+
|
24
|
+
def mappend(b)
|
25
|
+
concat(b)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.mempty
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
Array.(Integer).new.mappend([3])
|
data/spec/lib/language_spec.rb
CHANGED
@@ -109,4 +109,16 @@ describe TypedRb::Language do
|
|
109
109
|
}.to raise_error(TypedRb::Types::Polymorphism::UnificationError)
|
110
110
|
end
|
111
111
|
end
|
112
|
+
|
113
|
+
context 'with monoid2 example, type checks correctly' do
|
114
|
+
let(:example) { 'monoid2.rb' }
|
115
|
+
|
116
|
+
it 'should be possible to type check the example correctly' do
|
117
|
+
expect {
|
118
|
+
silence_stream(STDOUT) do
|
119
|
+
language.check_file(file, true)
|
120
|
+
end
|
121
|
+
}.to_not raise_error
|
122
|
+
end
|
123
|
+
end
|
112
124
|
end
|
@@ -62,12 +62,13 @@ describe Array do
|
|
62
62
|
|
63
63
|
describe '#count' do
|
64
64
|
it 'type checks / &([T] -> Boolean) -> Integer' do
|
65
|
+
=begin
|
65
66
|
result = language.check('Array.(Integer).new(10,0).count(0)')
|
66
67
|
expect(result.ruby_type).to eq(Integer)
|
67
|
-
|
68
|
+
=end
|
68
69
|
result = language.check('Array.(Integer).new(10,0).count{ |x| x == 0 }')
|
69
70
|
expect(result.ruby_type).to eq(Integer)
|
70
|
-
|
71
|
+
=begin
|
71
72
|
expect {
|
72
73
|
code = <<__CODE
|
73
74
|
ts '#testarrs / String -> Boolean'
|
@@ -77,6 +78,7 @@ describe Array do
|
|
77
78
|
__CODE
|
78
79
|
language.check(code)
|
79
80
|
}.to raise_error(TypedRb::Types::UncomparableTypes)
|
81
|
+
=end
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
@@ -12,8 +12,41 @@ describe TypedRb::Runtime::Normalization do
|
|
12
12
|
__END
|
13
13
|
result = language.check(code)
|
14
14
|
expect(result.ruby_type).to eq(TestPair)
|
15
|
-
expect(result.super_type.ruby_type).to eq(Array)
|
16
|
-
expect(result.super_type.type_vars.first.bound.ruby_type).to eq(Object)
|
15
|
+
expect(result.super_type[0].ruby_type).to eq(Array)
|
16
|
+
expect(result.super_type[0].type_vars.first.bound.ruby_type).to eq(Object)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'normalizes generic types with multiple super types annotations' do
|
20
|
+
code = <<__END
|
21
|
+
ts 'type TestModule[T]'
|
22
|
+
module TestModule; end
|
23
|
+
|
24
|
+
ts 'type TestPair[S][T] super Array[Object], TestModule[Object]'
|
25
|
+
class TestPair < Array
|
26
|
+
include TestModule
|
27
|
+
ts '#first / -> [S]'
|
28
|
+
end
|
29
|
+
TestPair
|
30
|
+
__END
|
31
|
+
result = language.check(code)
|
32
|
+
expect(result.ruby_type).to eq(TestPair)
|
33
|
+
expect(result.super_type[0].ruby_type).to eq(Array)
|
34
|
+
expect(result.super_type[0].type_vars.first.bound.ruby_type).to eq(Object)
|
35
|
+
expect(result.super_type[1].ruby_type).to eq(TestModule)
|
36
|
+
expect(result.super_type[1].type_vars.first.bound.ruby_type).to eq(Object)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises a meaningful error if no generic type is found' do
|
40
|
+
code = <<__END
|
41
|
+
ts 'type TestPair[S][T] super Array[Object], Integer[Object]'
|
42
|
+
class TestPair < Array
|
43
|
+
ts '#first / -> [S]'
|
44
|
+
end
|
45
|
+
TestPair
|
46
|
+
__END
|
47
|
+
expect {
|
48
|
+
language.check(code)
|
49
|
+
}.to raise_error(TypedRb::TypeCheckError)
|
17
50
|
end
|
18
51
|
|
19
52
|
it 'raises an exception if the super type is not a super class of the current type' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typed.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antonio Garrote
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- spec/lib/examples/monoid/monoid_error2.rb
|
153
153
|
- spec/lib/examples/monoid/monoid_error3.rb
|
154
154
|
- spec/lib/examples/monoid/monoid_error4.rb
|
155
|
+
- spec/lib/examples/monoid2.rb
|
155
156
|
- spec/lib/language_spec.rb
|
156
157
|
- spec/lib/model/tm_abs_spec.rb
|
157
158
|
- spec/lib/model/tm_array_literal_spec.rb
|