Module: RDL

Extended by:
Annotate
Defined in:
lib/rdl_disable.rb,
lib/rdl/boot.rb,
lib/rdl/wrap.rb,
lib/rdl/query.rb,
lib/rdl_disable.rb,
lib/rdl/types/type_inferencer.rb

Overview

Defines RDL methods that do nothing

Defined Under Namespace

Modules: Annotate, Contract, Globals, RDLAnnotate, Type, Typecheck Classes: Config, Info, Query, Rails, Switch, TypeInferencer, Util, Wrap

Class Method Summary collapse

Methods included from Annotate

attr_accessor_type, attr_reader_type, attr_writer_type, post, pre, rdl_alias, type, type_params, var_type

Class Method Details

.at(*args) ⇒ Object

Register [+ blk ] to be executed when ‘rdl_do_typecheck [ sym +]` is called. The blk will be called with sym as its argument. The order in which multiple blks for the same sym will be executed is unspecified



536
537
538
539
# File 'lib/rdl/wrap.rb', line 536

def self.at(sym, &blk)
  RDL::Globals.to_do_at[sym] = [] unless RDL::Globals.to_do_at[sym]
  RDL::Globals.to_do_at[sym] << blk
end

.config(*args) {|RDL::Config.instance| ... } ⇒ Object

Yields:



10
11
12
# File 'lib/rdl/boot.rb', line 10

def RDL.config
  yield(RDL::Config.instance)
end

.deinstantaite!(*args) ⇒ Object



41
# File 'lib/rdl_disable.rb', line 41

def self.deinstantaite!(*args); self; end

.deinstantiate!(obj) ⇒ Object

Raises:

  • (RuntimeError)


609
610
611
612
613
614
615
616
# File 'lib/rdl/wrap.rb', line 609

def self.deinstantiate!(obj)
  klass = obj.class.to_s
  klass = "Object" if (klass.is_a? Object) && (klass.to_s == "main")
  raise RuntimeError, "Class #{self.to_s} is not parameterized" unless RDL::Globals.type_params[klass]
  raise RuntimeError, "Instance is not instantiated" unless obj.instance_variable_get(:@__rdl_type).instance_of?(RDL::Type::GenericType)
  obj.instance_variable_set(:@__rdl_type, nil)
  obj
end

.do_typecheck(*args) ⇒ Object

Invokes all callbacks from rdl_at(sym), in unspecified order. Afterwards, type checks all methods that had annotation ‘typecheck: sym’ at type call, in unspecified order.



543
544
545
546
547
548
549
550
551
552
553
554
# File 'lib/rdl/wrap.rb', line 543

def self.do_typecheck(sym)
  if RDL::Globals.to_do_at[sym]
    RDL::Globals.to_do_at[sym].each { |blk| blk.call(sym) }
  end
  RDL::Globals.to_do_at[sym] = Array.new
  return unless RDL::Globals.to_typecheck[sym]
  RDL::Globals.to_typecheck[sym].each { |klass, meth|
    RDL::Typecheck.typecheck(klass, meth)
  }
  RDL::Globals.to_typecheck[sym] = Set.new
  nil
end

.instantaite!(*args) ⇒ Object



40
# File 'lib/rdl_disable.rb', line 40

def self.instantaite!(*args); self; end

.instantiate!(obj, *typs, check: false) ⇒ Object

typs

is an array of types, classes, symbols, or strings to instantiate

the type parameters. If a class, symbol, or string is given, it is converted to a NominalType.

Raises:

  • (RuntimeError)


579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
# File 'lib/rdl/wrap.rb', line 579

def self.instantiate!(obj, *typs, check: false)
  klass = obj.class.to_s
  klass = "Object" if (klass.is_a? Object) && (klass.to_s == "main")
  formals, _, all = RDL::Globals.type_params[klass]
  raise RuntimeError, "Receiver is of class #{klass}, which is not parameterized" unless formals
  raise RuntimeError, "Expecting #{formals.size} type parameters, got #{typs.size}" unless formals.size == typs.size
  raise RuntimeError, "Instance already has type instantiation" if obj.instance_variable_get(:@__rdl_type)
  new_typs = typs.map { |t| if t.is_a? RDL::Type::Type then t else RDL::Globals.parser.scan_str "#T #{t}" end }
  t = RDL::Type::GenericType.new(RDL::Type::NominalType.new(klass), *new_typs)
  if check
    if all.instance_of? Symbol
      obj.send(all) { |*objs|
        new_typs.zip(objs).each { |nt, o|
          if nt.instance_of? RDL::Type::GenericType # require o to be instantiated
            t_o = RDL::Util.rdl_type(o)
            raise RDL::Type::TypeError, "Expecting element of type #{nt.to_s}, but got uninstantiated object #{o.inspect}" unless t_o
            raise RDL::Type::TypeError, "Expecting type #{nt.to_s}, got type #{t_o.to_s}" unless t_o <= nt
          else
            raise RDL::Type::TypeError, "Expecting type #{nt.to_s}, got #{o.inspect}" unless nt.member? o
          end
        }
      }
    else
      raise RDL::Type::TypeError, "Not an instance of #{t}" unless instance_exec(*new_typs, &all)
    end
  end
  obj.instance_variable_set(:@__rdl_type, t)
  obj
end

.note_type(*args) ⇒ Object

Does nothing at run time



557
558
559
# File 'lib/rdl/wrap.rb', line 557

def self.note_type(x)
  return x
end

.nowrap(*args) ⇒ Object



528
529
530
531
# File 'lib/rdl/wrap.rb', line 528

def self.nowrap(klass=self)
  RDL.config { |config| config.add_nowrap(klass) }
  nil
end

.query(*args) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rdl/query.rb', line 72

def self.query(q)
  RDL::Globals.contract_switch.off {
    if q =~ /^[A-Z]\w*(#|\.)([a-z_]\w*(!|\?|=)?|!|~|\+|\*\*|-|\*|\/|%|<<|>>|&|\||\^|<|<=|=>|>|==|===|!=|=~|!~|<=>|\[\]|\[\]=)$/
      typs = RDL::Query.method_query(q)
      if typs.nil? then
        puts "No types for #{q}"
      else
        typs.each { |t|
          puts "#{q}: #{t}"
        }
      end
    elsif q =~ /^[A-Z]\w*$/
      typs = RDL::Query.class_query(q)
      if typs.nil? then
        puts "No method types for #{q}"
      else
        typs.each { |m, t| puts "#{m}: #{t}"}
      end
    elsif q =~ /\(.*\)/
      typs = RDL::Query.method_type_query(q)
      if typs.empty? then
        puts "No matching methods"
      else
        typs.each { |m, t| puts "#{m}: #{t}" }
      end
    else
      raise "Don't know how to handle query"
    end
    nil
  }
end

.remove_type(*args) ⇒ Object

Raises:

  • (RuntimeError)


561
562
563
564
565
# File 'lib/rdl/wrap.rb', line 561

def self.remove_type(klass, meth)
  raise RuntimeError, "No existing type for #{RDL::Util.pp_klass_method(klass, meth)}" unless RDL::Globals.info.has? klass, meth, :type
  RDL::Globals.info.remove klass, meth, :type
  nil
end

.type_alias(*args) ⇒ Object

Add a new type alias.

name

must be a string beginning with %.

typ

can be either a string, in which case it will be parsed

into a type, or a Type.

Raises:

  • (RuntimeError)


514
515
516
517
518
519
520
521
522
523
524
525
526
# File 'lib/rdl/wrap.rb', line 514

def self.type_alias(name, typ)
  raise RuntimeError, "Attempt to redefine type #{name}" if RDL::Globals.special_types[name]
  case typ
  when String
    t = RDL::Globals.parser.scan_str "#T #{typ}"
    RDL::Globals.special_types[name] = t
  when RDL::Type::Type
    RDL::Globals.special_types[name] = typ
  else
    raise RuntimeError, "Unexpected typ argument #{typ.inspect}"
  end
  nil
end

.type_cast(*args) ⇒ Object

Returns a new object that wraps self in a type cast. If force is true this cast is unchecked, so use with caution

Raises:

  • (RuntimeError)


568
569
570
571
572
573
574
# File 'lib/rdl/wrap.rb', line 568

def self.type_cast(obj, typ, force: false)
  new_typ = if typ.is_a? RDL::Type::Type then typ else RDL::Globals.parser.scan_str "#T #{typ}" end
  raise RuntimeError, "type cast error: self not a member of #{new_typ}" unless force || typ.member?(obj)
  new_obj = SimpleDelegator.new(obj)
  new_obj.instance_variable_set('@__rdl_type', new_typ)
  new_obj
end