def transform(self, expr):
     unary_expr = expr
     if unary_expr.operator == "!":
         self.main.process_expression(expr)
         type = unary_expr.operand.actual_type
         lit_types = self.main.current_file.literal_types
         if isinstance(type, astTypes.ClassType) and type.decl != lit_types.boolean.decl and type.decl != lit_types.numeric.decl:
             return exprs.BinaryExpression(unary_expr.operand, "==", exprs.NullLiteral())
     
     return expr
    def unary_prehook(self):
        if self.reader.read_token("null"):
            return exprs.NullLiteral()
        elif self.reader.read_token("true"):
            return exprs.BooleanLiteral(True)
        elif self.reader.read_token("false"):
            return exprs.BooleanLiteral(False)
        elif self.reader.read_token("`"):
            parts = []
            lit_part = ""
            while True:
                if self.reader.read_exactly("`"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    break
                elif self.reader.read_exactly("${"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    expr = self.parse_expression()
                    parts.append(exprs.TemplateStringPart.expression(expr))
                    self.reader.expect_token("}")
                elif self.allow_dollar_ids and self.reader.read_exactly("$"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    id = self.reader.read_identifier()
                    parts.append(
                        exprs.TemplateStringPart.expression(
                            exprs.Identifier(id)))
                elif self.reader.read_exactly("\\"):
                    chr = self.reader.read_char()
                    if chr == "n":
                        lit_part += "\n"
                    elif chr == "r":
                        lit_part += "\r"
                    elif chr == "t":
                        lit_part += "\t"
                    elif chr == "`":
                        lit_part += "`"
                    elif chr == "$":
                        lit_part += "$"
                    elif chr == "\\":
                        lit_part += "\\"
                    else:
                        self.reader.fail("invalid escape",
                                         self.reader.offset - 1)
                else:
                    chr = self.reader.read_char()
                    chr_code = ord(chr[0])
                    if not (32 <= chr_code
                            and chr_code <= 126) or chr == "`" or chr == "\\":
                        self.reader.fail(
                            f'''not allowed character (code={chr_code})''',
                            self.reader.offset - 1)
                    lit_part += chr
            return exprs.TemplateString(parts)
        elif self.reader.read_token("new"):
            type = self.parse_type()
            if isinstance(type, astTypes.UnresolvedType):
                self.reader.expect_token("(")
                args = self.expression_parser.parse_call_arguments()
                return exprs.UnresolvedNewExpression(type, args)
            else:
                raise Error(
                    f'''[TypeScriptParser2] Expected UnresolvedType here!''')
        elif self.reader.read_token("<"):
            new_type = self.parse_type()
            self.reader.expect_token(">")
            expression = self.parse_expression()
            return exprs.CastExpression(new_type, expression)
        elif self.reader.read_token("/"):
            pattern = ""
            while True:
                chr = self.reader.read_char()
                if chr == "\\":
                    chr2 = self.reader.read_char()
                    pattern += "/" if chr2 == "/" else "\\" + chr2
                elif chr == "/":
                    break
                else:
                    pattern += chr
            modifiers = self.reader.read_modifiers(["g", "i"])
            return exprs.RegexLiteral(pattern, "i" in modifiers, "g"
                                      in modifiers)
        elif self.reader.read_token("typeof"):
            expr = self.expression_parser.parse(
                self.expression_parser.prefix_precedence)
            self.reader.expect_token("===")
            check = self.reader.expect_string()

            ts_type = None
            if check == "string":
                ts_type = "TsString"
            elif check == "boolean":
                ts_type = "TsBoolean"
            elif check == "object":
                ts_type = "Object"
            elif check == "function":
                # TODO: ???
                ts_type = "Function"
            elif check == "undefined":
                # TODO: ???
                ts_type = "Object"
            else:
                self.reader.fail("unexpected typeof comparison")

            return exprs.InstanceOfExpression(
                expr, astTypes.UnresolvedType(ts_type, []))
        elif self.reader.peek_regex("\\([A-Za-z0-9_]+\\s*[:,]|\\(\\)") != None:
            params = self.parse_lambda_params()
            self.reader.expect_token("=>")
            block = self.parse_lambda_block()
            return types.Lambda(params, block)
        elif self.reader.read_token("await"):
            expression = self.parse_expression()
            return exprs.AwaitExpression(expression)

        map_literal = self.expression_parser.parse_map_literal()
        if map_literal != None:
            return map_literal

        array_literal = self.expression_parser.parse_array_literal()
        if array_literal != None:
            return array_literal

        return None