Class: Pione::Lang::Type

Inherits:
StructX
  • Object
show all
Defined in:
lib/pione/lang/type.rb

Overview

Type is a class for type expression of PIONE model objects.

Class Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Type

Create a type for PIONE model object.



16
17
18
19
# File 'lib/pione/lang/type.rb', line 16

def initialize(*args)
  super(*args)
  Type.table[name] = {parent: parent_type}
end

Class Attribute Details

.tableObject (readonly)

Returns the value of attribute table.



8
9
10
# File 'lib/pione/lang/type.rb', line 8

def table
  @table
end

Instance Method Details

#check(env, data) ⇒ void

This method returns an undefined value.

Return true if the data has the type.



77
78
79
80
81
# File 'lib/pione/lang/type.rb', line 77

def check(env, data)
  unless match(env, data)
    raise LangTypeError.new(data, self, env)
  end
end

#define_deferred_pione_method(name, inputs, output, &b) ⇒ Object

Define PIONE methods. Arguments are non-evaluated.



70
71
72
# File 'lib/pione/lang/type.rb', line 70

def define_deferred_pione_method(name, inputs, output, &b)
  (pione_method[name] ||= []) << PioneMethod.new(:deferred, name, inputs, output, b)
end

#define_pione_method(name, inputs, output, &b) ⇒ Object

Define PIONE methods. Arguments are evaluated immediately.



65
66
67
# File 'lib/pione/lang/type.rb', line 65

def define_pione_method(name, inputs, output, &b)
  (pione_method[name] ||= []) << PioneMethod.new(:immediate, name, inputs, output, b)
end

#find_method(env, name, rec, args) ⇒ Object

Find named method.



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
# File 'lib/pione/lang/type.rb', line 37

def find_method(env, name, rec, args)
  # find a suitable method
  if pione_method.has_key?(name)
    group = pione_method[name].group_by{|m| m.method_type}

    # exist deferred methods
    if group.has_key?(:deferred)
      if m = group[:deferred].find {|m| m.validate_inputs(env, rec, args)}
        return m
      end
    end

    # try immediate methods
    _args = args.map {|arg| arg.pione_type(env)} # FIXME : should be replaced by type inference
    if group.has_key?(:immediate)
      return group[:immediate].find {|m| m.validate_inputs(env, rec, _args)}
    else
      return nil
    end
  end

  # find from parent type
  if parent_type
    return parent_type.find_method(env, name, rec, args)
  end
end

#fold1(val, seq1, &b) ⇒ Object



126
127
128
129
130
# File 'lib/pione/lang/type.rb', line 126

def fold1(val, seq1, &b)
  seq1.pieces.inject(val) do |obj, elt1|
    b.call(obj, elt1)
  end
end

#inspectObject



169
170
171
# File 'lib/pione/lang/type.rb', line 169

def inspect
  "#<Type %s>" % name
end

#map1(seq, &b) ⇒ Object



87
88
89
# File 'lib/pione/lang/type.rb', line 87

def map1(seq, &b)
  sequence_class.of(seq.pieces.map{|elt| b.call(elt)}, seq.attribute)
end

#map2(seq1, seq2, &b) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/pione/lang/type.rb', line 91

def map2(seq1, seq2, &b)
  seq1.pieces.map do |elt1|
    seq2.pieces.map do |elt2|
      b.call(elt1, elt2)
    end
  end.flatten.tap {|x| break sequence_class.new(x, seq1.attribute)}
end

#match(env, target) ⇒ Boolean

Return true if the type or the pione model object matches.

Parameters:

Returns:

  • (Boolean)

    true if it matches, or false



27
28
29
30
31
32
33
34
# File 'lib/pione/lang/type.rb', line 27

def match(env, target)
  target_type = target.kind_of?(Type) ? target : target.pione_type(env)
  while target_type do
    return true if self == target_type
    target_type = target_type.parent_type
  end
  return false
end

#sequence_classObject



83
84
85
# File 'lib/pione/lang/type.rb', line 83

def sequence_class
  Type.table[self.name][:sequence_class]
end

#sequential_fold1(type, seq1, &b) ⇒ Object



132
133
134
135
136
137
# File 'lib/pione/lang/type.rb', line 132

def sequential_fold1(type, seq1, &b)
  seq_class = type_to_class(type)
  seq1.pieces.inject(seq_class.new([], seq1.attribute)) do |obj, elt1|
    b.call(elt1, obj)
  end
end

#sequential_fold2(type, seq1, seq2, &b) ⇒ Object



139
140
141
142
143
144
145
146
# File 'lib/pione/lang/type.rb', line 139

def sequential_fold2(type, seq1, seq2, &b)
  seq_class = type_to_class(type)
  seq1.pieces.inject(seq_class.new([], seq1.attribute)) do |obj1, elt1|
    seq2.pieces.inject(obj1) do |obj2, elt2|
      b.call(obj2, elt1, elt2)
    end
  end
end

#sequential_map1(type, seq1, &b) ⇒ Object



99
100
101
102
103
104
# File 'lib/pione/lang/type.rb', line 99

def sequential_map1(type, seq1, &b)
  seq_class = type_to_class(type)
  seq1.pieces.map do |elt1|
    seq_class.piece_class.new(b.call(elt1))
  end.tap {|x| break seq_class.new(x, seq1.attribute)}
end

#sequential_map2(type, seq1, seq2, &b) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/pione/lang/type.rb', line 106

def sequential_map2(type, seq1, seq2, &b)
  seq_class = type_to_class(type)
  seq1.pieces.map do |elt1|
    seq2.pieces.map do |elt2|
      seq_class.piece_class.new(b.call(elt1, elt2))
    end
  end.flatten.tap {|x| break seq1.set(x, seq1.attribute)}
end

#sequential_map3(type, seq1, seq2, seq3, &b) ⇒ Object



115
116
117
118
119
120
121
122
123
124
# File 'lib/pione/lang/type.rb', line 115

def sequential_map3(type, seq1, seq2, seq3, &b)
  seq_class = type_to_class(type)
  seq1.pieces.map do |elt1|
    seq2.pieces.map do |elt2|
      seq3.pieces.map do |elt3|
        seq_class.piece_class.new(b.call(elt1, elt2, elt3))
      end
    end
  end.flatten.tap {|x| break seq_class.new(x, seq1.attribute)}
end

#sequential_pred1(seq1, &b) ⇒ Object



148
149
150
151
152
153
# File 'lib/pione/lang/type.rb', line 148

def sequential_pred1(seq1, &b)
  method1 = seq1.every? ? :all? : :any?
  seq1.pieces.send(method1) do |elt1|
    PioneBoolean.new(b.call(elt1))
  end.tap {|x| break BooleanSequence.new(x)}
end

#sequential_pred2(seq1, seq2, &b) ⇒ Object



155
156
157
158
159
160
161
162
163
# File 'lib/pione/lang/type.rb', line 155

def sequential_pred2(seq1, seq2, &b)
  method1 = seq1.every? ? :all? : :any?
  method2 = seq2.every? ? :all? : :any?
  seq1.pieces.send(method1) do |elt1|
    seq2.pieces.send(method2) do |elt2|
      b.call(elt1, elt2)
    end
  end.tap {|x| break BooleanSequence.new([PioneBoolean.new(x)])}
end

#to_sObject



165
166
167
# File 'lib/pione/lang/type.rb', line 165

def to_s
  "#<Type %s>" % name
end