sbyc 0.1.3 → 0.1.4
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.
- data/lib/sbyc.rb +1 -5
- data/lib/sbyc/codetree.rb +79 -77
- data/lib/sbyc/codetree/ast_node.rb +117 -115
- data/lib/sbyc/codetree/eval/ast_node_ext.rb +33 -31
- data/lib/sbyc/codetree/eval/functional_eval.rb +33 -31
- data/lib/sbyc/codetree/eval/object_eval.rb +33 -31
- data/lib/sbyc/codetree/matching/ast_node_ext.rb +13 -11
- data/lib/sbyc/codetree/matching/match_data.rb +25 -23
- data/lib/sbyc/codetree/matching/matcher.rb +73 -71
- data/lib/sbyc/codetree/name2x/delegate.rb +56 -54
- data/lib/sbyc/codetree/name2x/module_delegate.rb +23 -22
- data/lib/sbyc/codetree/proc_parser.rb +101 -99
- data/lib/sbyc/codetree/producing/producer.rb +69 -67
- data/lib/sbyc/codetree/producing/tracing_methods.rb +66 -64
- data/lib/sbyc/codetree/rewriting/class_methods.rb +15 -13
- data/lib/sbyc/codetree/rewriting/compiler.rb +27 -25
- data/lib/sbyc/codetree/rewriting/instance_methods.rb +80 -78
- data/lib/sbyc/codetree/rewriting/match.rb +51 -49
- data/lib/sbyc/shortspaces.rb +3 -0
- data/lib/sbyc/type_system.rb +4 -2
- data/lib/sbyc/type_system/contract.rb +38 -36
- data/lib/sbyc/type_system/errors.rb +8 -6
- data/lib/sbyc/type_system/ruby.rb +137 -121
- data/test/spec/spec_helper.rb +1 -1
- data/test/spec/unit/sbyc/type_system/ruby/boolean.spec +14 -0
- data/test/spec/unit/sbyc/type_system/ruby/coerce.spec +10 -1
- metadata +6 -4
@@ -1,6 +1,8 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module SByC
|
2
|
+
module TypeSystem
|
3
|
+
class Error < StandardError; end
|
4
|
+
class InvalidValueLiteralError < Error; end
|
5
|
+
class NoSuchLiteralError < Error; end
|
6
|
+
class CoercionError < Error; end
|
7
|
+
end # module TypeSystem
|
8
|
+
end # module SByC
|
@@ -1,135 +1,151 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'time'
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module SByC
|
4
|
+
module TypeSystem
|
5
|
+
#
|
6
|
+
# Implements a basic TypeSystem that mimics Ruby's type system.
|
7
|
+
#
|
8
|
+
module Ruby
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
# Marker module for ruby Boolean values
|
11
|
+
module Boolean
|
12
|
+
|
13
|
+
# Returns true if value is a boolean
|
14
|
+
def self.===(value)
|
15
|
+
(value == true) or (value == false)
|
16
|
+
end
|
11
17
|
|
12
|
-
# Ruby classes for which value.inspect will work for returning
|
13
|
-
# a valid literal
|
14
|
-
SAFE_LITERAL_CLASSES = {}
|
15
|
-
[NilClass, TrueClass, FalseClass,
|
16
|
-
Fixnum, Bignum,
|
17
|
-
Float,
|
18
|
-
String,
|
19
|
-
Symbol,
|
20
|
-
Class,
|
21
|
-
Module,
|
22
|
-
Regexp].each{|c| SAFE_LITERAL_CLASSES[c] = true}
|
23
|
-
|
24
|
-
#
|
25
|
-
# Returns value.class
|
26
|
-
#
|
27
|
-
# @see TypeSystem::Contract#type_of
|
28
|
-
#
|
29
|
-
def type_of(value)
|
30
|
-
value.class
|
31
18
|
end
|
19
|
+
|
20
|
+
# Methods
|
21
|
+
module Methods
|
22
|
+
|
23
|
+
# Ruby classes for which value.inspect will work for returning
|
24
|
+
# a valid literal
|
25
|
+
SAFE_LITERAL_CLASSES = {}
|
26
|
+
[NilClass, TrueClass, FalseClass,
|
27
|
+
Fixnum, Bignum,
|
28
|
+
Float,
|
29
|
+
String,
|
30
|
+
Symbol,
|
31
|
+
Class,
|
32
|
+
Module,
|
33
|
+
Regexp].each{|c| SAFE_LITERAL_CLASSES[c] = true}
|
34
|
+
|
35
|
+
#
|
36
|
+
# Returns value.class
|
37
|
+
#
|
38
|
+
# @see TypeSystem::Contract#type_of
|
39
|
+
#
|
40
|
+
def type_of(value)
|
41
|
+
value.class
|
42
|
+
end
|
32
43
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
44
|
+
#
|
45
|
+
# Converts _value_ to a ruby literal and returns it.
|
46
|
+
#
|
47
|
+
# Behavior of the algorithm when th value cannot be recognized depends
|
48
|
+
# on the :fallback option:
|
49
|
+
# * when set to :fail, it raises a NoSuchLiteralError
|
50
|
+
# * when set to :inspect, it returns <code>value.inspect</code>
|
51
|
+
# * when set to :marshal it uses <code>Marshal::dump(value)</code>
|
52
|
+
# * when set to :json it uses <code>JSON::generate(value)</code>
|
53
|
+
#
|
54
|
+
# @see TypeSystem::Contract#to_literal(value)
|
55
|
+
#
|
56
|
+
def to_literal(value, options = {:fallback => :fail})
|
57
|
+
if value.respond_to?(:to_ruby_literal)
|
58
|
+
value.to_ruby_literal
|
59
|
+
elsif value == (1.0/0)
|
60
|
+
return '(1.0/0)'
|
61
|
+
elsif value == -(1.0/0)
|
62
|
+
return '(-1.0/0)'
|
63
|
+
elsif SAFE_LITERAL_CLASSES.key?(type_of(value))
|
64
|
+
value.inspect
|
65
|
+
elsif value.kind_of?(Array)
|
66
|
+
"[" + value.collect{|v| to_literal(v, options)}.join(', ') + "]"
|
67
|
+
elsif value.kind_of?(Hash)
|
68
|
+
"{" + value.collect{|pair| "#{to_literal(pair[0], options)} => #{to_literal(pair[1], options)}"}.join(', ') + "}"
|
69
|
+
elsif value.kind_of?(Date)
|
70
|
+
"Date::parse(#{value.to_s.inspect})"
|
71
|
+
elsif value.kind_of?(Time)
|
72
|
+
"Time::parse(#{value.inspect.inspect})"
|
73
|
+
else
|
74
|
+
case options[:fallback]
|
75
|
+
when :inspect
|
76
|
+
value.inspect
|
77
|
+
when :marshal
|
78
|
+
"Marshal::load(#{Marshal::dump(value).inspect})"
|
79
|
+
when :json
|
80
|
+
require 'json'
|
81
|
+
JSON::generate(value)
|
82
|
+
when :fail, nil
|
83
|
+
raise NoSuchLiteralError, "Unable to convert #{value.inspect} to a ruby literal"
|
84
|
+
else
|
85
|
+
raise ArgumentError, "Invalid fallback option #{options[:fallback]}"
|
86
|
+
end
|
75
87
|
end
|
76
88
|
end
|
77
|
-
end
|
78
89
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
90
|
+
#
|
91
|
+
# Returns result of Kernel.eval(str)
|
92
|
+
#
|
93
|
+
# @see TypeSystem::Contract#parse_literal(str)
|
94
|
+
#
|
95
|
+
def parse_literal(str)
|
96
|
+
Kernel.eval(str)
|
97
|
+
rescue Exception => ex
|
98
|
+
raise TypeSystem::InvalidValueLiteralError, "Invalid ruby value literal #{str.inspect}", ex.backtrace
|
99
|
+
end
|
89
100
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
return
|
101
|
+
#
|
102
|
+
# Coerces a string to a given class.
|
103
|
+
#
|
104
|
+
# @see TypeSystem::Contract#coerce(str)
|
105
|
+
#
|
106
|
+
def coerce(str, clazz)
|
107
|
+
return str if str.kind_of?(clazz)
|
108
|
+
if clazz == NilClass
|
109
|
+
return nil if str.empty? or str == "nil"
|
110
|
+
elsif clazz == Ruby::Boolean
|
111
|
+
return true if str.to_s == "true"
|
112
|
+
return false if str.to_s == "false"
|
113
|
+
elsif clazz == TrueClass
|
114
|
+
return true if str == "true"
|
115
|
+
elsif clazz == FalseClass
|
116
|
+
return false if str == "false"
|
117
|
+
elsif [Fixnum, Bignum, Integer].include?(clazz)
|
118
|
+
if str =~ /^[-+]?[0-9]+$/
|
119
|
+
i = str.to_i
|
120
|
+
return i if i.kind_of?(clazz)
|
121
|
+
end
|
122
|
+
elsif clazz == Float
|
123
|
+
if str =~ /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/
|
124
|
+
return str.to_f
|
125
|
+
end
|
126
|
+
elsif clazz == String
|
127
|
+
return str
|
128
|
+
elsif clazz == Symbol
|
129
|
+
return str.to_sym
|
130
|
+
elsif clazz == Class or clazz == Module
|
131
|
+
parts, current = str.split("::"), Kernel
|
132
|
+
parts.each{|part| current = current.const_get(part.to_sym)}
|
133
|
+
return current if current.kind_of?(clazz)
|
134
|
+
elsif clazz == Regexp
|
135
|
+
return Regexp::compile(str)
|
136
|
+
elsif clazz.respond_to?(:parse)
|
137
|
+
return clazz.parse(str)
|
106
138
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return str
|
113
|
-
elsif clazz == Symbol
|
114
|
-
return str.to_sym
|
115
|
-
elsif clazz == Class or clazz == Module
|
116
|
-
parts, current = str.split("::"), Kernel
|
117
|
-
parts.each{|part| current = current.const_get(part.to_sym)}
|
118
|
-
return current if current.kind_of?(clazz)
|
119
|
-
elsif clazz == Regexp
|
120
|
-
return Regexp::compile(str)
|
121
|
-
elsif clazz.respond_to?(:parse)
|
122
|
-
return clazz.parse(str)
|
139
|
+
raise TypeSystem::CoercionError, "Unable to coerce #{str} to a #{clazz}"
|
140
|
+
rescue TypeSystem::CoercionError
|
141
|
+
raise
|
142
|
+
rescue StandardError => ex
|
143
|
+
raise TypeSystem::CoercionError, "Unable to coerce #{str} to a #{clazz}: #{ex.message}"
|
123
144
|
end
|
124
|
-
raise TypeSystem::CoercionError, "Unable to coerce #{str} to a #{clazz}"
|
125
|
-
rescue TypeSystem::CoercionError
|
126
|
-
raise
|
127
|
-
rescue StandardError => ex
|
128
|
-
raise TypeSystem::CoercionError, "Unable to coerce #{str} to a #{clazz}: #{ex.message}"
|
129
|
-
end
|
130
145
|
|
131
|
-
|
132
|
-
|
146
|
+
end # module Methods
|
147
|
+
extend(Methods)
|
133
148
|
|
134
|
-
|
135
|
-
end # module TypeSystem
|
149
|
+
end # class Ruby
|
150
|
+
end # module TypeSystem
|
151
|
+
end # module SByC
|
data/test/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path('../../../../../spec_helper', __FILE__)
|
2
|
+
require 'sbyc/type_system/ruby'
|
3
|
+
|
4
|
+
describe "TypeSystem::Ruby::Boolean" do
|
5
|
+
|
6
|
+
subject{ TypeSystem::Ruby::Boolean }
|
7
|
+
|
8
|
+
it { should === true }
|
9
|
+
|
10
|
+
it { should === false }
|
11
|
+
|
12
|
+
it { should_not === nil }
|
13
|
+
|
14
|
+
end
|
@@ -9,6 +9,7 @@ describe "TypeSystem::Ruby#coerce" do
|
|
9
9
|
|
10
10
|
safe_representors = {
|
11
11
|
NilClass => [ nil ],
|
12
|
+
::SByC::TypeSystem::Ruby::Boolean => [ true, false ],
|
12
13
|
TrueClass => [ true ],
|
13
14
|
FalseClass => [ false ],
|
14
15
|
Fixnum => [ -(2**(0.size * 8 - 2)), -1, 0, 1, 10, (2**(0.size * 8 - 2) - 1)],
|
@@ -23,12 +24,20 @@ describe "TypeSystem::Ruby#coerce" do
|
|
23
24
|
|
24
25
|
safe_representors.each_pair do |clazz, values|
|
25
26
|
values.each do |value|
|
26
|
-
|
27
|
+
|
28
|
+
describe "When coercing '#{value} to a #{clazz}" do
|
29
|
+
|
27
30
|
it "should return #{value}" do
|
28
31
|
str = value.kind_of?(Regexp) ? value.inspect[1..-2] : value.to_s
|
29
32
|
TypeSystem::Ruby::coerce(str, clazz).should == value
|
30
33
|
end
|
34
|
+
|
35
|
+
it "should be friendly" do
|
36
|
+
TypeSystem::Ruby::coerce(value, clazz).should == value
|
37
|
+
end
|
38
|
+
|
31
39
|
end
|
40
|
+
|
32
41
|
end
|
33
42
|
end
|
34
43
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sbyc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 4
|
10
|
+
version: 0.1.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bernard Lambeau
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-08 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/sbyc/codetree/rewriting/match.rb
|
52
52
|
- lib/sbyc/codetree/rewriting.rb
|
53
53
|
- lib/sbyc/codetree.rb
|
54
|
+
- lib/sbyc/shortspaces.rb
|
54
55
|
- lib/sbyc/type_system/contract.rb
|
55
56
|
- lib/sbyc/type_system/errors.rb
|
56
57
|
- lib/sbyc/type_system/ruby.rb
|
@@ -113,6 +114,7 @@ files:
|
|
113
114
|
- test/spec/unit/sbyc/codetree/rewriting/match/apply.spec
|
114
115
|
- test/spec/unit/sbyc/codetree/rewriting/match/coerce.spec
|
115
116
|
- test/spec/unit/sbyc/codetree/rewriting/match/matches.spec
|
117
|
+
- test/spec/unit/sbyc/type_system/ruby/boolean.spec
|
116
118
|
- test/spec/unit/sbyc/type_system/ruby/coerce.spec
|
117
119
|
- test/spec/unit/sbyc/type_system/ruby/parse_literal.spec
|
118
120
|
- test/spec/unit/sbyc/type_system/ruby/to_literal.spec
|