class Kalculator::Validator

Public Class Methods

new(type_source) click to toggle source
# 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

Public Instance Methods

!=(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 118
def !=(_, left, right, metadata)
  leftType = validate(left)
  if(leftType==validate(right))
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same comparable types"
end
*(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 62
def *(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(metadata), "not operating on two of the same Number types"
end
+(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 46
def +(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(metadata), "not operating on two of the same Number types"
end
-(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 54
def -(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(metadata), "not operating on two of the same Number types"
end
/(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 70
def /(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType <=Number)
    return leftType
  end
raise TypeError.new(metadata), "not operating on two of the same Number types"
end
<(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 94
def <(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same types"
end
<=(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 102
def <=(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same comparable types"
end
==(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 110
def ==(_, left, right, metadata)
  leftType = validate(left)
  if(leftType==validate(right))
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same comparable types"
end
>(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 78
def >(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same comparable types"
end
>=(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 86
def >=(_, left, right, metadata)
  leftType = validate(left)
  if((leftType==validate(right)) and leftType<= Comparable)
    return Bool
  end
raise TypeError.new(metadata), "not comparing two of the same comparable types"
end
access(_,identifier,object, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 28
def access(_,identifier,object, metadata)
  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(metadata), "object #{objectType} doesn't have type attribute #{identifier}"
  end
  raise TypeError.new(metadata), "trying to access something that isn't an object"
end
and(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 126
def and(_, left, right, metadata)
  if(validate(left)<=Bool and validate(right)<=Bool)
    return Bool
  end
raise TypeError.new(metadata), "not comparing (AND) two BOOL types"
end
boolean(_, boolean, type, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 140
def boolean(_, boolean, type, metadata)
  return Bool
end
exists(_, variable, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 144
def exists(_, variable, metadata)
    return Bool
end
fn_call(_, fn_name, expressions, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 148
def fn_call(_, fn_name, expressions, metadata) #compare individually to make sure it is a subclass or class
  ex =expressions.map{|expression| validate(expression) }
  raise UndefinedVariableError.new(metadata), "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(metadata), "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(metadata), "generic function type error"
    end
    return @environment[fn_name][@environment[fn_name].size - 1]
  end
  raise TypeError.new(metadata), "function type error"
end
if(_, condition, true_clause, false_clause, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 183
def if(_, condition, true_clause, false_clause, metadata)
  conditionType = validate(condition)
  if(conditionType <= Object and validate(true_clause)==validate(false_clause))
    return validate(true_clause)
  end
raise TypeError.new(metadata), "if statement type error"
end
list(_, expressions, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 191
def list(_, expressions, metadata)
  ex =expressions.map{|expression| validate(expression) }

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

end
not(_, expression, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 202
def not(_, expression, metadata)
  if(validate(expression) ==Bool)
    return Bool

  end
  raise TypeError.new(metadata), "NOT expression type error"
end
null(_, _, type, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 210
def null(_, _, type, metadata)
  return type
end
number(_, number, type, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 214
def number(_, number, type, metadata)
  return type
end
or(_, left, right, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 133
def or(_, left, right, metadata)
  if(validate(left)<=Bool and validate(right)<=Bool)
    return Bool
  end
raise TypeError.new(metadata), "not comparing (OR) two BOOL types"
end
percent(_, percent, type, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 218
def percent(_, percent, type, metadata)
  return type
end
string(_, string, type, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 222
def string(_, string, type, metadata)
  return type
end
validate(ast) click to toggle source
# File lib/kalculator/validator.rb, line 23
def validate(ast)
  send(ast.first, *ast)

end
variable(_, name, metadata) click to toggle source
# File lib/kalculator/validator.rb, line 226
def variable(_, name, metadata)

  raise UndefinedVariableError.new(metadata), "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