Beispiel #1
0
 def syn_idx_Unary_Name_constructor(cls, ctx, e, inc_idx):
     id = e.operand.id
     if id != "Inf":
         raise _errors.TyError("Invalid ieee literal.", e)
     if not isinstance(e.op, (ast.UAdd, ast.USub)):
         raise _errors.TyError("Invalid unary operator on ieee literal.", e)
     return ()
Beispiel #2
0
    def _setup_args(ctx, args, arg_types, tree):
        # var and kw args are not supported
        if args.vararg:
            raise _errors.TyError("Varargs are not supported.", args.vararg)
        if args.kwarg:
            raise _errors.TyError("Kwargs are not supported.", args.kwarg)
        if len(args.defaults) != 0:
            raise _errors.TyError("Defaults are not supported.", tree)

        variables = ctx.variables
        arguments = args.args
        n_args, n_arg_types = len(arguments), len(arg_types)
        if n_args != n_arg_types:
            raise _errors.TyError(
                "Type specifies {0} arguments but function has {1}.".format(
                    n_arg_types, n_args), 
                tree)
        for arg, arg_type in zip(arguments, arg_types):
            if not isinstance(arg, ast.Name):
                raise _errors.TyError("Argument must be an identifier.", arg)
            arg_id = arg.id
            uniq_id = ctx.generate_fresh_id(arg_id)
            arg.uniq_id = uniq_id
            variables[arg_id] = (uniq_id, arg_type)
            yield arg_id
Beispiel #3
0
    def ana_FunctionDef(self, ctx, tree):
        if not hasattr(tree, '_post_docstring_body'):
            self.preprocess_FunctionDef(tree)
        
        args = tree.args
        body = tree._post_docstring_body
        (arg_types, return_type) = self.idx

        tree.uniq_id = fn._setup_recursive_fn(ctx, self, tree.name)
        arg_names = tuple(fn._setup_args(ctx, args, arg_types, tree))

        if len(body) > 0:
            sig_idx = fn._process_function_signature(
                body[0], arg_names, ctx.fn.static_env)
            if sig_idx is not None:
                if (sig_idx[0] != arg_types) \
                        or (sig_idx[1] != Ellipsis 
                            and sig_idx[1] != return_type):
                    raise _errors.TyError(
                        "Function signature and ascription do not match.", 
                        body[0])
                body = tree._post_sig_body = body[1:]
            else:
                tree._post_sig_body = body

        if len(body) == 0:
            raise _errors.TyError("Function body is empty.", tree)

        body_block = tree.body_block = Block.from_stmts(body)
        body_block.ana(ctx, return_type)
Beispiel #4
0
    def ana_pat_Dict(self, ctx, pat):
        keys, values = pat.keys, pat.values
        idx = self.idx
        n_keys, n_idx = len(keys), len(idx)
        if n_keys < n_idx:
            raise _errors.TyError("Too few elements in pattern.", pat)
        elif n_keys > n_idx:
            raise _errors.TyError("Too many elements in pattern.", keys[n_idx])

        used_labels = set()
        bindings = _util.odict()
        n_bindings = 0
        for key, value in zip(keys, values):
            label = _read_label(key)
            if label in used_labels:
                raise _errors.TyError("Duplicate label: " + str(label), key)
            used_labels.add(label)
            key.label = label

            try:
                ty = idx[label]
            except KeyError:
                raise _errors.TyError("Invalid label: " + str(label), key)
            elt_bindings = ctx.ana_pat(value, ty)
            n_elt_bindings = len(elt_bindings)
            bindings.update(elt_bindings)
            n_bindings_new = len(bindings)
            if n_bindings_new != n_bindings + n_elt_bindings:
                raise _errors.TyError("Duplicate variable in pattern.", pat)
            n_bindings = n_bindings_new

        return bindings
Beispiel #5
0
 def ana_pat_Unary_Name_constructor(self, ctx, pat):
     id = pat.operand.id
     if id != "Inf":
         raise _errors.TyError("Invalid ieee literal pattern.", pat)
     if not isinstance(pat.op, (ast.UAdd, ast.USub)):
         raise _errors.TyError(
             "Invalid unary operator on ieee literal pattern.", pat)
     return _util.odict()
Beispiel #6
0
    def ana_Name_constructor(self, ctx, e):
        idx = self.idx
        lbl = e.id

        try:
            ty = idx[lbl]
        except KeyError:
            raise _errors.TyError("Label not found in finsum: " + lbl, e)
        if ty != _product.unit:
            raise _errors.TyError(
                "Label has non-unit type but no payload was applied: " + lbl,
                e)
Beispiel #7
0
    def ana_Tuple(self, ctx, e):
        elts = e.elts
        idx = self.idx

        n_elts, n_idx = len(elts), len(idx)
        if n_elts < n_idx:
            raise _errors.TyError("Too few components provided.", e)
        elif n_elts > n_idx:
            raise _errors.TyError("Too many components provided.", elts[n_idx])

        for elt, ty in zip(elts, idx.itervalues()):
            ctx.ana(elt, ty)
Beispiel #8
0
    def ana_pat_Name_constructor(self, ctx, pat):
        idx = self.idx
        lbl = pat.id

        try:
            ty = idx[lbl]
        except KeyError:
            raise _errors.TyError("Label not found in finsum: " + lbl, pat)
        if ty != _product.unit:
            raise _errors.TyError(
                "Label has non-unit type but no payload pattern was applied: "
                + lbl, pat)
        return _util.odict()
Beispiel #9
0
 def syn_Subscript(self, ctx, e):
     slice_ = e.slice
     if not isinstance(slice_, ast.Index):
         raise _errors.TyError("Must provide a single label.", slice_)
     value = slice_.value
     label = _read_label(value)
     try:
         ty = self.idx[label]
     except KeyError:
         raise _errors.TyError(
             "Cannot project component labeled " + str(label), e)
     value.label = label
     return ty
Beispiel #10
0
    def syn_idx_FunctionDef(cls, ctx, tree, inc_idx):
        if not hasattr(tree, '_post_docstring_body'):
            cls.preprocess_FunctionDef(tree)
        
        args = tree.args 
        body = tree._post_docstring_body

        if len(body) > 0:
            arg_names = astx._get_arg_names(args)
            sig_idx = cls._process_function_signature(body[0], arg_names, 
                                                      ctx.fn.static_env)
            if inc_idx == Ellipsis:
                if sig_idx is None:
                    if len(arg_names) == 0:
                        inc_idx = ((), Ellipsis)
                        tree._post_sig_body = body
                    else:
                        raise _errors.TyError("Missing argument signature.", 
                                             tree)
                else:
                    inc_idx = sig_idx
                    body = tree._post_sig_body = body[1:]
            else:
                if sig_idx is None:
                    tree._post_sig_body = body
                else:
                    if inc_idx[0] != sig_idx[0]:
                        raise _errors.TyError(
                            "Argument signature and ascription do not match.",
                            body[0])
                    inc_idx = sig_idx
                    body = tree._post_sig_body = body[1:]

        if len(body) == 0:
            raise _errors.TyError("Function body is empty.", tree)

        (arg_types, return_type) = inc_idx
        if return_type != Ellipsis:
            fn_ty = cls[arg_types, return_type]
        else:
            fn_ty = None
        tree.uniq_id = cls._setup_recursive_fn(ctx, fn_ty, tree.name)
        tuple(cls._setup_args(ctx, args, arg_types, tree))
        
        body_block = tree.body_block = Block.from_stmts(body)
        if return_type == Ellipsis:
            return_type = body_block.syn(ctx)
        else:
            body_block.ana(ctx, return_type)

        return (arg_types, return_type)
Beispiel #11
0
 def check_valid_function_def(cls, stmt):
     if isinstance(stmt, ast.FunctionDef):
         if cls._check_valid_args(stmt.args):
             decorator_list = stmt.decorator_list
             if len(decorator_list) == 0:
                 stmt.asc_ast = None 
                 return True
             elif len(decorator_list) == 1:
                 stmt.asc_ast = decorator_list[0]
                 return True
             else:
                 raise _errors.TyError(
                     """Too many decorators.""", stmt)
     raise _errors.TyError("Not a function definition.", stmt)
Beispiel #12
0
    def syn_BinOp(self, ctx, e):
        if isinstance(
                e.op,
            (ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd)):
            raise _errors.TyError(
                "Cannot use bitwise operators on cplx values.", e)
        if isinstance(e.op, ast.Mod):
            raise _errors.TyError(
                "Cannot take the modulus of a complex number.", e)

        right = e.right
        ctx.ana(right, self)

        return self
Beispiel #13
0
 def syn_Compare(self, ctx, e):
     left, ops, comparators = e.left, e.ops, e.comparators
     for op in ops:
         if isinstance(op, (ast.Lt, ast.LtE, ast.Gt, ast.GtE)):
             raise _errors.TyError(
                 "No ordering relation on complex numbers.", e)
         elif isinstance(op, (ast.In, ast.NotIn)):
             raise _errors.TyError(
                 "Type complex does not support this operator.", op)
     for e_ in _util.tpl_cons(left, comparators):
         if hasattr(e_, 'match'):
             continue  # already synthesized
         ctx.ana(e_, self)
     return _boolean.boolean
Beispiel #14
0
 def syn_UnaryOp(self, ctx, e):
     if isinstance(e.op, ast.Not):
         return self
     else:
         raise _errors.TyError(
             """Type bool does not support this unary operator.""",
             e)
Beispiel #15
0
 def _check_valid_args(cls, args):
     if (args.vararg is not None 
             or args.kwarg is not None
             or len(args.defaults) != 0):
         raise _errors.TyError(
             "Invalid function argument format.", args)
     return True
Beispiel #16
0
 def syn_BinOp(self, ctx, e):
     op = e.op
     if isinstance(op, ast.Add):
         ctx.ana(e.right, self)
         return self
     else:
         raise _errors.TyError("Invalid binary operator on strings.", e)
Beispiel #17
0
 def syn_idx_Name_constructor(cls, ctx, e, inc_idx):
     id = e.id
     if id != "True" and id != "False":
         raise _errors.TyError(
             "Must introduce a value of boolean type with either True or False.",
             e)
     return ()
Beispiel #18
0
    def syn_Compare(self, ctx, e):
        left, ops, comparators = e.left, e.ops, e.comparators
        for op in ops:
            if isinstance(op, (ast.Eq, ast.NotEq)):
                if not len(self.idx) == 0:
                    raise _errors.TyError(
                        "Can only compare unit values for equality.", e)
            elif not isinstance(op, (ast.Is, ast.IsNot)):
                raise _errors.TyError("Invalid comparison operator.", op)

        for e_ in _util.tpl_cons(left, comparators):
            if hasattr(e_, "match"):
                continue  # already synthesized
            ctx.ana(e_, self)

        return _boolean.boolean
Beispiel #19
0
 def syn_idx_Num(cls, ctx, e, inc_idx):
     n = e.n
     if isinstance(n, (int, long)):
         return ()
     else:
         raise _errors.TyError("Expression is not an int or long literal.",
                               e)
Beispiel #20
0
 def _yield_items(stmts):
     match_head = None
     match_rules = None
     for stmt in stmts:
         if match_head is not None:
             if (isinstance(stmt, ast.With) and
                     not BlockWithBinding.is_with_binding(stmt)):
                 if stmt.optional_vars is not None:
                     raise _errors.TyError("Invalid rule form.", stmt)
                 match_rules.append(stmt)
                 continue
             else:
                 if len(match_rules) == 0:
                     raise _errors.TyError(
                         "No match rules.", match_head)
                 yield BlockMatchExpr(match_head, match_rules)
                 match_head = match_rules = None
                 # falls through below
         if match_head is None:
             if isinstance(stmt, ast.Expr):
                 if BlockMatchExpr.is_match_head(stmt):
                     match_head = stmt
                     match_rules = []
                 else:
                     yield BlockExprExpr(stmt)
             elif isinstance(stmt, ast.With):
                 if (BlockWithBinding.is_with_binding(stmt)):
                     yield BlockWithBinding(stmt)
                 else:
                     raise _errors.TyError("Invalid with form.", stmt)
             elif isinstance(stmt, ast.Assign):
                 yield BlockLet(stmt)
             elif isinstance(stmt, ast.If):
                 yield BlockIfExpr(stmt)
             elif isinstance(stmt, ast.Pass):
                 yield BlockPassExpr(stmt)
             elif isinstance(stmt, ast.FunctionDef):
                 if BlockFunctionDefExpr.check_valid_function_def(stmt):
                     yield BlockFunctionDefExpr(stmt)
             else:
                 raise _errors.TyError("Statement form not supported.", stmt)
     # finish making match expression at the end of the block if necessary
     if match_head is not None:
         if len(match_rules) == 0:
             raise _errors.TyError(
                 "No match rules.", match_head)
         yield BlockMatchExpr(match_head, match_rules)
Beispiel #21
0
 def syn_Attribute(self, ctx, e):
     attr = e.attr
     if attr == "real" or attr == "imag":
         return ieee
     elif attr == "conjugate":
         return _fn.fn[(), self]
     else:
         raise _errors.TyError("Invalid attribute: " + attr, e)
Beispiel #22
0
 def syn_Subscript(self, ctx, e):
     slice_ = e.slice 
     if isinstance(slice_, ast.Ellipsis):
         raise _errors.TyError("stringing slice cannot be an Ellipsis.", e)
     elif isinstance(slice_, ast.ExtSlice):
         raise _errors.TyError("stringing slice can only have one dimension.", e)
     elif isinstance(slice_, ast.Index):
         ctx.ana(slice_.value, _numeric.num)
     else: # if isinstance(slice_, ast.Slice):
         lower, upper, step = slice_.lower, slice_.upper, slice_.step
         if lower is not None:
             ctx.ana(lower, _numeric.num)
         if upper is not None:
             ctx.ana(upper, _numeric.num)
         if not _is_None(step):
             ctx.ana(step, _numeric.num)
     return self
Beispiel #23
0
 def _is_ascribed_match_head(cls, e):
     if isinstance(e, ast.Subscript):
         value = e.value
         if cls._is_unascribed_match_head(value):
             slice = e.slice
             if isinstance(slice, ast.Slice):
                 lower, upper, step = slice.lower, slice.upper, slice.step
                 if lower is None and upper is not None and step is None:
                     e.is_match_head = True
                     e.scrutinee = value.scrutinee
                     e.asc_ast = upper
                     return True
                 else:
                     raise _errors.TyError("Invalid ascription format.", slice)
             else:
                 raise _errors.TyError("Invalid ascription format.", slice)
     return False
Beispiel #24
0
 def ana_pat_Tuple(self, ctx, pat):
     elts = pat.elts
     if len(elts) != 2:
         raise _errors.TyError(
             "Using a tuple pattern for a value of type cplx requires two elements.",
             pat)
     rl, im = elts[0], elts[1]
     rl_bindings = ctx.ana_pat(rl, ieee)
     im_bindings = ctx.ana_pat(im, ieee)
     n_rl_bindings = len(rl_bindings)
     n_im_bindings = len(im_bindings)
     bindings = _util.odict(rl_bindings)
     bindings.update(im_bindings)
     n_bindings = len(bindings)
     if n_bindings != n_rl_bindings + n_im_bindings:
         raise _errors.TyError("Duplicated variables in pattern.", pat)
     return bindings
Beispiel #25
0
 def syn_BinOp(self, ctx, e):
     if isinstance(
             e.op,
         (ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd)):
         raise _errors.TyError(
             "Cannot use bitwise operators on ieee values.", e)
     ctx.ana(e.right, self)
     return self
Beispiel #26
0
 def syn_Attribute(self, ctx, e):
     attr = e.attr
     if attr == 'f':
         return ieee
     elif attr == 'c':
         return cplx
     else:
         raise _errors.TyError("Invalid attribute.", e)
Beispiel #27
0
def _read_label(key):
    if isinstance(key, ast.Name):
        return key.id
    elif isinstance(key, ast.Num):
        n = key.n
        if isinstance(n, (int, long)) and n >= 0:
            return n
        else:
            raise _errors.TyError("Invalid numeric label.", key)
    elif isinstance(key, ast.Str):
        s = key.s
        if s != "":
            return s
        else:
            raise _errors.TyError("Invalid string label.", key)
    else:
        raise _errors.TyError("Invalid label", key)
Beispiel #28
0
 def syn_Name(cls, ctx, e):
     id = e.id
     try:
         (uniq_id, ty) = ctx.variables[id]
     except KeyError:
         raise _errors.TyError(
             "Variable not found in context: " + id, e)
     e.uniq_id = uniq_id
     return ty
Beispiel #29
0
 def from_stmts(cls, stmts):
     items = tuple(cls._yield_items(stmts))
     first_items = items[0:-1]
     last_item = items[-1]
     if not isinstance(last_item, BlockExpr):
         raise _errors.TyError(
             "Block ends with a binding.",
             last_item.stmts[0])
     return cls(first_items, last_item)
Beispiel #30
0
 def syn_Attribute(self, ctx, e):
     idx = self.idx
     attr = e.attr
     try:
         ty = idx[attr]
     except KeyError:
         raise _errors.TyError("Cannot project component labeled " + attr,
                               e)
     return ty