rdl 2.0.0.rc4 → 2.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,9 +25,9 @@ module RDL::Type
25
25
  end
26
26
 
27
27
  # default behavior, override in appropriate subclasses
28
- def canonical
29
- return self
30
- end
28
+ def canonical; return self; end
29
+ def optional?; return false; end
30
+ def vararg?; return false; end
31
31
 
32
32
  # [+ other +] is a Type
33
33
  # [+ inst +] is a Hash<Symbol, Type> representing an instantiation
@@ -143,6 +143,7 @@ module RDL::Type
143
143
  return false # one has a block and the other doesn't
144
144
  end
145
145
  end
146
+ return true if left.is_a?(MethodType) && right.is_a?(NominalType) && right.name == 'Proc'
146
147
 
147
148
  # structural
148
149
  if left.is_a?(StructuralType) && right.is_a?(StructuralType)
@@ -175,18 +176,26 @@ module RDL::Type
175
176
  if left.is_a?(FiniteHashType) && right.is_a?(FiniteHashType)
176
177
  # Like Tuples, FiniteHashes are immutable, so covariant subtyping allowed
177
178
  # But note, no width subtyping allowed, to match #member?
178
- rest = right.elts.clone # shallow copy
179
+ right_elts = right.elts.clone # shallow copy
179
180
  left.elts.each_pair { |k, tl|
180
- return false unless rest.has_key? k
181
- tr = rest[k]
182
- tl = tl.type if tl.is_a? OptionalType
183
- tr = tr.type if tr.is_a? OptionalType
184
- return false unless leq(tl, tr, inst, ileft)
185
- rest.delete k
181
+ if right_elts.has_key? k
182
+ tr = right_elts[k]
183
+ return false if tl.is_a?(OptionalType) && !tr.is_a?(OptionalType) # optional left, required right not allowed, since left may not have key
184
+ tl = tl.type if tl.is_a? OptionalType
185
+ tr = tr.type if tr.is_a? OptionalType
186
+ return false unless leq(tl, tr, inst, ileft)
187
+ right_elts.delete k
188
+ else
189
+ return false unless right.rest && leq(tl, right.rest, inst, ileft)
190
+ end
186
191
  }
187
- rest.each_pair { |k, t|
192
+ right_elts.each_pair { |k, t|
188
193
  return false unless t.is_a? OptionalType
189
194
  }
195
+ unless left.rest.nil?
196
+ # If left has optional stuff, right needs to accept it
197
+ return false unless !(right.rest.nil?) && leq(left.rest, right.rest, inst, ileft)
198
+ end
190
199
  left.ubounds << right
191
200
  right.lbounds << left
192
201
  return true
@@ -15,6 +15,9 @@ module RDL::Type
15
15
  ts.concat t.types
16
16
  else
17
17
  raise RuntimeError, "Attempt to create union type with non-type" unless t.is_a? Type
18
+ raise RuntimeError, "Attempt to create union with optional type" if t.is_a? OptionalType
19
+ raise RuntimeError, "Attempt to create union with vararg type" if t.is_a? VarargType
20
+ raise RuntimeError, "Attempt to create union with annotated type" if t.is_a? AnnotatedArgType
18
21
  ts << t
19
22
  end
20
23
  }
@@ -17,8 +17,9 @@ module RDL::Type
17
17
  end
18
18
 
19
19
  def initialize(type)
20
- raise "Can't have vararg optional type" if type.class == OptionalType
21
- raise "Can't have vararg vararg type" if type.class == VarargType
20
+ raise "Can't have vararg optional type" if type.is_a? OptionalType
21
+ raise "Can't have vararg vararg type" if type.is_a? VarargType
22
+ raise "Can't have optional annotated type" if type.is_a? AnnotatedArgType
22
23
  @type = type
23
24
  super()
24
25
  end
@@ -55,5 +56,9 @@ module RDL::Type
55
56
  def hash # :nodoc:
56
57
  return 59 + @type.hash
57
58
  end
59
+
60
+ def vararg?
61
+ return true
62
+ end
58
63
  end
59
64
  end
@@ -535,13 +535,26 @@ class Object
535
535
  nil
536
536
  end
537
537
 
538
- # Type check all methods that had annotation `typecheck: sym' at type call
538
+ # Register [+ blk +] to be executed when `rdl_do_typecheck [+ sym +]` is called.
539
+ # The blk will be called with sym as its argument. The order
540
+ # in which multiple blks for the same sym will be executed is unspecified
541
+ def rdl_at(sym, &blk)
542
+ $__rdl_at[sym] = [] unless $__rdl_at[sym]
543
+ $__rdl_at[sym] << blk
544
+ end
545
+
546
+ # Invokes all callbacks from rdl_at(sym), in unspecified order.
547
+ # Afterwards, type checks all methods that had annotation `typecheck: sym' at type call, in unspecified order.
539
548
  def rdl_do_typecheck(sym)
549
+ if $__rdl_at[sym]
550
+ $__rdl_at[sym].each { |blk| blk.call(sym) }
551
+ end
552
+ $__rdl_at[sym] = Array.new
540
553
  return unless $__rdl_to_typecheck[sym]
541
554
  $__rdl_to_typecheck[sym].each { |klass, meth|
542
555
  RDL::Typecheck.typecheck(klass, meth)
543
556
  }
544
- $__rdl_to_typecheck[sym] = Array.new
557
+ $__rdl_to_typecheck[sym] = Set.new
545
558
  nil
546
559
  end
547
560
 
@@ -0,0 +1,16 @@
1
+ class Proc
2
+ rdl_nowrap
3
+
4
+ type :arity, '() -> %integer'
5
+ type :binding, '() -> Binding'
6
+ type :curry, '(?%integer arity) -> Proc'
7
+ type :hash, '() -> %integer'
8
+ rdl_alias :inspect, :to_s
9
+ type :lambda, '() -> %bool'
10
+ type :parameters, '() -> Array<[Symbol, Symbol]>'
11
+ type :source_location, '() -> [String, %integer]'
12
+ type :to_proc, '() -> self'
13
+ type :to_s, '() -> String'
14
+
15
+
16
+ end
@@ -1,6 +1,8 @@
1
1
  # :integer, :bigint, :float, :decimal, :numeric, :datetime, :time, :date, :binary, :boolean.
2
2
  # null allowed
3
3
 
4
+ type_alias '%symstr', 'Symbol or String'
5
+
4
6
  module RDL
5
7
  class Rails
6
8
 
@@ -28,5 +30,23 @@ module RDL
28
30
  raise RuntimeError, "Unrecoganized column type #{rails_type}"
29
31
  end
30
32
  end
33
+
34
+ # [+ model +] is an ActiveRecord::Base subclass that has been loaded.
35
+ # Gets the columns_hash of the model and returns a String that can
36
+ # serve as the paramter list to a method that accepts any number
37
+ # of the model's attributes keyed by the attribute names.
38
+ def self.attribute_types(model)
39
+ args = []
40
+
41
+ model.columns_hash.each { |name, col|
42
+ t = column_to_rdl(col.type)
43
+ if col.null
44
+ args << "#{name}: ?#{t}"
45
+ else
46
+ args << "#{name}: ?!#{t}"
47
+ end
48
+ }
49
+ return args.join ','
50
+ end
31
51
  end
32
52
  end
@@ -0,0 +1,15 @@
1
+ class ActiveModel::Errors
2
+ type :clear, '() -> %any'
3
+ type :delete, '(%symstr) -> %any'
4
+ type :[], '(%symstr) -> Array<String>'
5
+ type :each, '() { (%symstr, String) -> %any } -> %any'
6
+ type :size, '() -> %integer'
7
+ rdl_alias :count, :size
8
+ type :values, '() -> Array<String>'
9
+ type :keys, '() -> Array<Symbol>'
10
+ type :empty?, '() -> %bool'
11
+ rdl_alias :blank?, :empty?
12
+ type :hash, '(?%bool full_messages) -> Hash<Symbol, String>'
13
+ type :add, '(%symstr, %symstr, Hash<Symbol, %any>) -> %any'
14
+ type :add, '(%symstr, { () -> String }, Hash<Symbol, %any>) -> %any' # TODO: combine with prev with union once supported
15
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveModel
2
+ module Validations
3
+ type :errors, '() -> ActiveModel::Errors'
4
+ end
5
+ end
@@ -0,0 +1,190 @@
1
+ class ActiveRecord::Associations::CollectionProxy
2
+ type_params [:t], :all?
3
+
4
+ type :<<, '(*(t or Array<t>)) -> self'
5
+ type :==, '(%any) -> %bool'
6
+ type :any?, '() ?{ (t) -> %bool } -> %bool'
7
+ rdl_alias :append, :<<
8
+ type :build, '(Hash<Symbol, %any> or Array<Hash<Symbol, %any>>) -> self'
9
+ type :clear, '() -> self'
10
+ type :concat, '(*t) -> self'
11
+ type :count, '() -> %integer'
12
+ type :create, '(Hash<Symbol, %any> or Array<Hash<Symbol, %any>>) -> self'
13
+ type :create!, '(Hash<Symbol, %any> or Array<Hash<Symbol, %any>>) -> self'
14
+ type :delete, '(*t) -> Array<t>'
15
+ type :delete_all, '(?Symbol dependent) -> Array<t>'
16
+ type :destroy, '(*t) -> Array<t>'
17
+ type :destroy_all, '() -> %any'
18
+ type :distinct, '() -> self'
19
+ type :empty?, '() -> %bool'
20
+ type :find, '(%integer) -> t'
21
+ type :find, '(%integer, %integer, *%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
22
+ type :include?, '(t) -> %bool'
23
+ type :length, '() -> %integer'
24
+ type :load_target, '() -> %any'
25
+ type :loaded?, '() -> %bool'
26
+ type :many?, '() ?{ (t) -> %bool } -> %bool'
27
+ rdl_alias :new, :build
28
+ rdl_alias :push, :<<
29
+ type :reload, '() -> self'
30
+ type :replace, '(Array<t>) -> %any'
31
+ type :reset, '() -> self'
32
+ type :scope, '() -> ActiveRecord::Relation' # TODO fix
33
+ type :select, '(*Symbol) -> t'
34
+ type :select, '() { (t) -> %bool } -> ActiveRecord::Associations::CollectionProxy<t>'
35
+ type :size, '() -> %integer'
36
+ rdl_alias :spawn, :scope
37
+ type :take, '() -> t or nil'
38
+ type :take, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
39
+ type :to_ary, '() -> Array<t>'
40
+ rdl_alias :to_a, :to_ary
41
+ rdl_alias :unique, :distinct
42
+
43
+ type :first, '() -> t or nil'
44
+ type :first, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
45
+ type :second, '() -> t or nil'
46
+ type :second, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
47
+ type :third, '() -> t or nil'
48
+ type :third, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
49
+ type :fourth, '() -> t or nil'
50
+ type :fourth, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
51
+ type :fifth, '() -> t or nil'
52
+ type :fifth, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
53
+ type :forty_two, '() -> t or nil'
54
+ type :forty_two, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
55
+ type :third_to_last, '() -> t or nil'
56
+ type :third_to_last, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
57
+ type :second_to_last, '() -> t or nil'
58
+ type :second_to_last, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
59
+ type :last, '() -> t or nil'
60
+ type :last, '(%integer) -> ActiveRecord::Associations::CollectionProxy<t>'
61
+ end
62
+
63
+ module ActiveRecord::Associations::ClassMethods
64
+
65
+ # TODO: Check presence of methods required by, e.g., foreign_key, primary_key, etc.
66
+ # TODO: Check counter_cache, add to model attr_readonly_type
67
+
68
+
69
+ type :belongs_to, '(%symstr name, ?{ (?ActiveRecord::Base) -> %any } scope, class_name: ?%symstr, foreign_key: ?%symstr,' +
70
+ 'primary_key: ?%symstr, dependent: ?(:delete or :destroy), counter_cache: ?(%bool or %symstr),' +
71
+ 'polymorphic: ?%bool, validate: ?%bool, autosave: ?%bool, touch: ?(%bool or %symstr),' +
72
+ 'inverse_of: ?%symstr, optional: ?%bool, required: ?%bool, anonymous_class: ?Class) -> %any'
73
+
74
+ pre :belongs_to do |name, scope=nil, class_name: nil, foreign_key: nil, primary_key: nil,
75
+ dependent: nil, counter_cache: nil, polymorphic: nil,
76
+ validate: nil, autosave: nil, touch: nil, inverse_of: nil,
77
+ optional: nil, required: nil, anonymous_class: nil|
78
+ if polymorphic
79
+ assoc_type = '%any' # type is data-driven, can't determine statically
80
+ elsif class_name
81
+ assoc_type = class_name.to_s.classify
82
+ elsif anonymous_class
83
+ assoc_type = anonymous_class.to_s
84
+ else
85
+ assoc_type = name.to_s.classify # camelize?
86
+ end
87
+ type name, "(?%bool force_reload) -> #{assoc_type}"
88
+ type "#{name}=", "(#{assoc_type}) -> #{assoc_type}"
89
+ unless polymorphic
90
+ rdl_at(:model) { |sym|
91
+ assoc_attribute_types = RDL::Rails.attribute_types(assoc_type.constantize)
92
+ type "build_#{name}", "(#{assoc_attribute_types}) -> #{assoc_type}"
93
+ type "create_#{name}", "(#{assoc_attribute_types}) -> #{assoc_type}"
94
+ type "create_#{name}!", "(#{assoc_attribute_types}) -> #{assoc_type}"
95
+ }
96
+ end
97
+ true
98
+ end
99
+
100
+ type :has_one, '(%symstr name, ?{ (?ActiveRecord::Base) -> %any } scope, class_name: ?%symstr,'+
101
+ 'dependent: ?(:destroy or :delete or :nullify or :restrict_with_exception or :restrict_with_error),' +
102
+ 'foreign_key: ?%symstr, foreign_type: ?%symstr, primary_key: ?%symstr, as: ?%symstr,' +
103
+ 'through: ?%symstr, source: ?%symstr, source_type: ?%symstr, validate: ?%bool, autosave: ?%bool,' +
104
+ 'inverse_of: ?%symstr, required: ?%bool, anonymous_class: ?Class) -> %any'
105
+
106
+ pre :has_one do |name, scope=nil, class_name: nil, dependent: nil, foreign_key: nil,
107
+ foreign_type: nil, primary_key: nil, as: nil, through: nil, source: nil,
108
+ source_type: nil, vadliate: nil, autosave: nil, inverse_of: nil,
109
+ required: nil|
110
+ if as
111
+ assoc_type = '%any' # type is data-driven, can't determine statically
112
+ elsif class_name
113
+ assoc_type = class_name.to_s.classify
114
+ elsif anonymous_class # not sure this has anonymou_class
115
+ assoc_type = anonymous_class.to_s.classify
116
+ else
117
+ assoc_type = name.to_s.classify # camelize?
118
+ end
119
+ type name, "(?%bool force_reload) -> #{assoc_type}"
120
+ type "#{name}=", "(#{assoc_type}) -> #{assoc_type}"
121
+ unless as
122
+ rdl_at(:model) { |sym|
123
+ assoc_attribute_types = RDL::Rails.attribute_types(assoc_type.constantize)
124
+ type "build_#{name}", "(#{assoc_attribute_types}) -> #{assoc_type}"
125
+ type "create_#{name}", "(#{assoc_attribute_types}) -> #{assoc_type}"
126
+ type "create_#{name}!", "(#{assoc_attribute_types}) -> #{assoc_type}"
127
+ }
128
+ end
129
+ end
130
+
131
+ type :has_many, '(%symstr name, ?{ (?ActiveRecord::Base) -> %any } scope, class_name: ?%symstr,' +
132
+ 'foreign_key: ?%symstr, foreign_type: ?%symstr, primary_key: ?%symstr,' +
133
+ 'dependent: ?(:destroy or :delete_all or :nullify or :restrict_with_exception or :restrict_with_error),' +
134
+ 'counter_cache: ?(%bool or %symstr), as: ?%symstr, through: ?%symstr, source: ?%symstr,' +
135
+ 'source_type: ?%symstr, validate: ?%bool, inverse_of: ?%symstr, extend: ?(Module or Array<Module>))' +
136
+ '?{ () -> %any } -> %any'
137
+
138
+ pre :has_many do |name, scope=nil, class_name: nil, foreign_key: nil, foreign_type: nil, primary_key: nil,
139
+ dependent: nil, counter_cache: nil, as: nil, through: nil, source: nil, source_type: nil,
140
+ validate: nil, inverse_of: nil, extend: nil|
141
+ if class_name
142
+ collect_type = class_name.to_s.classify
143
+ else
144
+ collect_type = name.to_s.singularize.classify
145
+ end
146
+ type name, "() -> ActiveRecord::Associations::CollectionProxy<#{collect_type}>"
147
+ type "#{name}=", "(Array<t>) -> ActiveRecord::Associations::CollectionProxy<#{collect_type}>" # TODO not sure of type
148
+ id_type = RDL::Rails.column_to_rdl(collect_type.constantize.columns_hash['id'].type) # TODO assumes id field is "id"
149
+ type "#{name.to_s.singularize}_ids", "() -> Array<#{id_type}>"
150
+ type "#{name.to_s.singularize}_ids=", "() -> Array<#{id_type}>"
151
+
152
+ true
153
+ end
154
+
155
+ type :has_and_belongs_to_many, '(%symstr name, ?{ (?ActiveRecord::Base) -> %any } scope, class_name: ?%symstr,' +
156
+ 'join_table: ?%symstr, foreign_key: ?%symstr, association_foreign_key: ?%symstr,' +
157
+ 'validate: ?%bool, autosave: ?%bool) ?{ () -> %any } -> %any'
158
+
159
+ pre :has_and_belongs_to_many do |name, scope=nil, class_name: nil, join_table: nil,
160
+ foreign_key: nil, association_foreign_key: nil,
161
+ validate: nil, autosave: nil|
162
+ if class_name
163
+ collect_type = class_name.to_s.classify
164
+ else
165
+ collect_type = name.to_s.singularize.classify
166
+ end
167
+ type name, "() -> ActiveRecord::Associations::CollectionProxy<#{collect_type}>"
168
+ type "#{name}=", "(Array<t>) -> ActiveRecord::Associations::CollectionProxy<#{collect_type}>" # TODO not sure of type
169
+ id_type = RDL::Rails.column_to_rdl(collect_type.constantize.columns_hash['id'].type) # TODO assumes id field is "id"
170
+ type "#{name.to_s.singularize}_ids", "() -> Array<#{id_type}>"
171
+ type "#{name.to_s.singularize}_ids=", "() -> Array<#{id_type}>"
172
+
173
+ # Remaining methods are from CollectionProxy
174
+ # TODO give these precise types for this particular model
175
+ # collection<<(object, ...)
176
+ # collection.delete(object, ...)
177
+ # collection.destroy(object, ...)
178
+ # collection.clear
179
+ # collection.empty?
180
+ # collection.size
181
+ # collection.find(...)
182
+ # collection.where(...)
183
+ # collection.exists?(...)
184
+ # collection.build(attributes = {})
185
+ # collection.create(attributes = {})
186
+ # collection.create!(attributes = {})
187
+ true
188
+ end
189
+
190
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveRecord::Core
2
+ type :==, '(%any) -> %bool'
3
+ end
@@ -2,8 +2,6 @@ module ActiveRecord
2
2
  module ModelSchema
3
3
  module ClassMethods
4
4
  post(:load_schema!) { |ret| # load_schema! doesn't return anything interesting
5
- find_by_args = []
6
-
7
5
  columns_hash.each { |name, col|
8
6
  t = RDL::Rails.column_to_rdl(col.type)
9
7
  if col.null
@@ -13,7 +11,6 @@ module ActiveRecord
13
11
  type "write_attribute", "(:#{name}, #{t}) -> %bool"
14
12
  type "update_attribute", "(:#{name}, #{t}) -> %bool"
15
13
  type "update_column", "(:#{name}, #{t}) -> %bool"
16
- find_by_args << "#{name}: ?#{t}"
17
14
  else
18
15
  # not null; can't truly check in type system but hint via the name
19
16
  type name, "() -> !#{t}" # getter
@@ -21,15 +18,15 @@ module ActiveRecord
21
18
  type "write_attribute", "(:#{name}, !#{t}) -> %bool"
22
19
  type "update_attribute", "(:#{name}, #{t}) -> %bool"
23
20
  type "update_column", "(:#{name}, #{t}) -> %bool"
24
- find_by_args << "#{name}: ?!#{t}"
25
21
  end
26
22
  }
27
- hash_args = find_by_args.join(',')
28
- type 'self.find_by', '(' + hash_args + ") -> #{self} or nil"
29
- type 'self.find_by!', '(' + hash_args + ") -> #{self}"
30
- type 'update', '(' + hash_args + ') -> %bool'
31
- type 'update_columns', '(' + hash_args + ') -> %bool'
32
- type 'attributes=', '(' + hash_args + ') -> %bool'
23
+
24
+ attribute_types = RDL::Rails.attribute_types(self)
25
+ type 'self.find_by', '(' + attribute_types + ") -> #{self} or nil"
26
+ type 'self.find_by!', '(' + attribute_types + ") -> #{self}"
27
+ type 'update', '(' + attribute_types + ') -> %bool'
28
+ type 'update_columns', '(' + attribute_types + ') -> %bool'
29
+ type 'attributes=', '(' + attribute_types + ') -> %bool'
33
30
 
34
31
  # If called with String arguments, can't check types as precisely
35
32
  type 'write_attribute', '(String, %any) -> %bool'
@@ -4,8 +4,8 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '2.0.0.rc4'
8
- s.date = '2016-08-13'
7
+ s.version = '2.0.0.rc5'
8
+ s.date = '2016-08-24'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
11
  RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
@@ -168,6 +168,29 @@ class TestLe < Minitest::Test
168
168
  assert (tfs2_4 <= thfs_4) # allowed, both tfs2_4 and tfs_4 promoted to hash
169
169
  tfs3_4 = tt "{x: Fixnum, y: String}"
170
170
  assert (not(tfs_4 <= tfs3_4)) # not allowed, tfs_4 has been promoted
171
+
172
+ tfss_5 = tt "{x: Fixnum, y: String, **Symbol}"
173
+ tfns_5 = tt "{x: Fixnum, **Symbol}"
174
+ tfsn_5 = tt "{x: Fixnum, y: String}"
175
+ tftn_5 = tt "{x: Fixnum, z: Symbol}"
176
+ tooo_5 = tt "{x: Object, y: Object, **Object}"
177
+ tono_5 = tt "{x: Object, **Object}"
178
+ assert (tfss_5 <= tooo_5)
179
+ assert (tfns_5 <= tono_5)
180
+ assert (not (tfss_5 <= tfns_5))
181
+ assert (not (tfss_5 <= tfsn_5))
182
+ assert (not (tfss_5 <= tftn_5))
183
+ assert (not (tfns_5 <= tfss_5))
184
+ assert (not (tfns_5 <= tfsn_5))
185
+ assert (not (tfns_5 <= tftn_5))
186
+ assert (tfsn_5 <= tfss_5)
187
+ assert (not (tfsn_5 <= tfns_5))
188
+ assert (not (tfsn_5 <= tftn_5))
189
+ assert (not (tftn_5 <= tfss_5))
190
+ assert (tftn_5 <= tfns_5)
191
+ assert (not (tftn_5 <= tfsn_5))
192
+
193
+ assert (not (tt("{x: ?Fixnum}") <= tt("{x: Fixnum}")))
171
194
  end
172
195
 
173
196
  def test_method
@@ -197,6 +220,7 @@ class TestLe < Minitest::Test
197
220
  assert (not (tbos <= tbso))
198
221
  assert (tbso <= tbso)
199
222
  assert (tbso <= tbos)
223
+ assert (tss <= $__rdl_proc_type)
200
224
  end
201
225
 
202
226
  def test_structural