Esempio n. 1
0
def method_invocation(node):
  if not isinstance(node, ast_expression.ASTMethodInvocation):
    return None

  param_types = [type_checker.get_type(arg) for arg in node.arguments]
  # If we have a right node, we must do field access on the left. Otherwise the
  # left is an ASTIdentifiers.
  if node.right is None:
    iden = node.left
    name, defn = iden.first_definition
    if defn is None:
      return None

    # When there is only one part to the identifier, it is meant to be called on
    # "this", and we have that defn is an ASTType of the class.
    if name == '':
      method = _resolve_further_fields(defn.definition, iden.parts,
          method_type=param_types, type_node=defn)
    else:
      method = _resolve_identifier(node.left, method_type=param_types)
  else:
    t_left = type_checker.get_type(node.left)
    method = _resolve_further_fields(t_left.definition, node.right.parts,
        method_type=param_types, type_node=t_left)

  if not isinstance(method, ast_method.ASTMethod):
    return None

  return method.return_type
Esempio n. 2
0
def block(node):
  if not isinstance(node, ast_block.ASTBlock):
    return None

  # Type of all of the substatements:
  for c in node.children:
    type_checker.get_type(c)

  return ast_type.ASTType.ASTVoid
Esempio n. 3
0
def assignment(node):
  if not isinstance(node, ast_expression.ASTAssignment):
    return None

  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)

  if not t_left.is_final and _is_assignable(t_left, t_right):
    return t_left

  return None
Esempio n. 4
0
def array_access(node):
  if not isinstance(node, ast_expression.ASTArrayAccess):
    return None

  t_array = type_checker.get_type(node.array_expression)
  t_index = type_checker.get_type(node.index)
  if t_array.is_array and _is_numeric(t_index):
    new_t_array = copy.copy(t_array)
    new_t_array.is_array = False
    return new_t_array

  return None
Esempio n. 5
0
def while_statement(node):
  '''Check statement: while (E) S'''
  if not isinstance(node, ast_while.ASTWhile):
    return None

  # While expression must be a boolean
  t_while_expr = type_checker.get_type(node.expression)
  if t_while_expr != ast_type.ASTType.ASTBoolean:
    return None

  # Make sure that the while body is typeable.
  type_checker.get_type(node.statement)

  return ast_type.ASTType.ASTVoid
Esempio n. 6
0
def numeric_comparisons(node):
  '''Comparison operators for numeric types (<, <=, >, >=)'''
  if not isinstance(node, ast_expression.ASTBinary):
    return None

  # Check for valid operators.
  if node.operator not in ['<', '<=', '>', '>=']:
    return None

  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)
  if _is_numeric(t_left) and _is_numeric(t_right):
    return ast_type.ASTType.ASTBoolean
  return None
Esempio n. 7
0
def generic_equality(node):
  '''Equality comparisons for assignable types (==, !=)'''
  if not isinstance(node, ast_expression.ASTBinary):
    return None

  # Check for valid operators.
  if node.operator not in ['==', '!=']:
    return None

  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)
  if _is_assignable(t_left, t_right) or _is_assignable(t_right, t_left):
    return ast_type.ASTType.ASTBoolean
  return None
Esempio n. 8
0
def return_statement(node):
  '''Check statement: return E'''
  if not isinstance(node, ast_return.ASTReturn):
    return None

  method = type_checker.get_param('cur_method')

  # If there is an expression, make sure it is typeable.
  expr_type = None
  if len(node.expressions) != 0:
    expr_type = type_checker.get_type(node.expressions[0])

  # Constructors have no return type, so you can't return something in one:
  if method.is_constructor and expr_type:
    return None

  # void methods should return nothing:
  if method.return_type == ast_type.ASTType.ASTVoid and not expr_type:
    return True

  # constructors should return nothing:
  if method.is_constructor and not expr_type:
    return True

  # The type you return must be assignable to the current method return type:
  if not _is_assignable(method.return_type, expr_type):
    return None

  return ast_type.ASTType.ASTVoid
Esempio n. 9
0
def if_statement(node):
  '''Check statement: if (E) S'''
  if not isinstance(node, ast_if.ASTIf):
    return None

  # If expression must be a boolean
  t_if_expr = type_checker.get_type(node.expression)
  if t_if_expr != ast_type.ASTType.ASTBoolean:
    return None

  # Check that the if and else statements are typeable.
  type_checker.get_type(node.if_statement)
  if node.else_statement:
    type_checker.get_type(node.else_statement)

  return ast_type.ASTType.ASTVoid
Esempio n. 10
0
def constructor(node):
  '''new D(E1, E2, .., Ek) types to D'''
  if not isinstance(node, ast_expression.ASTClassInstanceCreation):
    return None

  # You can't instantiate abstract classes.
  if node.type_node.definition.is_abstract:
    return None

  short_name = node.type_node.identifier.parts[-1]
  env = node.type_node.definition.environment
  param_types = [type_checker.get_type(x) for x in node.arguments]

  method_sig = (short_name, param_types)
  method, enclosing_type = env.lookup_method(method_sig, constructor=True)
  if method is not None:
    if method.is_protected:
      # JLS 6.6.2. A protected constructor can be accessed only from within the
      # package in which it is defined.
      if enclosing_type.package_name != \
          type_checker.get_param('cur_class').package_name:
        return None
    return node.type_node

  # No matching constructor found.  Whoops...!
  return None
Esempio n. 11
0
def boolean_ops(node):
  '''Eager and lazy boolean operations (&, |, &&, ||)'''
  if not isinstance(node, ast_expression.ASTBinary):
    return None

  # Check for valid operators.
  if node.operator not in ['&', '|', '&&', '||']:
    return None

  # Make sure both operands are booleans.
  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)
  if t_left == ast_type.ASTType.ASTBoolean and \
     t_right == ast_type.ASTType.ASTBoolean:
    return ast_type.ASTType.ASTBoolean
  return None
Esempio n. 12
0
def numeric_math(node):
  '''Math operator for numeric types (+, -, *, /, %)'''
  if not isinstance(node, ast_expression.ASTBinary):
    return None

  # Check for valid math operators.
  if node.operator not in ['+', '-', '*', '/', '%']:
    return None

  # Check that both operands are numeric.
  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)
  if _is_numeric(t_left) and _is_numeric(t_right):
    # Always promote math exprs to int.
    return ast_type.ASTType.ASTInt
  return None
Esempio n. 13
0
def instance_of(node):
  if not isinstance(node, ast_expression.ASTInstanceOf):
    return None

  expr_type = type_checker.get_type(node.expressions[0])
  if _is_assignable(expr_type, node.type_node) or \
      _is_assignable(node.type_node, expr_type):
    return ast_type.ASTType.ASTBoolean

  return None
Esempio n. 14
0
def array_creation(node):
  if not isinstance(node, ast_expression.ASTArrayCreation):
    return None

  t_length_expr = type_checker.get_type(node.length_expr)
  t_array = node.type_node
  if _is_numeric(t_length_expr):
    new_t_array = copy.copy(t_array)
    new_t_array.is_array = True
    return new_t_array
Esempio n. 15
0
def boolean_not(node):
  '''Unary boolean operator: !'''
  if not isinstance(node, ast_expression.ASTUnary):
    return None

  if node.operator != '!':
    return None

  t = type_checker.get_type(node.expressions[0])
  if t == ast_type.ASTType.ASTBoolean:
    return ast_type.ASTType.ASTBoolean
  return None
Esempio n. 16
0
def cast(node):
  if not isinstance(node, ast_cast.ASTCast):
    return None

  expr_type = type_checker.get_type(node.expressions[0])
  if _is_numeric(expr_type) and _is_numeric(node.type_node):
    return node.type_node
  if _is_assignable(expr_type, node.type_node) or \
      _is_assignable(node.type_node, expr_type):
    return node.type_node

  return None
Esempio n. 17
0
def string_plus(node):
  '''Binary expression of string + string'''
  if not isinstance(node, ast_expression.ASTBinary):
    return None

  if node.operator != '+':
    return None

  # Check that both operands are of the string type.
  t_left = type_checker.get_type(node.left_expr)
  t_right = type_checker.get_type(node.right_expr)

  if t_left == ast_type.ASTType.ASTVoid or \
      t_right == ast_type.ASTType.ASTVoid:
    # You can't string + on void types.
    return None

  # Check to make sure one of part typed to a string.
  if _is_string(t_left) or _is_string(t_right):
    return ast_type.ASTType.ASTString
  return None
Esempio n. 18
0
def unary_math(node):
  '''Unary negation operator for numeric types (-)'''
  if not isinstance(node, ast_expression.ASTUnary):
    return None

  if node.operator != '-':
    return None

  t = type_checker.get_type(node.expressions[0])
  if _is_numeric(t):
    # Promote to int.
    return ast_type.ASTType.ASTInt
  return None
Esempio n. 19
0
def variable_declaration(node):
  if not isinstance(node, ast_variable_declaration.ASTVariableDeclaration):
    return None

  t_left = node.type_node
  t_right = None
  if node.expression is not None:
    t_right = type_checker.get_type(node.expression)

  if t_right is None or _is_assignable(t_left, t_right):
    return ast_type.ASTType.ASTVoid

  return None
Esempio n. 20
0
def field_access(node):
  if not isinstance(node, ast_expression.ASTFieldAccess):
    return None

  t_left = type_checker.get_type(node.left)

  # Make sure that the left type can have fields.
  if (t_left.is_primitive and not t_left.is_array):
    return None

  type_or_decl = _resolve_further_fields(t_left.definition, node.right.parts,
      type_node=t_left)
  if isinstance(type_or_decl, ast_variable_declaration.ASTVariableDeclaration):
    return type_or_decl.type_node
  elif isinstance(type_or_decl, ast_param.ASTParam):
    return type_or_decl.type

  return type_or_decl
Esempio n. 21
0
def for_statement(node):
  '''Check statement: for (S ; E ; S) S'''
  if not isinstance(node, ast_for.ASTFor):
    return None

  # If there is a for expression, the type of it must be a boolean.
  if node.expression is not None:
    t_for_expr = type_checker.get_type(node.expression)
    if t_for_expr != ast_type.ASTType.ASTBoolean:
      return None

  # If there is an init or update statement, we must make sure that it is
  # typeable.
  if node.init is not None:
    type_checker.get_type(node.init)
  if node.update is not None:
    type_checker.get_type(node.update)

  type_checker.get_type(node.statement)

  return ast_type.ASTType.ASTVoid