Esempio n. 1
0
File: parser.py Progetto: W-M-T/gsc
def ExpSubTup():
    yield ps.token(TOKEN.PAR_OPEN)
    a = yield Exp
    b = yield ExpClose
    if b is None:
        return a
    else:
        return AST.TUPLE(a=a, b=b)
Esempio n. 2
0
def typecheck(expr, exp_type, symbol_table, ext_table, func=None, r=0, noErrors=False):

    if type(expr) is Token:
        if expr.typ == TOKEN.EMPTY_LIST:
            if type(exp_type) == AST.LISTTYPE:
                return True, expr
            else:
                ERROR_HANDLER.addError(ERR.UnexpectedEmptyList, [expr])

        typ = tokenToNode(expr)
        if not AST.equalVals(typ, exp_type):
            if r == 0 and not noErrors:
                ERROR_HANDLER.addError(ERR.UnexpectedType, [subprint_type(typ), subprint_type(exp_type), expr])
            return False, expr

        return True, expr
    elif type(expr) is AST.PARSEDEXPR:
        return typecheck(expr.val, exp_type, symbol_table, ext_table, func, r, noErrors)
    elif type(expr) is AST.RES_VARREF:
        if type(expr.val) is AST.RES_GLOBAL:
            if expr.val.module is None:
                typ = symbol_table.global_vars[expr.val.id.val].type.val
            else:
                typ = ext_table.global_vars[expr.val.id.val]['type'].val
            fields = list(reversed(expr.val.fields))

            success, typ = getSubType(typ, fields, expr)

            if not success:
                return True, expr

            if not AST.equalVals(typ, exp_type):
                if r == 0 and not noErrors:
                    ERROR_HANDLER.addError(ERR.UnexpectedType, [subprint_type(typ), subprint_type(exp_type), expr])
                return False, expr

        elif type(expr.val) is AST.RES_NONGLOBAL:
            typ = None
            if expr.val.scope == NONGLOBALSCOPE.LocalVar:
                typ = func['local_vars'][expr.val.id.val].type.val
            else:
                typ = func['arg_vars'][expr.val.id.val]['type'].val

            fields = list(reversed(expr.val.fields))
            success, typ = getSubType(typ, fields, expr)

            if not success:
                return True, expr

            if not AST.equalVals(typ, exp_type):
                if r == 0 and not noErrors:
                    ERROR_HANDLER.addError(ERR.UnexpectedType, [subprint_type(typ), subprint_type(exp_type), expr])
                return False, expr

        return True, expr
    elif type(expr) is AST.FUNCALL:
        identifier = (FunKindToUniq(expr.kind), expr.id.val)
        if identifier not in symbol_table.functions and identifier not in ext_table.functions:
            ERROR_HANDLER.addError(ERR.UndefinedFun, [expr.id.val, expr.id])
            return True, expr

        # Symbol table functions
        matches = []
        if identifier in symbol_table.functions:
            out_type_matches = {}
            i = 0
            for o in symbol_table.functions[identifier]:
                if AST.equalVals(exp_type, o['type'].to_type.val) or exp_type is None:
                    out_type_matches[i] = o
                i += 1

            for k, o in out_type_matches.items():
                args = []

                if len(o['type'].from_types) == len(expr.args):
                    input_matches = 0

                    for i in range(len(o['type'].from_types)):
                        typ, arg_res = typecheck(expr.args[i], o['type'].from_types[i].val, symbol_table, ext_table, func, r, noErrors=True)
                        args.append(arg_res)
                        if typ:
                            input_matches += 1

                    if input_matches == len(expr.args):
                        matches.append({
                            'id': k,
                            'module': None,
                            'args': args,
                            'returns': not AST.equalVals(o['type'].to_type, AST.TYPE(val=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Void"))),
                        })

        if identifier in ext_table.functions:
            out_type_matches = {}
            i = 0
            for o in ext_table.functions[identifier]:
                if AST.equalVals(exp_type, o['type'].to_type.val) or exp_type is None:
                    if o['module'] not in out_type_matches:
                        out_type_matches[o['module']] = {}
                    out_type_matches[o['module']][i] = o
                i += 1

            if len(out_type_matches) == 0 and len(matches) == 0:
                if not noErrors and exp_type is not None:
                    if expr.kind == FunKind.FUNC:
                        ERROR_HANDLER.addError(ERR.NoOverloadedFunDef, [expr.id.val, subprint_type(exp_type), expr.id])
                    else:
                        ERROR_HANDLER.addError(ERR.NoOpDefWithType, [expr.id.val, subprint_type(exp_type), expr.id])
                return False, expr

            for module, f in out_type_matches.items():
                for oid, of in f.items():
                    args = []
                    if len(of['type'].from_types) == len(expr.args):
                        input_matches = 0

                        for i in range(len(of['type'].from_types)):
                            typ, arg_res = typecheck(expr.args[i], of['type'].from_types[i].val, symbol_table, ext_table, func, r, noErrors=True)
                            args.append(arg_res)
                            if typ:
                                input_matches += 1

                        if input_matches == len(expr.args):
                            matches.append({
                                'id': oid,
                                'module': module,
                                'args': args,
                                'returns': not AST.equalVals(of['type'].to_type, AST.TYPE(val=Token(Position(), TOKEN.TYPE_IDENTIFIER, "Void"))),
                            })

        # Give preference to functions defined in current module if type is exactly the same.
        if len(matches) > 0:
            current_module_matches = 0
            prefered_match = None
            for m in matches:
                if m['module'] is None:
                    current_module_matches += 1
                    if current_module_matches > 1:
                        break
                    else:
                        prefered_match = m

            if current_module_matches == 1:
                matches = [prefered_match]

        if len(matches) == 0:
            if not noErrors:
                if expr.kind == FunKind.FUNC:
                    ERROR_HANDLER.addError(ERR.NoOverloadedFunWithArgs, [expr.id.val, expr.id])
                else:
                    ERROR_HANDLER.addError(ERR.NoOpDefWithInputType, [expr.id.val, expr.id])
            return False, expr
        elif len(matches) > 1 and exp_type is None:
            if not noErrors:
                if expr.kind == FunKind.FUNC:
                    ERROR_HANDLER.addError(ERR.AmbiguousFunCall, [expr.id.val, expr.id])
                else:
                    ERROR_HANDLER.addError(ERR.AmbiguousOp, [expr.id.val, expr.id])
            return False, expr
        elif len(matches) > 1:
            if not noErrors:
                if expr.kind == FunKind.FUNC:
                    ERROR_HANDLER.addError(ERR.AmbiguousNestedFunCall, [expr.id.val, expr.id])
                else:
                    ERROR_HANDLER.addError(ERR.AmbiguousOp, [expr.id.val, expr.id])
            return False, expr
        else:
            if func is None and (matches[0]['module'] != 'builtins' or expr.kind == FunKind.FUNC):
                ERROR_HANDLER.addError(ERR.GlobalDefMustBeConstant, [expr.id])
                return True, expr

        return True, AST.TYPED_FUNCALL(id=expr.id, uniq=FunKindToUniq(expr.kind), args=matches[0]['args'], oid=matches[0]['id'],
                                           module=matches[0]['module'], returns=matches[0]['returns'])

    elif type(expr) is AST.TUPLE:
        if type(exp_type) is not AST.TUPLETYPE:
            ERROR_HANDLER.addError(ERR.UnexpectedTuple, [exp_type, expr])
            return True, expr

        type1, a = typecheck(expr.a, exp_type.a.val, symbol_table, ext_table, func)
        type2, b = typecheck(expr.b, exp_type.b.val, symbol_table, ext_table, func)

        return type1 or type2, AST.TUPLE(a=a, b=b)

    else:
        print(expr)
        print(type(expr))
        raise Exception('Unknown type of expression encountered in typechecking')