def compile_return(self, tree, code):
        "Compile a return statement."
        vals = tree.children[1].children
        for val in vals:
            self.compile_expression(val, code)
        if self._current_def_name == 'program':
            vrs = []
            expr_count = 1
            for v in tree.children[1].children:
                if v.children[0] == 'varName':
                    vrs.append(v.children[1].value)
                else:
                    vrs.append("#%s" % (expr_count,))
                expr_count += 1

            if hasattr(tree, 'type_annot'):
                # Decorate the return variables with their types.
                types = [
                    repr(subtype)
                    for subtype in tree.type_annot.subtypes()
                ]
                vrs = [
                    gbs_builtins.polyname(vname, [vtype])
                    for vname, vtype in zip(vrs, types)
                ]
            code.push(('returnVars', len(vals), vrs), near=tree)
        else:
            code.push(('return', len(vals)), near=tree)
    def _compile_func_call_poly(self, tree, funcname, args, code):
        "Compile a potentially polymorphic function call."
        polys = gbs_builtins.BUILTINS_POLYMORPHIC
        annotate = True
        annotate = annotate and funcname in polys
        annotate = annotate and hasattr(tree, 'type_annotation')
        annotate = annotate and isinstance(tree.type_annotation, list)

        type_annotation = None
        if hasattr(tree, 'type_annotation'):
            type_annotation = tree.type_annotation

        for i, arg in zip(range(len(args)),args):
            self.compile_expression(arg, code)

        if annotate:
            funcname = gbs_builtins.polyname(
                funcname,
                [repr(ann) for ann in tree.type_annotation])
        code.push(('call', funcname, len(args)), near=tree)