def parse_left(self, required=True):
        result = self.hooks.unary_prehook() if self.hooks != None else None
        if result != None:
            return result

        unary = self.reader.read_any_of(self.config.unary)
        if unary != None:
            right = self.parse(self.prefix_precedence)
            return exprs.UnaryExpression(exprs.UNARY_TYPE.PREFIX, unary, right)

        id = self.reader.read_identifier()
        if id != None:
            return exprs.Identifier(id)

        num = self.reader.read_number()
        if num != None:
            return exprs.NumericLiteral(num)

        str = self.reader.read_string()
        if str != None:
            return exprs.StringLiteral(str)

        if self.reader.read_token("("):
            expr = self.parse()
            self.reader.expect_token(")")
            return exprs.ParenthesizedExpression(expr)

        if required:
            self.reader.fail(
                f'''unknown (literal / unary) token in expression''')

        return None
Exemplo n.º 2
0
    def transform(self, expr):
        if isinstance(expr, exprs.BinaryExpression) and expr.operator == "||":
            lit_types = self.main.current_file.literal_types

            expr.left = self.main.run_plugins_on(expr.left)
            left_type = expr.left.get_type()

            if isinstance(expr.right, exprs.ArrayLiteral) and len(
                    expr.right.items) == 0:
                if isinstance(left_type, astTypes.ClassType
                              ) and left_type.decl == lit_types.array.decl:
                    expr.right.set_actual_type(left_type)
                    return exprs.NullCoalesceExpression(expr.left, expr.right)

            if isinstance(expr.right, exprs.MapLiteral) and len(
                    expr.right.items) == 0:
                if isinstance(left_type, astTypes.ClassType
                              ) and left_type.decl == lit_types.map.decl:
                    expr.right.set_actual_type(left_type)
                    return exprs.NullCoalesceExpression(expr.left, expr.right)

            expr.right = self.main.run_plugins_on(expr.right)
            right_type = expr.right.get_type()

            if isinstance(expr.right, exprs.NullLiteral):
                # something-which-can-be-undefined || null
                return expr.left
            elif astTypes.TypeHelper.is_assignable_to(
                    right_type, left_type) and not astTypes.TypeHelper.equals(
                        right_type,
                        self.main.current_file.literal_types.boolean):
                return exprs.NullCoalesceExpression(expr.left, expr.right)
        return expr
    def parse_map_literal(self,
                          key_separator=":",
                          start_token="{",
                          end_token="}"):
        if not self.reader.read_token(start_token):
            return None

        items = []
        while True:
            if self.reader.peek_token(end_token):
                break

            name = self.reader.read_string()
            if name == None:
                name = self.reader.expect_identifier(
                    "expected string or identifier as map key")

            self.reader.expect_token(key_separator)
            initializer = self.parse()
            items.append(exprs.MapLiteralItem(name, initializer))
            if not (self.reader.read_token(",")):
                break

        self.reader.expect_token(end_token)
        return exprs.MapLiteral(items)
 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
Exemplo n.º 5
0
    def visit_expression(self, expr):
        orig_expr = expr

        expr = super().visit_expression(expr)

        if isinstance(expr, exprs.BinaryExpression) and expr.operator == "in":
            expr = exprs.UnresolvedCallExpression(
                exprs.PropertyAccessExpression(expr.right, "hasKey"), [],
                [expr.left])

        expr.parent_node = orig_expr.parent_node
        return expr
    def transform_method_call(self, expr):
        if isinstance(expr.object, refs.ClassReference) or isinstance(
                expr.object, refs.StaticThisReference):
            cls_ = expr.object.decl if isinstance(
                expr.object,
                refs.ClassReference) else expr.object.cls_ if isinstance(
                    expr.object, refs.StaticThisReference) else None
            method = self.find_method(cls_, expr.method_name, True, expr.args)
            result = exprs.StaticMethodCallExpression(
                method, expr.type_args, expr.args,
                isinstance(expr.object, refs.StaticThisReference))
            self.resolve_return_type(result, genRes.GenericsResolver())
            return result
        else:
            resolved_object = expr.object if expr.object.actual_type != None else self.main.run_plugins_on(
                expr.object)
            object_type = resolved_object.get_type()
            intf_type = object_type.decl if isinstance(
                object_type,
                astTypes.ClassType) else object_type.decl if isinstance(
                    object_type, astTypes.InterfaceType) else None

            if intf_type != None:
                lambda_field = next(
                    filter(
                        lambda x: x.name == expr.method_name and isinstance(
                            x.type, astTypes.LambdaType) and len(
                                x.type.parameters) == len(expr.args),
                        intf_type.fields), None)
                if lambda_field != None:
                    lambda_call = exprs.LambdaCallExpression(
                        refs.InstanceFieldReference(expr.object, lambda_field),
                        expr.args)
                    lambda_call.set_actual_type(
                        (lambda_field.type).return_type, True)
                    return lambda_call

                method = self.find_method(intf_type, expr.method_name, False,
                                          expr.args)
                result = exprs.InstanceMethodCallExpression(
                    resolved_object, method, expr.type_args, expr.args)
                self.resolve_return_type(
                    result,
                    genRes.GenericsResolver.from_object(resolved_object))
                return result
            elif isinstance(object_type, astTypes.AnyType):
                expr.set_actual_type(astTypes.AnyType.instance)
                return expr
            else:
                pass
            return resolved_object
 def infix_prehook(self, left):
     if isinstance(
             left, exprs.PropertyAccessExpression
     ) and self.reader.peek_regex("<[A-Za-z0-9_<>]*?>\\(") != None:
         type_args = self.parse_type_args()
         self.reader.expect_token("(")
         args = self.expression_parser.parse_call_arguments()
         return exprs.UnresolvedCallExpression(left, type_args, args)
     elif self.reader.read_token("instanceof"):
         type = self.parse_type()
         return exprs.InstanceOfExpression(left, type)
     elif isinstance(left,
                     exprs.Identifier) and self.reader.read_token("=>"):
         block = self.parse_lambda_block()
         return types.Lambda(
             [types.MethodParameter(left.text, None, None, None)], block)
     return None
 def visit_expression(self, expr):
     expr = super().visit_expression(expr)
     if isinstance(expr, exprs.UnresolvedCallExpression) and isinstance(
             expr.func, exprs.PropertyAccessExpression):
         return exprs.UnresolvedMethodCallExpression(
             expr.func.object, expr.func.property_name, expr.type_args,
             expr.args)
     return expr
    def parse(self, precedence=0, required=True):
        self.reader.skip_whitespace()
        left_start = self.reader.offset
        left = self.parse_left(required)
        if left == None:
            return None
        self.add_node(left, left_start)

        while True:
            if self.hooks != None:
                parsed = self.hooks.infix_prehook(left)
                if parsed != None:
                    left = parsed
                    self.add_node(left, left_start)
                    continue

            op = self.parse_operator()
            if op == None or op.precedence <= precedence:
                break
            self.reader.expect_token(op.text)
            op_text = self.config.aliases.get(
                op.text) if op.text in self.config.aliases else op.text

            if op.is_binary:
                right = self.parse(op.precedence -
                                   1 if op.is_right_assoc else op.precedence)
                left = exprs.BinaryExpression(left, op_text, right)
            elif op.is_postfix:
                left = exprs.UnaryExpression(exprs.UNARY_TYPE.POSTFIX, op_text,
                                             left)
            elif op.text == "?":
                when_true = self.parse()
                self.reader.expect_token(":")
                when_false = self.parse(op.precedence - 1)
                left = exprs.ConditionalExpression(left, when_true, when_false)
            elif op.text == "(":
                args = self.parse_call_arguments()
                left = exprs.UnresolvedCallExpression(left, [], args)
            elif op.text == "[":
                element_expr = self.parse()
                self.reader.expect_token("]")
                left = exprs.ElementAccessExpression(left, element_expr)
            elif op.text in self.config.property_access_ops:
                prop = self.reader.expect_identifier(
                    "expected identifier as property name")
                left = exprs.PropertyAccessExpression(left, prop)
            else:
                self.reader.fail(
                    f'''parsing \'{op.text}\' is not yet implemented''')

            self.add_node(left, left_start)

        if isinstance(left, exprs.ParenthesizedExpression) and isinstance(
                left.expression, exprs.Identifier):
            expr = self.parse(0, False)
            if expr != None:
                return exprs.CastExpression(
                    astTypes.UnresolvedType(left.expression.text, []), expr)

        return left
Exemplo n.º 10
0
 def transform(self, expr):
     call_expr = expr
     if isinstance(call_expr.func, refs.GlobalFunctionReference):
         new_expr = exprs.GlobalFunctionCallExpression(
             call_expr.func.decl, call_expr.args)
         call_expr.args = list(
             map(lambda arg: self.main.run_plugins_on(arg), call_expr.args))
         new_expr.set_actual_type(call_expr.func.decl.returns)
         return new_expr
     else:
         self.main.process_expression(expr)
         if isinstance(call_expr.func.actual_type, astTypes.LambdaType):
             new_expr = exprs.LambdaCallExpression(call_expr.func,
                                                   call_expr.args)
             new_expr.set_actual_type(
                 call_expr.func.actual_type.return_type)
             return new_expr
         else:
             return expr
 def transform(self, expr):
     # TODO: convert ElementAccess to ElementGet and ElementSet expressions
     if isinstance(expr, exprs.BinaryExpression) and isinstance(
             expr.left, exprs.ElementAccessExpression):
         expr.left.object = self.main.run_plugins_on(expr.left.object)
         if self.is_map_or_array_type(expr.left.object.get_type()):
             #const right = expr.operator === "=" ? expr.right : new BinaryExpression(<Expression>expr.left.clone(), expr.operator === "+=" ? "+" : "-", expr.right);
             return exprs.UnresolvedMethodCallExpression(
                 expr.left.object, "set", [],
                 [expr.left.element_expr, expr.right])
     elif isinstance(expr, exprs.ElementAccessExpression):
         expr.object = self.main.run_plugins_on(expr.object)
         if self.is_map_or_array_type(expr.object.get_type()):
             return exprs.UnresolvedMethodCallExpression(
                 expr.object, "get", [], [expr.element_expr])
         elif isinstance(expr.element_expr, exprs.StringLiteral):
             return exprs.PropertyAccessExpression(
                 expr.object, expr.element_expr.string_value)
     return expr
Exemplo n.º 12
0
 def visit_expression(self, expr):
     if isinstance(expr, exprs.UnresolvedNewExpression):
         cls_type = self.visit_type(expr.cls_)
         if isinstance(cls_type, astTypes.ClassType):
             new_expr = exprs.NewExpression(cls_type, expr.args)
             new_expr.parent_node = expr.parent_node
             super().visit_expression(new_expr)
             return new_expr
         else:
             self.error_man.throw(
                 f'''Excepted ClassType, but got {cls_type}''')
             return expr
     else:
         return super().visit_expression(expr)
    def parse_array_literal(self, start_token="[", end_token="]"):
        if not self.reader.read_token(start_token):
            return None

        items = []
        if not self.reader.read_token(end_token):
            while True:
                item = self.parse()
                items.append(item)
                if not (self.reader.read_token(",")):
                    break

            self.reader.expect_token(end_token)
        return exprs.ArrayLiteral(items)
Exemplo n.º 14
0
 def parse_block(self, indent_len = 0):
     block = nodes.TemplateBlock([])
     indent_man = BlockIndentManager(block, indent_len)
     while not self.reader.get_eof():
         if self.reader.peek_exactly("{{/"):
             break
         if self.reader.read_exactly("${"):
             expr = self.parser.parse_expression()
             block.items.append(nodes.ExpressionNode(expr))
             self.reader.expect_token("}")
         elif self.reader.read_exactly("$"):
             id = self.reader.expect_identifier()
             block.items.append(nodes.ExpressionNode(exprs.Identifier(id)))
         elif self.reader.read_exactly("{{"):
             block_indent_len = indent_man.remove_prev_indent()
             
             if self.reader.read_token("for"):
                 var_name = self.reader.expect_identifier()
                 self.reader.expect_token("of")
                 items_expr = self.parser.parse_expression()
                 attrs = self.parse_attributes()
                 self.reader.expect_token("}}")
                 body = self.parse_block(block_indent_len)
                 self.reader.expect_token("{{/for}}")
                 block.items.append(nodes.ForNode(var_name, items_expr, body, attrs.get("joiner")))
             else:
                 expr = self.parser.parse_expression()
                 block.items.append(nodes.ExpressionNode(expr))
                 self.reader.expect_token("}}")
         else:
             literal = self.reader.read_regex("([^\\\\]\\\\(\\{\\{|\\$)|\r|\n|(?!\\{\\{|\\$\\{|\\$).)*")[0]
             if literal == "":
                 raise Error("This should not happen!")
             block.items.append(indent_man.deindent(nodes.LiteralNode(literal)))
     
     if indent_len != 0:
         indent_man.remove_prev_indent()
     
     return block
Exemplo n.º 15
0
    def class_like(self, cls_):
        self.current_class = cls_
        res_list = []

        static_constructor_stmts = []
        complex_field_inits = []
        if isinstance(cls_, types.Class):
            field_reprs = []
            for field in cls_.fields:
                is_initializer_complex = field.initializer != None and not (
                    isinstance(field.initializer, exprs.StringLiteral)
                ) and not (isinstance(
                    field.initializer, exprs.BooleanLiteral)) and not (
                        isinstance(field.initializer, exprs.NumericLiteral))

                prefix = f'''{self.vis(field.visibility)} {self.pre_if("static ", field.is_static)}'''
                if len(field.interface_declarations) > 0:
                    init = f''' = {self.expr(field.initializer)};''' if field.initializer != None else ""
                    field_reprs.append(
                        f'''{prefix}{self.var_wo_init(field, field)} {{ get; set; }}{init}'''
                    )
                elif is_initializer_complex:
                    if field.is_static:
                        static_constructor_stmts.append(
                            stats.ExpressionStatement(
                                exprs.BinaryExpression(
                                    refs.StaticFieldReference(field), "=",
                                    field.initializer)))
                    else:
                        complex_field_inits.append(
                            stats.ExpressionStatement(
                                exprs.BinaryExpression(
                                    refs.InstanceFieldReference(
                                        refs.ThisReference(cls_), field), "=",
                                    field.initializer)))

                    field_reprs.append(
                        f'''{prefix}{self.var_wo_init(field, field)};''')
                else:
                    field_reprs.append(
                        f'''{prefix}{self.var(field, field)};''')
            res_list.append("\n".join(field_reprs))

            res_list.append("\n".join(
                list(
                    map(
                        lambda prop:
                        f'''{self.vis(prop.visibility)} {self.pre_if("static ", prop.is_static)}'''
                        + self.var_wo_init(prop, prop) +
                        (f''' {{\n    get {{\n{self.pad(self.block(prop.getter))}\n    }}\n}}'''
                         if prop.getter != None else "") +
                        (f''' {{\n    set {{\n{self.pad(self.block(prop.setter))}\n    }}\n}}'''
                         if prop.setter != None else ""), cls_.properties))))

            if len(static_constructor_stmts) > 0:
                res_list.append(
                    f'''static {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}'''
                )

            if cls_.constructor_ != None:
                constr_field_inits = []
                for field in list(
                        filter(lambda x: x.constructor_param != None,
                               cls_.fields)):
                    field_ref = refs.InstanceFieldReference(
                        refs.ThisReference(cls_), field)
                    mp_ref = refs.MethodParameterReference(
                        field.constructor_param)
                    # TODO: decide what to do with "after-TypeEngine" transformations
                    mp_ref.set_actual_type(field.type, False, False)
                    constr_field_inits.append(
                        stats.ExpressionStatement(
                            exprs.BinaryExpression(field_ref, "=", mp_ref)))

                # @java var stmts = Stream.concat(Stream.concat(constrFieldInits.stream(), complexFieldInits.stream()), ((Class)cls).constructor_.getBody().statements.stream()).toArray(Statement[]::new);
                # @java-import java.util.stream.Stream
                stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements
                res_list.append(
                    "public " +
                    self.pre_if("/* throws */ ", cls_.constructor_.throws) +
                    self.name_(cls_.name) +
                    f'''({", ".join(list(map(lambda p: self.var(p, p), cls_.constructor_.parameters)))})'''
                    +
                    (f''': base({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))})'''
                     if cls_.constructor_.super_call_args != None else "") +
                    f'''\n{{\n{self.pad(self.stmts(stmts))}\n}}''')
            elif len(complex_field_inits) > 0:
                res_list.append(
                    f'''public {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}'''
                )
        elif isinstance(cls_, types.Interface):
            res_list.append("\n".join(
                list(
                    map(
                        lambda field:
                        f'''{self.var_wo_init(field, field)} {{ get; set; }}''',
                        cls_.fields))))

        methods = []
        for method in cls_.methods:
            if isinstance(cls_, types.Class) and method.body == None:
                continue
            # declaration only
            methods.append(
                ("" if isinstance(method.parent_interface, types.Interface
                                  ) else self.vis(method.visibility) + " ") +
                self.pre_if("static ", method.is_static) + self.pre_if(
                    "virtual ", method.overrides == None
                    and len(method.overridden_by) > 0) +
                self.pre_if("override ", method.overrides != None) +
                self.pre_if("async ", method.async_) +
                self.pre_if("/* throws */ ", method.throws) +
                f'''{self.type(method.returns, False)} ''' +
                self.name_(method.name) +
                self.type_args(method.type_arguments) +
                f'''({", ".join(list(map(lambda p: self.var(p, None), method.parameters)))})'''
                +
                (f'''\n{{\n{self.pad(self.stmts(method.body.statements))}\n}}'''
                 if method.body != None else ";"))
        res_list.append("\n\n".join(methods))
        return self.pad("\n\n".join(list(filter(lambda x: x != "", res_list))))
Exemplo n.º 16
0
    def class_(self, cls_):
        self.current_class = cls_
        res_list = []

        static_constructor_stmts = []
        complex_field_inits = []
        field_reprs = []
        prop_reprs = []
        for field in cls_.fields:
            is_initializer_complex = field.initializer != None and not (
                isinstance(field.initializer, exprs.StringLiteral)) and not (
                    isinstance(field.initializer,
                               exprs.BooleanLiteral)) and not (isinstance(
                                   field.initializer, exprs.NumericLiteral))

            prefix = f'''{self.vis(field.visibility)} {self.pre_if("static ", field.is_static)}'''
            if len(field.interface_declarations) > 0:
                var_type = self.var_type(field, field)
                name = self.name_(field.name)
                pname = self.uc_first(field.name)
                set_to_false = astTypes.TypeHelper.equals(
                    field.type,
                    self.current_class.parent_file.literal_types.boolean)
                prop_reprs.append(
                    f'''{var_type} {name}{(" = false" if set_to_false else f' = {self.expr(field.initializer)}' if field.initializer != None else "")};\n'''
                    +
                    f'''{prefix}{var_type} get{pname}() {{ return this.{name}; }}\n'''
                    +
                    f'''{prefix}void set{pname}({var_type} value) {{ this.{name} = value; }}'''
                )
            elif is_initializer_complex:
                if field.is_static:
                    static_constructor_stmts.append(
                        stats.ExpressionStatement(
                            exprs.BinaryExpression(
                                refs.StaticFieldReference(field), "=",
                                field.initializer)))
                else:
                    complex_field_inits.append(
                        stats.ExpressionStatement(
                            exprs.BinaryExpression(
                                refs.InstanceFieldReference(
                                    refs.ThisReference(cls_), field), "=",
                                field.initializer)))

                field_reprs.append(
                    f'''{prefix}{self.var_wo_init(field, field)};''')
            else:
                field_reprs.append(f'''{prefix}{self.var(field, field)};''')
        res_list.append("\n".join(field_reprs))
        res_list.append("\n\n".join(prop_reprs))

        for prop in cls_.properties:
            prefix = f'''{self.vis(prop.visibility)} {self.pre_if("static ", prop.is_static)}'''
            if prop.getter != None:
                res_list.append(
                    f'''{prefix}{self.type(prop.type)} get{self.uc_first(prop.name)}(){self.block(prop.getter, False)}'''
                )

            if prop.setter != None:
                res_list.append(
                    f'''{prefix}void set{self.uc_first(prop.name)}({self.type(prop.type)} value){self.block(prop.setter, False)}'''
                )

        if len(static_constructor_stmts) > 0:
            res_list.append(
                f'''static {{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}'''
            )

        if cls_.constructor_ != None:
            constr_field_inits = []
            for field in list(
                    filter(lambda x: x.constructor_param != None,
                           cls_.fields)):
                field_ref = refs.InstanceFieldReference(
                    refs.ThisReference(cls_), field)
                mp_ref = refs.MethodParameterReference(field.constructor_param)
                # TODO: decide what to do with "after-TypeEngine" transformations
                mp_ref.set_actual_type(field.type, False, False)
                constr_field_inits.append(
                    stats.ExpressionStatement(
                        exprs.BinaryExpression(field_ref, "=", mp_ref)))

            super_call = f'''super({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))});\n''' if cls_.constructor_.super_call_args != None else ""

            # @java var stmts = Stream.of(constrFieldInits, complexFieldInits, cls.constructor_.getBody().statements).flatMap(Collection::stream).toArray(Statement[]::new);
            # @java-import java.util.Collection
            # @java-import java.util.stream.Stream
            stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements

            # TODO: super calls
            res_list.append(
                self.method_gen(
                    "public " +
                    self.pre_if("/* throws */ ", cls_.constructor_.throws) +
                    self.name_(cls_.name), cls_.constructor_.parameters,
                    f'''\n{{\n{self.pad(super_call + self.stmts(stmts))}\n}}'''
                ))
        elif len(complex_field_inits) > 0:
            res_list.append(
                f'''public {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}'''
            )

        methods = []
        for method in cls_.methods:
            if method.body == None:
                continue
            # declaration only
            methods.append(self.method(method, True))
        res_list.append("\n\n".join(methods))
        return self.pad("\n\n".join(list(filter(lambda x: x != "", res_list))))
Exemplo n.º 17
0
 def class_like(self, cls_):
     self.current_class = cls_
     res_list = []
     
     static_constructor_stmts = []
     complex_field_inits = []
     if isinstance(cls_, types.Class):
         field_reprs = []
         for field in cls_.fields:
             is_initializer_complex = field.initializer != None and not (isinstance(field.initializer, exprs.StringLiteral)) and not (isinstance(field.initializer, exprs.BooleanLiteral)) and not (isinstance(field.initializer, exprs.NumericLiteral))
             
             prefix = f'''{self.vis(field.visibility, True)}{self.pre_if("static ", field.is_static)}'''
             if is_initializer_complex:
                 if field.is_static:
                     static_constructor_stmts.append(stats.ExpressionStatement(exprs.BinaryExpression(refs.StaticFieldReference(field), "=", field.initializer)))
                 else:
                     complex_field_inits.append(stats.ExpressionStatement(exprs.BinaryExpression(refs.InstanceFieldReference(refs.ThisReference(cls_), field), "=", field.initializer)))
                 
                 field_reprs.append(f'''{prefix}{self.var_wo_init(field, field)};''')
             else:
                 field_reprs.append(f'''{prefix}{self.var(field, field)};''')
         res_list.append("\n".join(field_reprs))
         
         for prop in cls_.properties:
             if prop.getter != None:
                 res_list.append(self.vis(prop.visibility, False) + self.pre_if("static ", prop.is_static) + f'''function get_{self.name_(prop.name)}(){self.block(prop.getter, False)}''')
             if prop.setter != None:
                 res_list.append(self.vis(prop.visibility, False) + self.pre_if("static ", prop.is_static) + f'''function set_{self.name_(prop.name)}($value){self.block(prop.setter, False)}''')
         
         if len(static_constructor_stmts) > 0:
             res_list.append(f'''static function StaticInit()\n{{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}''')
         
         if cls_.constructor_ != None:
             constr_field_inits = []
             for field in list(filter(lambda x: x.constructor_param != None, cls_.fields)):
                 field_ref = refs.InstanceFieldReference(refs.ThisReference(cls_), field)
                 mp_ref = refs.MethodParameterReference(field.constructor_param)
                 # TODO: decide what to do with "after-TypeEngine" transformations
                 mp_ref.set_actual_type(field.type, False, False)
                 constr_field_inits.append(stats.ExpressionStatement(exprs.BinaryExpression(field_ref, "=", mp_ref)))
             
             parent_call = f'''parent::__construct({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))});\n''' if cls_.constructor_.super_call_args != None else ""
             
             # @java var stmts = Stream.of(constrFieldInits, complexFieldInits, ((Class)cls).constructor_.getBody().statements).flatMap(Collection::stream).toArray(Statement[]::new);
             # @java-import java.util.Collection
             # @java-import java.util.stream.Stream
             stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements
             
             res_list.append(self.pre_if("/* throws */ ", cls_.constructor_.throws) + "function __construct" + f'''({", ".join(list(map(lambda p: self.var(p, p), cls_.constructor_.parameters)))})''' + f''' {{\n{self.pad(parent_call + self.stmts(stmts))}\n}}''')
         elif len(complex_field_inits) > 0:
             res_list.append(f'''function __construct()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}''')
     elif isinstance(cls_, types.Interface):
         pass
     
     methods = []
     for method in cls_.methods:
         if isinstance(cls_, types.Class) and method.body == None:
             continue
         # declaration only
         methods.append(("" if isinstance(method.parent_interface, types.Interface) else self.vis(method.visibility, False)) + self.pre_if("static ", method.is_static) + self.pre_if("/* throws */ ", method.throws) + f'''function ''' + self.name_(method.name) + self.type_args(method.type_arguments) + f'''({", ".join(list(map(lambda p: self.var(p, None), method.parameters)))})''' + (f''' {{\n{self.pad(self.stmts(method.body.statements))}\n}}''' if method.body != None else ";"))
     res_list.append("\n\n".join(methods))
     
     res_list_joined = self.pad("\n\n".join(list(filter(lambda x: x != "", res_list))))
     return f''' {{\n{res_list_joined}\n}}''' + (f'''\n{self.name_(cls_.name)}::StaticInit();''' if len(static_constructor_stmts) > 0 else "")
    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