Example #1
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t

        if t1.base:
            if type(t1) == TypeSystem.Sym:
                rt.t = t1
            elif type(t1) == TypeSystem.Real:
                rt.t = TypeSystem.Real
            else:
                return None
        else:
            return None

        return t_env
Example #2
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t
        t2: TypeSystem.T = rt.chd[1].t

        if t1.base:
            if t2.base:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2)

                if type(res_t) in [
                        TypeSystem.Real, TypeSystem.Cmplx, TypeSystem.Sym
                ]:
                    rt.t = res_t
                else:
                    return None
            else:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2.chd_t)

                if type(res_t) in [
                        TypeSystem.Real, TypeSystem.Cmplx, TypeSystem.Sym
                ]:
                    rt.t = TypeSystem.ArrFact.inst().coerce_arr_t(t2, res_t)
                else:
                    return None
        else:
            if t2.base:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1.chd_t, t2)

                if type(res_t) in [
                        TypeSystem.Real, TypeSystem.Cmplx, TypeSystem.Sym
                ]:
                    rt.t = TypeSystem.ArrFact.inst().coerce_arr_t(t1, res_t)
                else:
                    return None
            else:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2)

                if res_t and type(
                        res_t.chd_t) in [TypeSystem.Real, TypeSystem.Cmplx]:
                    rt.t = res_t
                else:
                    return None

        return t_env
Example #3
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t: TypeSystem.T = rt.chd[0].t

        if t.base:
            if type(t) not in [TypeSystem.Bool, TypeSystem.Sym]:
                return None
            else:
                rt.t = TypeSystem.Bool.inst()
        else:
            if type(t.chd_t) != TypeSystem.Bool:
                return None
            else:
                rt.t = TypeSystem.Bool.inst()

        return t_env
Example #4
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t
        t2: TypeSystem.T = rt.chd[1].t

        if t1.base:
            if t2.base:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2)

                if not res_t or type(res_t) == TypeSystem.Void:
                    return None
                else:
                    rt.t = TypeSystem.Bool.inst()
            else:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2.chd_t)

                if not res_t or type(res_t) == TypeSystem.Void:
                    return None
                else:
                    rt.t = TypeSystem.ArrFact.inst().coerce_arr_t(
                        t2, TypeSystem.Bool.inst())
        else:
            if t2.base:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1.chd_t, t2)

                if not res_t or type(res_t) == TypeSystem.Void:
                    return None
                else:
                    rt.t = TypeSystem.ArrFact.inst().coerce_arr_t(
                        t1, TypeSystem.Bool.inst())
            else:
                res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2)

                if not res_t.chd_t or type(res_t.chd_t) == TypeSystem.Void:
                    return None
                else:
                    rt.t = TypeSystem.ArrFact.inst().coerce_arr_t(
                        t1, TypeSystem.Bool.inst())

        return t_env
Example #5
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t
        t2: TypeSystem.T = rt.chd[1].t

        if t1.base and t2.base:
            res_t: TypeSystem.T = TypeSystem.T.supt(t1, t2)

            if type(res_t) == TypeSystem.Real:
                rt.t = TypeSystem.Tens(res_t, [None])
            elif type(res_t) == TypeSystem.Sym:
                rt.t = res_t
            else:
                return None
        else:
            return None

        return t_env
Example #6
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t: TypeSystem.T = rt.chd[0].t

        if t.base:
            if type(t) in [TypeSystem.Real, TypeSystem.Cmplx, TypeSystem.Sym]:
                rt.t = t

                return t_env
            else:
                return None
        else:
            if type(t.chd_t) in [TypeSystem.Real, TypeSystem.Cmplx]:
                rt.t = t

                return t_env
            else:
                return None
Example #7
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t: TypeSystem.T = rt.chd[0].t

        if t.base:
            if type(t) == TypeSystem.Sym:
                rt.t = t

                return t_env
            else:
                return None
        else:
            if type(t.chd_t) == TypeSystem.Void or t.fold == 1:
                return None
            else:
                rt.t = t

                return t_env
Example #8
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t

        if any(map(lambda x: type(x.t) == TypeSystem.Sym, rt.chd)):
            rt.t = TypeSystem.Sym.inst()

            return t_env

        if t1.base or t1.fold < rt.argc - 1:
            return None

        for tok in rt.chd[1:]:
            t1 = cls.__chk_t_hlpr(t1, tok.t)

            if not t1:
                return None

        rt.t = t1

        return t_env
Example #9
0
    def chk_t(
            cls, rt: Token.Tok,
            t_env: Dict[int,
                        TypeSystem.T]) -> Optional[Dict[int, TypeSystem.T]]:
        t1: TypeSystem.T = rt.chd[0].t
        t2: TypeSystem.T = rt.chd[1].t

        if t1.base:
            if not (type(t1) == TypeSystem.Sym) or type(t2) == TypeSystem.Void:
                return None
            else:
                rt.t = t2
        else:
            return None

        return t_env
Example #10
0
    def __str_pos_hlpr(self, rt: Token.Tok,
                       target: Token.Tok) -> Tuple[str, bool, int]:
        tok_t: type = type(rt)

        if tok_t == Token.Op:
            if rt.v == Binary.Pow or rt.v.__base__ in [Assign.AsgnOp]:
                tmp_1: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[0], target)
                tmp_2: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[1], target)

                if rt == target:
                    if type(
                            rt.chd[0]
                    ) == Token.Op and rt.precd_in >= rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                        pos: int = tmp_1[2] + 3
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '
                        pos: int = tmp_1[2] + 1

                    if type(rt.chd[1]
                            ) == Token.Op and rt.precd_in > rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_1[1]:
                    if type(
                            rt.chd[0]
                    ) == Token.Op and rt.precd_in >= rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                        pos: int = tmp_1[2] + 1
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '
                        pos: int = tmp_1[2]

                    if type(rt.chd[1]
                            ) == Token.Op and rt.precd_in > rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_2[1]:
                    if type(
                            rt.chd[0]
                    ) == Token.Op and rt.precd_in >= rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '

                    if type(rt.chd[1]
                            ) == Token.Op and rt.precd_in > rt.chd[1].precd_in:
                        pos: int = len(buf) + tmp_2[2] + 1
                        buf += f'({tmp_2[0]})'
                    else:
                        pos: int = len(buf) + tmp_2[2]
                        buf += tmp_2[0]

                    return buf, True, pos
                else:
                    if type(
                            rt.chd[0]
                    ) == Token.Op and rt.precd_in >= rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '

                    if type(rt.chd[1]
                            ) == Token.Op and rt.precd_in > rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, False, len(buf)
            elif rt.v in [Unary.Plus, Unary.Minus, Bool.Neg]:
                tmp: Tuple[str, bool,
                           int] = self.__str_pos_hlpr(rt.chd[0], target)

                if rt == target:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        return f'{rt.v.sym()}({tmp[0]})', True, 0
                    else:
                        return f'{rt.v.sym()}{tmp[0]}', True, 0
                elif tmp[1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        return f'{rt.v.sym()}({tmp[0]})', True, tmp[2] + 2
                    else:
                        return f'{rt.v.sym()}{tmp[0]}', True, tmp[2] + 1
                else:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        return f'{rt.v.sym()}({tmp[0]})', False, tmp[2] + 3
                    else:
                        return f'{rt.v.sym()}{tmp[0]}', False, tmp[2] + 1
            elif rt.v == Unary.Trans:
                tmp: Tuple[str, bool,
                           int] = self.__str_pos_hlpr(rt.chd[0], target)

                if rt == target:
                    if type(rt.chd[0]) == Token.Op and rt.precd_in > rt.chd[0].precd_in and \
                            rt.chd[0].v != Delimiter.Idx:
                        return f'({tmp[0]})\'', True, tmp[2] + 2
                    else:
                        return f'{tmp[0]}\'', True, tmp[2]
                elif tmp[1]:
                    if type(rt.chd[0]) == Token.Op and rt.precd_in > rt.chd[0].precd_in and \
                            rt.chd[0].v != Delimiter.Idx:
                        return f'({tmp[0]})\'', True, tmp[2] + 1
                    else:
                        return f'{tmp[0]}\'', True, tmp[2]
                else:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        return f'({tmp[0]})\'', False, tmp[2] + 3
                    else:
                        return f'{tmp[0]}\'', False, tmp[2] + 1
            elif rt.v == Delimiter.Seq:
                tmp_1: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[0], target)
                tmp_2: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[1], target)

                if rt == target:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}):'
                        pos: int = tmp_1[2] + 2
                    else:
                        buf: str = f'{tmp_1[0]}:'
                        pos: int = tmp_1[2]

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_1[1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}):'
                        pos: int = tmp_1[2] + 1
                    else:
                        buf: str = f'{tmp_1[0]}:'
                        pos: int = tmp_1[2]

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_2[1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}):'
                    else:
                        buf: str = f'{tmp_1[0]}:'

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        pos: int = len(buf) + tmp_2[2] + 1
                        buf += f'({tmp_2[0]})'
                    else:
                        pos: int = len(buf) + tmp_2[2]
                        buf += tmp_2[0]

                    return buf, True, pos
                else:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}):'
                    else:
                        buf: str = f'{tmp_1[0]}:'

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, False, len(buf)
            elif rt.v == Delimiter.Idx:
                tmp_l: List[Tuple[str, bool, int]] = [
                    self.__str_pos_hlpr(tok, target) for tok in rt.chd
                ]

                if rt == target:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_l[0][0]})['
                        pos: int = tmp_l[0][2] + 2
                    else:
                        buf: str = f'{tmp_l[0][0]}['
                        pos: int = tmp_l[0][2]

                    return buf + ', '.join([tmp[0] for tmp in tmp_l[1:]
                                            ]) + ']', True, pos
                elif tmp_l[0][1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_l[0][0]})['
                        pos: int = tmp_l[0][2] + 1
                    else:
                        buf: str = f'{tmp_l[0][0]}['
                        pos: int = tmp_l[0][2]

                    return buf + ', '.join([tmp[0] for tmp in tmp_l[1:]
                                            ]) + ']', True, pos

                if type(rt.chd[0]
                        ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                    buf: str = f'({tmp_l[0][0]})['
                else:
                    buf: str = f'{tmp_l[0][0]}['

                pos: int = len(buf)
                i: int = 1

                while i < len(tmp_l) and not tmp_l[i][1]:
                    pos += tmp_l[i][2] + 2
                    i += 1

                if i == len(tmp_l):
                    return buf + ', '.join([
                        tmp[0] for tmp in tmp_l[1:]
                    ]) + ']', False, pos - 1 if i > 1 else pos + 1
                else:
                    return buf + ', '.join([tmp[0] for tmp in tmp_l[1:]
                                            ]) + ']', True, pos
            else:
                tmp_1: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[0], target)
                tmp_2: Tuple[str, bool,
                             int] = self.__str_pos_hlpr(rt.chd[1], target)

                if rt == target:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                        pos: int = tmp_1[2] + 3
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '
                        pos: int = tmp_1[2] + 1

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_1[1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                        pos: int = tmp_1[2] + 1
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '
                        pos: int = tmp_1[2]

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, True, pos
                elif tmp_2[1]:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        pos: int = len(buf) + tmp_2[2] + 1
                        buf += f'({tmp_2[0]})'
                    else:
                        pos: int = len(buf) + tmp_2[2]
                        buf += tmp_2[0]

                    return buf, True, pos
                else:
                    if type(rt.chd[0]
                            ) == Token.Op and rt.precd_in > rt.chd[0].precd_in:
                        buf: str = f'({tmp_1[0]}) {rt.v.sym()} '
                    else:
                        buf: str = f'{tmp_1[0]} {rt.v.sym()} '

                    if type(
                            rt.chd[1]
                    ) == Token.Op and rt.precd_in >= rt.chd[1].precd_in:
                        buf += f'({tmp_2[0]})'
                    else:
                        buf += tmp_2[0]

                    return buf, False, len(buf)
        elif tok_t == Token.Fun:
            tmp_l: List[Tuple[str, bool, int]] = [
                self.__str_pos_hlpr(tok, target) for tok in rt.chd
            ]

            if rt == target:
                return rt.v_str() + '[' + ', '.join([tmp[0] for tmp in tmp_l
                                                     ]) + ']', True, 0

            buf: str = rt.v_str() + '['
            pos: int = len(buf)
            i: int = 0

            while i < len(tmp_l) and not tmp_l[i][1]:
                pos += tmp_l[i][2] + 2
                i += 1

            print(pos)

            if i == len(tmp_l):
                return buf + ', '.join([
                    tmp[0] for tmp in tmp_l
                ]) + ']', False, pos - 1 if i > 0 else pos + 1
            else:
                return buf + ', '.join([tmp[0] for tmp in tmp_l
                                        ]) + ']', True, pos + tmp_l[i][2]
        elif tok_t == Token.List:
            tmp_l: List[Tuple[str, bool, int]] = [
                self.__str_pos_hlpr(tok, target) for tok in rt.chd
            ]

            if rt == target:
                return '{' + ', '.join([tmp[0]
                                        for tmp in tmp_l]) + '}', True, 0

            buf: str = '{'
            pos: int = 1
            i: int = 0

            while i < len(tmp_l) and not tmp_l[i][1]:
                pos += tmp_l[i][2] + 2
                i += 1

            if i == len(tmp_l):
                return buf + ', '.join([
                    tmp[0] for tmp in tmp_l
                ]) + '}', False, pos - 1 if i > 0 else pos + 1
            else:
                return buf + ', '.join([tmp[0]
                                        for tmp in tmp_l]) + '}', True, pos
        else:
            buf: str = rt.v_str()

            return (buf, True, 0) if rt == target else (buf, False, len(buf))
Example #11
0
    def __chk_t_hlpr(self, rt: Token.Tok, t_env: Dict[int, TypeSystem.T]) -> Dict[int, TypeSystem.T]:
        """
        Check type of partial AST.

        Usually, type checking is quite tricky logic.
        For example, Hindley-Milner let type system needs unification algorithms for type checking.
        But since grammar of math expression is simple, type checking logic is relatively simple.

        It just calls corresponding type checking methods by looking up the value of root token.
        After checking type, it assign inferred type of root token as its field value.
        For concept of Hindley-Milner let type system and unification algorithm, consult the references below.

        This method is private and called internally as a helper of ``Interp.__chk_t``.

        **Reference**
            * https://en.wikipedia.org/wiki/Hindley–Milner_type_system
            * https://en.wikipedia.org/wiki/Unification_(computer_science)

        :param rt: Root of partial AST to be typed checked.
        :type rt: Token.Tok
        """
        tok_t: type = type(rt)

        if tok_t == Token.Num:
            rt.t = TypeSystem.Cmplx.inst() if type(rt.v) == complex else TypeSystem.Real.inst()

            return t_env
        elif tok_t == Token.Str:
            rt.t = TypeSystem.Str.inst()

            return t_env
        elif tok_t == Token.Bool:
            rt.t = TypeSystem.Bool.inst()

            return t_env
        elif tok_t == Token.Void:
            rt.t = TypeSystem.Void.inst()

            return t_env
        elif tok_t == Token.Var:
            # find: TypeSystem.T = t_env.get(rt.v)

            rt.t = TypeSystem.Sym.inst()

            return t_env
        elif tok_t == Token.List:
            chd_t: List[TypeSystem.T] = []

            for tok in rt.chd:
                t_env = self.__chk_t_hlpr(tok, t_env)
                chd_t.append(tok.t)

            res_t: TypeSystem.T = TypeSystem.ArrFact.inst().get_arr_t(chd_t)

            if not res_t:
                raise Exception('type error')

            rt.t = res_t

            return t_env
        elif tok_t == Token.Op:
            for tok in rt.chd:
                t_env = self.__chk_t_hlpr(tok, t_env)

            t_env = rt.v.chk_t(rt, t_env)

            if not t_env:
                raise InterpreterError.TErr(23, *self.__expr.str_pos(rt), rt, rt.v.sgn(), rt.v.__name__.upper())

            return t_env
        else:
            for tok in rt.chd:
                t_env = self.__chk_t_hlpr(tok, t_env)

            rt.t = TypeSystem.Sym()

            return t_env