def tuple_type(self, node: ast.AstTupleType) -> None: super().tuple_type(node) node.type_annot = ts.TupleType.make( [elem.type_annot for elem in node.types]) if not ts.valid(node.type_annot): self.errors.add(message=f"invalid type {node.type_annot}", regions=[node.region])
def func_type(self, node: ast.AstFuncType) -> None: super().func_type(node) node.type_annot = ts.FunctionType.make( [param.type_annot for param in node.params], node.return_type.type_annot) if not ts.valid(node.type_annot): self.errors.add(message=f"invalid type {node.type_annot}", regions=[node.region])
def param(self, node: ast.AstParam) -> None: super().param(node) node.binding.type_annot = node.param_type.type_annot if not ts.valid(node.binding.type_annot): self.errors.add( message=f"invalid type {node.binding.type_annot} for parameter", regions=[node.region], )
def expr_stmt(self, node: ast.AstExprStmt) -> None: super().expr_stmt(node) if not ts.valid( node.expr.type_annot) and node.expr.type_annot != ts.VOID: self.errors.add( f"invalid expression type {node.expr.type_annot}", regions=[node.expr.region], ) if node.expr.type_annot != ts.VOID: self.errors.add( message=f"unused non-void value", regions=[node.expr.region], severity=er.Severity.WARNING, )
def func_decl(self, node: ast.AstFuncDecl) -> None: for decorator in node.decorators: decorator.accept(self) for param in node.params: param.accept(self) node.return_type.accept(self) if (not ts.valid(node.return_type.type_annot) and node.return_type.type_annot != ts.VOID): self.errors.add( message=f"invalid return type {node.return_type.type_annot}", regions=[node.return_type.region], ) node.binding.type_annot = ts.FunctionType.make( [param.binding.type_annot for param in node.params], node.return_type.type_annot, ) self.expected_returns.append(node.return_type.type_annot) node.block.accept(self) self.expected_returns.pop() node.binding.type_annot = self._apply_decorators( node.decorators, node.binding.type_annot) node.type_annot = node.binding.type_annot
def return_stmt(self, node: ast.AstReturnStmt) -> None: super().return_stmt(node) if not self.expected_returns: self.errors.add(message=f"return statement outside of function", regions=[node.region]) if node.expr: if not ts.valid(node.expr.type_annot): self.errors.add( message=f"invalid type {node.expr.type_annot} to return", regions=[node.expr.region], ) elif not ts.contains(node.expr.type_annot, self.expected_returns[-1]): self.errors.add( message=f"mismatched return type: " f"expected {self.expected_returns[-1]} but got {node.expr.type_annot}", regions=[node.expr.region], ) else: if self.expected_returns[-1] != ts.VOID: self.errors.add( message=f"missing return value in non-void function", regions=[node.region], )
def union_type(self, node: ast.AstUnionType) -> None: super().union_type(node) node.type_annot = ts.union(elem.type_annot for elem in node.types) if not ts.valid(node.type_annot) and node.type_annot != ts.VOID: self.errors.add(message=f"invalid type {node.type_annot}", regions=[node.region])
def optional_type(self, node: ast.AstOptionalType) -> None: super().optional_type(node) node.type_annot = ts.union((node.target.type_annot, ts.NIL)) if not ts.valid(node.type_annot): self.errors.add(message=f"invalid type {node.type_annot}", regions=[node.region])