Class: Kalculator::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/kalculator/validator.rb

Instance Method Summary collapse

Constructor Details

#initialize(type_source) ⇒ Validator

Returns a new instance of Validator.



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/kalculator/validator.rb', line 9

def initialize(type_source)
  @type_source = type_source
  #e stores built in function type data
  #last index is ALWAYS the return type, and types before that are types of children from left to right
  e = { "contains" => [Collection.new(Object), Object, Bool],
    "count" => [List.new(Object), Number],
    "date" => [String.new, Time],
    "max"=> [Number,Number,Number],
    "min" => [Number,Number,Number],
    "sum" => [List.new(Number), Number] #this only accepts number Lists
  }
  @environment = e.merge(type_source.toHash)
end

Instance Method Details

#!=(_, left, right, metadata) ⇒ Object

Raises:



118
119
120
121
122
123
124
# File 'lib/kalculator/validator.rb', line 118

def !=(_, left, right, )
  leftType = validate(left)
  if(leftType==validate(right))
    return Bool
  end
raise TypeError.new(), "not comparing two of the same comparable types"
end

#*(_, left, right, metadata) ⇒ Object

Raises:



62
63
64
65
66
67
68
# File 'lib/kalculator/validator.rb', line 62

def *(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(), "not operating on two of the same Number types"
end

#+(_, left, right, metadata) ⇒ Object

Raises:



46
47
48
49
50
51
52
# File 'lib/kalculator/validator.rb', line 46

def +(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(), "not operating on two of the same Number types"
end

#-(_, left, right, metadata) ⇒ Object

Raises:



54
55
56
57
58
59
60
# File 'lib/kalculator/validator.rb', line 54

def -(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(), "not operating on two of the same Number types"
end

#/(_, left, right, metadata) ⇒ Object

Raises:



70
71
72
73
74
75
76
# File 'lib/kalculator/validator.rb', line 70

def /(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(), "not operating on two of the same Number types"
end

#<(_, left, right, metadata) ⇒ Object

Raises:



94
95
96
97
98
99
100
# File 'lib/kalculator/validator.rb', line 94

def <(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(), "not comparing two of the same types"
end

#<=(_, left, right, metadata) ⇒ Object

Raises:



102
103
104
105
106
107
108
# File 'lib/kalculator/validator.rb', line 102

def <=(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(), "not comparing two of the same comparable types"
end

#==(_, left, right, metadata) ⇒ Object

Raises:



110
111
112
113
114
115
116
# File 'lib/kalculator/validator.rb', line 110

def ==(_, left, right, )
  leftType = validate(left)
  if(leftType==validate(right))
    return Bool
  end
raise TypeError.new(), "not comparing two of the same comparable types"
end

#>(_, left, right, metadata) ⇒ Object

Raises:



78
79
80
81
82
83
84
# File 'lib/kalculator/validator.rb', line 78

def >(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(), "not comparing two of the same comparable types"
end

#>=(_, left, right, metadata) ⇒ Object

Raises:



86
87
88
89
90
91
92
# File 'lib/kalculator/validator.rb', line 86

def >=(_, left, right, )
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(), "not comparing two of the same comparable types"
end

#access(_, identifier, object, metadata) ⇒ Object

Raises:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/kalculator/validator.rb', line 28

def access(_,identifier,object, )
  objectType = validate(object)
  if((objectType.is_a?(MappedObject)))
    if(objectType.hash.key?(identifier))
      attribute =objectType.hash[identifier]
      if(attribute.is_a?(Pointer))
        attribute = @environment[attribute.p] #if the attribute is a pointer find an add
      end
      if(attribute.is_a?(Kalculator::AnonymousPointer))
        attribute = attribute.p
      end
      return attribute
    end
    raise UndefinedVariableError.new(), "object #{objectType} doesn't have type attribute #{identifier}"
  end
  raise TypeError.new(), "trying to access something that isn't an object"
end

#and(_, left, right, metadata) ⇒ Object

Raises:



126
127
128
129
130
131
# File 'lib/kalculator/validator.rb', line 126

def and(_, left, right, )
  if(validate(left)<=Bool and validate(right)<=Bool)
    return Bool
  end
raise TypeError.new(), "not comparing (AND) two BOOL types"
end

#boolean(_, boolean, type, metadata) ⇒ Object



140
141
142
# File 'lib/kalculator/validator.rb', line 140

def boolean(_, boolean, type, )
  return Bool
end

#exists(_, variable, metadata) ⇒ Object



144
145
146
# File 'lib/kalculator/validator.rb', line 144

def exists(_, variable, )
    return Bool
end

#fn_call(_, fn_name, expressions, metadata) ⇒ Object

compare individually to make sure it is a subclass or class

Raises:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/kalculator/validator.rb', line 148

def fn_call(_, fn_name, expressions, ) #compare individually to make sure it is a subclass or class
  ex =expressions.map{|expression| validate(expression) }
  raise UndefinedVariableError.new(), "undefined variable #{fn_name}" unless @environment.key?(fn_name)
  argumentMatch = ex.zip(@environment[fn_name]).all? do |(arg_type, expected_type)|
    begin
      arg_type <= expected_type
    rescue
      begin
        expected_type >= arg_type
      rescue
        false
      end
    end
  end
  if(argumentMatch) # make sure each element is related to corresponding element in the funcion params
    if(fn_name == "max" or fn_name == "min") #add functions here where output type depends on input type and all types must be exact same ie. max(Percent,Percent) => Percent max(Number,Percent)=> Error max(Number,Number)=>Number
      #check all expressions are same
      cmptype = ex[0]
      if( ex.all?{|t| t == cmptype})
        return cmptype
      end
      raise TypeError.new(), "specialized function type error"
    end
    #add other specialized functions here
    if(fn_name == "contains") #generic function in the format List<E>, E => ReturnType
      if(ex[0].generic_type?(ex[1]))
        return @environment[fn_name][@environment[fn_name].size - 1]
      end
      raise TypeError.new(), "generic function type error"
    end
    return @environment[fn_name][@environment[fn_name].size - 1]
  end
  raise TypeError.new(), "function type error"
end

#if(_, condition, true_clause, false_clause, metadata) ⇒ Object

Raises:



183
184
185
186
187
188
189
# File 'lib/kalculator/validator.rb', line 183

def if(_, condition, true_clause, false_clause, )
  conditionType = validate(condition)
  if(conditionType <= Object and validate(true_clause)==validate(false_clause))
    return validate(true_clause)
  end
raise TypeError.new(), "if statement type error"
end

#list(_, expressions, metadata) ⇒ Object

Raises:



191
192
193
194
195
196
197
198
199
200
# File 'lib/kalculator/validator.rb', line 191

def list(_, expressions, )
  ex =expressions.map{|expression| validate(expression) }

  cmptype = ex[0]
  if( ex.all?{|t| t == cmptype})
    return List.new(cmptype)
  end
raise TypeError.new(), "list type error"

end

#not(_, expression, metadata) ⇒ Object

Raises:



202
203
204
205
206
207
208
# File 'lib/kalculator/validator.rb', line 202

def not(_, expression, )
  if(validate(expression) ==Bool)
    return Bool

  end
  raise TypeError.new(), "NOT expression type error"
end

#null(_, _, type, metadata) ⇒ Object



210
211
212
# File 'lib/kalculator/validator.rb', line 210

def null(_, _, type, )
  return type
end

#number(_, number, type, metadata) ⇒ Object



214
215
216
# File 'lib/kalculator/validator.rb', line 214

def number(_, number, type, )
  return type
end

#or(_, left, right, metadata) ⇒ Object

Raises:



133
134
135
136
137
138
# File 'lib/kalculator/validator.rb', line 133

def or(_, left, right, )
  if(validate(left)<=Bool and validate(right)<=Bool)
    return Bool
  end
raise TypeError.new(), "not comparing (OR) two BOOL types"
end

#percent(_, percent, type, metadata) ⇒ Object



218
219
220
# File 'lib/kalculator/validator.rb', line 218

def percent(_, percent, type, )
  return type
end

#string(_, string, type, metadata) ⇒ Object



222
223
224
# File 'lib/kalculator/validator.rb', line 222

def string(_, string, type, )
  return type
end

#validate(ast) ⇒ Object



23
24
25
26
# File 'lib/kalculator/validator.rb', line 23

def validate(ast)
  send(ast.first, *ast)

end

#variable(_, name, metadata) ⇒ Object

Raises:



226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/kalculator/validator.rb', line 226

def variable(_, name, )

  raise UndefinedVariableError.new(), "undefined variable #{name}" unless @environment.key?(name)
  variable_type = @environment[name]
  if(variable_type.is_a?(Pointer))
    variable_type = @environment[variable_type.p] #if the variable you are accessing is a pointer, then return the type of the variable it is pointing to
  end
  if(variable_type.is_a?(Kalculator::AnonymousPointer))
    variable_type = variable_type.p
  end
  return variable_type
end