def _check_excluded_types(self, tree, type, excluded_types):
     for excluded_type in excluded_types:
         try:
             gbs_type.unify(type, excluded_type)
             area = position.ProgramAreaNear(tree)
             msg = i18n.i18n('Expression can\'t have type: %s') % (excluded_type,)
             self.error(GbsTypeInferenceException(msg, area))
         except gbs_type.UnificationFailedException as exception:
             pass
 def _set_routine_definition_type(self, tree, prfn, name, params, body):
     """Given a context with types for the parameters and local
     variables in a routine, build the type for this routine
     and unify it with its type in the global context.
     For instance if the function "f" has a parameter "x",
     and returns an expression, take the type "s" for "x"
     from the local context, the type "t" for the returned
     expression. Build the type "s -> t" for the function
     and unify that with any type information previously
     known for "f". This requires that the body of the routine
     has already been typechecked."""
     param_types = []
     for p in params.children:
         param_types.append(self.context[p.value])
     param_types = gbs_type.GbsTupleType(param_types)
     if prfn == 'procedure':
         def_type = gbs_type.GbsProcedureType(param_types)
     elif prfn == 'function':
         return_types = self._return_type(prfn, name, params, body)
         def_type = gbs_type.GbsFunctionType(param_types, return_types)
     elif prfn == 'entrypoint' and (name.value == 'program' or name.value == 'interactive'):
         def_type = gbs_type.GbsEntryPointType()
     else:
         assert False
     expected = self.global_context[name.value].instantiate()
     try:
         gbs_type.unify(expected, def_type)
         if prfn == 'function': #[TODO] Check
             freevars = def_type.freevars()
             if len(freevars) > 0:
                 def_type = gbs_type.GbsForallType(freevars, def_type)
                 self.global_context[name.value] = def_type
         tree.type_annot = def_type
     except gbs_type.UnificationFailedException as e:
         area = position.ProgramAreaNear(tree)
         if prfn == 'procedure':
             msg = i18n.i18n(
                       'procedure "%s" should take: %s\n' +
                       'But takes: %s'
                   ) % (
                       name.value,
                       expected.paramtype(),
                       def_type.paramtype()
                   )
         else:
             msg = i18n.i18n(
                       'function "%s" should take: %s and return: %s\n' +
                       'But takes: %s and returns: %s'
                   ) % (
                       name.value,
                       expected.paramtype(), expected.restype(),
                       def_type.paramtype(), def_type.restype()
                   )
         self.error(GbsTypeInferenceException(msg, area))
 def _add_var(self, token, new_type=None):
     """Add a variable to the context with the given type, checking
     that it is consistent with the types it might already have."""
     if new_type is None: # fresh
         new_type = gbs_type.GbsTypeVar()
     varname = token.value
     if varname in self.ribs[-1]:
         old_type = self.context[varname]
         gbs_type.unify(new_type, old_type)
     else:
         self.context[varname] = new_type
         set_add(self.ribs[-1], varname)
     return new_type
 def check_type(self, tree, real_type, expected_type, excluded_types=[]):
     try:
         gbs_type.unify(real_type, expected_type)
         self._check_excluded_types(tree, real_type, excluded_types)
         return real_type
     except gbs_type.UnificationFailedException as e:
         area = position.ProgramAreaNear(tree)
         msg = i18n.i18n(
                   'Expression should have type: %s\n' +
                   'But has type: %s'
               ) % (
                   expected_type, real_type
               )
         self.error(GbsTypeInferenceException(msg, area))
 def _check_literals(self, lits, expected_type):
     """Check the types for the list of literals in a
     case statement."""
     for lit in lits.children:
         lit_type = self.infer_tok_literal(lit)
         try:
             gbs_type.unify(lit_type, expected_type)
         except gbs_type.UnificationFailedException as e:
             area = position.ProgramAreaNear(lit)
             msg = i18n.i18n(
                       'Literal should have type: %s\n' +
                       'But has type: %s'
                   ) % (
                       expected_type, lit_type
                   )
             self.error(GbsTypeInferenceException(msg, area))
 def infer_proc_call(self, tree):
     "Infer types for a procedure call."
     proc_name = tree.children[1].value
     proc_type = self.global_context[proc_name].instantiate()
     arg_type = self.infer_tuple(tree.children[2])
     expected = gbs_type.GbsProcedureType(arg_type)
     try:
         gbs_type.unify(proc_type, expected)
     except gbs_type.UnificationFailedException as e:
         area = position.ProgramAreaNear(tree)
         msg = i18n.i18n(
                   'procedure "%s" is receiving: %s\n' +
                   'But should receive: %s'
               ) % (
                   proc_name, expected.paramtype(), proc_type.paramtype()
               )
         self.error(GbsTypeInferenceException(msg, area))
     tree.type_annotation = proc_type.parameters()
    def _infer_func_call(self, tree, nretvals):
        "Infer types for a function call."
        fun_name = tree.children[1].value
        fun_type = self.global_context[fun_name].instantiate()
        arg_type = self.infer_tuple(tree.children[2])
        subtypes = [gbs_type.GbsTypeVar() for i in range(nretvals)]
        res_type = gbs_type.GbsTupleType(subtypes)
        expected = gbs_type.GbsFunctionType(arg_type, res_type)

        # check parameters
        try:
            gbs_type.unify(expected.paramtype(), fun_type.paramtype())
        except gbs_type.UnificationFailedException as e:
            area = position.ProgramAreaNear(tree)
            msg = i18n.i18n(
                      'function "%s" is receiving: %s\n' +
                      'But should receive: %s'
                  ) % (
                      fun_name, print_type(expected.paramtype()), print_type(fun_type.paramtype())
                  )
            self.error(GbsTypeInferenceException(msg, area))

        # check return value
        try:
            gbs_type.unify(fun_type._res, expected._res)
        except gbs_type.UnificationFailedException as e:
            area = position.ProgramAreaNear(tree)
            msg = i18n.i18n(
                      'function "%s" is called as if it returned: %s\n' +
                      'But returns: %s'
                  ) % (
                      fun_name, expected._res, fun_type._res
                  )
            self.error(GbsTypeInferenceException(msg, area))

        tree.type_annotation = fun_type.parameters()
        return res_type