Ejemplo n.º 1
0
def map_class_def(babel_node, node, parents):
    class_name = build.identifier(node.name)
    bases = babel_node['bases']

    if not bases:
        super_class = None
    else:
        if len(bases) == 1:
            super_class = bases[0]
        else:
            super_class = build.call_expression(
                # TODO: Use constant
                callee=build.identifier('__multi__'),
                args=bases,
                ensure_native_compatibility=False,
            )

    body = babel_node['body']

    # Change functions to methods and variable declarations to class properties
    # that were created by the recursion already.

    class_expression = {
        'type': 'ClassExpression',
        'id': class_name,
        'superClass': super_class,
        'body': {
            'type': 'ClassBody',
            'body': body,
        },
    }

    if babel_node['keywords']:
        print('keywords was provided for class definition. ignored...')

    return {
        'type': 'VariableDeclaration',
        'declarations': [
            {
                'type': 'VariableDeclarator',
                'id': class_name,
                'init': utils.apply_decorators(
                    babel_node['decorator_list'],
                    build.call_expression(
                        # TODO: Use constant
                        callee=build.identifier('__def__'),
                        args=[class_expression],
                        ensure_native_compatibility=False,
                    )
                ),
            }
        ],
        'kind': 'var',
    }
Ejemplo n.º 2
0
def map_subscript(babel_node, node, parents):
    if isinstance(node.slice, ast.ExtSlice):
        raise ValueError('Advanced slicing (ExtSlice) is not supported.')

    args = [babel_node['value']]
    slice_data = babel_node['slice']
    if isinstance(node.slice, ast.Index):
        args += [
            build.string('index'),
            slice_data['value'],
        ]
    # isinstance(node.slice, ast.Slice)
    else:
        args += [
            build.string('slice'),
            slice_data['lower'],
            slice_data['upper'],
            slice_data['step'],
        ]

    return build.call_expression(
        callee=build.identifier(JsHelperNames.SUBSCRIPT),
        args=args,
        ensure_native_compatibility=False,
    )
Ejemplo n.º 3
0
def _map_function_def(babel_node, node, parents):
    common_parts = utils.function_definition_parts(babel_node, node)
    func_name = common_parts['__name__']
    params = common_parts['params']
    body = common_parts['body']

    function_definition = build.call_expression(
        # TODO: Use constant
        callee=build.identifier('__def__'),
        args=[{
            'type': 'FunctionExpression',
            'id': func_name,
            'params': params,
            'body': body,
        }],
        ensure_native_compatibility=False,
    )
    return {
        'type':
        'VariableDeclaration',
        'declarations': [{
            'type':
            'VariableDeclarator',
            'id':
            func_name,
            'init':
            utils.apply_decorators(babel_node['decorator_list'],
                                   function_definition),
        }],
        'kind':
        'var',
    }
Ejemplo n.º 4
0
def map_dict(babel_node, node, parents):
    return build.call_expression(
        callee=build.identifier(JsHelperNames.DICT_CONSTRUCTOR),
        args=[
            build.array_expression([
                (build.array_expression([key, value])
                 if key is not None else build.spread(
                     build.call_expression(
                         callee=build.member_expression(
                             object=value,
                             property=build.identifier('entries'),
                         ),
                         ensure_native_compatibility=False,
                     )))
                for key, value in zip(babel_node['keys'], babel_node['values'])
            ])
        ],
    )
Ejemplo n.º 5
0
def map_tuple(babel_node, node, parents):
    mapped_list = map_list(babel_node, node, parents)
    if isinstance(node.ctx, ast.Load):
        return build.call_expression(
            callee=build.identifier(JsHelperNames.TUPLE_CONSTRUCTOR),
            args=[mapped_list],
            ensure_native_compatibility=False,
        )
    else:
        return mapped_list
Ejemplo n.º 6
0
def _map_function_def_to_class_method(babel_node, node, parents):
    common_parts = utils.function_definition_parts(babel_node, node)
    method_name = common_parts['__name__']
    raw_method_name = method_name['name']
    params = common_parts['params']
    body = common_parts['body']

    decorators = []

    use_static_keyword = False
    inject_self = True
    for decorator in babel_node['decorator_list']:
        # '@classmethod' does not take any arguments
        # => it must be an identifier.
        decorator_is_identifier = check.is_identifier(decorator)
        decorator_requires_static_keyword = (
            decorator_is_identifier
            and decorator['name'] in ['classmethod', 'staticmethod'])
        if decorator_requires_static_keyword:
            use_static_keyword = True
            if decorator['name'] == 'staticmethod':
                inject_self = False
        else:
            if decorator_is_identifier:
                expression = decorator
            else:
                # Use the kwargs supporting way to call the function to avoid
                # actual expression as decorator which is technically possible.
                # NOTE: This corresponds to
                # 'build.call_expression(ensure_native_compatibility=False)'
                # in 'utils.apply_decorators'.
                expression = utils.unpack_value(
                    decorator,
                    'expression_statement.conditional_expression__consequent')
            decorators.append({'type': 'Decorator', 'expression': expression})

    # Remove 'self' as 1st positional argument
    # and remove 'self = __use_kwarg__(_, self, "self");'
    # and instead inject 'var self = this' into the method body.
    del params[0]['elements'][0]
    inner_body = body['body']
    if inner_body:
        del inner_body[0]
    if inject_self:
        inner_body.insert(
            0,
            build.variable_declaration(
                left=build.identifier('self'),
                right=build.this(),
            ))

    return {
        'type': 'ClassMethod',
        'kind':
        ('constructor' if raw_method_name == 'constructor' else 'method'),
        'decorators': decorators,
        'static': use_static_keyword,
        'key': method_name,
        'params': params,
        'body': body,
        'id': None,
        'generator': False,
        'expression': False,
        'async': False,
    }
Ejemplo n.º 7
0
def map_arg(babel_node, node, parents):
    return build.identifier(node.arg)
Ejemplo n.º 8
0
def function_definition_parts(babel_node, node):
    '''Returns parts of the function babel AST node that are common for normal
    function definitions and class/instance methods.'''

    arguments = babel_node['args']
    args = arguments.get('args', [])
    defaults = arguments.get('defaults', [])
    vararg = arguments.get('vararg', None)
    kwonlyargs = arguments.get('kwonlyargs', [])
    kw_defaults = arguments.get('kw_defaults', [])
    kwarg = arguments.get('kwarg', None)

    diff = len(args) - len(defaults)
    if diff > 0:
        defaults = [NO_DEFAULT_FOR_ARG for i in range(0, diff)] + defaults

    # Prepend custom JS code the function body (for creating the kwargs behavior).
    # body = babel_node['body']
    # if len(args) > 0:
    args_identifier = '__arguments__'
    if True:
        # var [[a, b=1, ...c], {d, e=3, ...f}] =  __get_args__(args)
        body = ([
            build.variable_declaration(
                left=build.array_destructuring(
                    bare_pattern=True,
                    props=[
                        build.array_destructuring(
                            props=[
                                (arg if defaults[i] is NO_DEFAULT_FOR_ARG else
                                 (arg, defaults[i]))
                                for i, arg in enumerate(args)
                            ],
                            rest=vararg,
                            bare_pattern=True,
                        ),
                        build.object_destructuring(
                            props=[(kwonlyarg if kw_defaults[i] is None else
                                    (kwonlyarg, kw_defaults[i]))
                                   for i, kwonlyarg in enumerate(kwonlyargs)],
                            rest=kwarg,
                            bare_pattern=True,
                        ),
                    ]),
                right=build.call_expression(
                    callee=build.identifier(JsHelperNames.GET_ARGS_AND_KWARGS),
                    args=[build.identifier(args_identifier)],
                    ensure_native_compatibility=False,
                ),
            ),
        ] + [
            build.assignment(
                left=arg,
                right=build.call_expression(
                    callee=build.identifier(
                        JsHelperNames.CONSUME_KWARG_IF_POSSIBLE),
                    args=[kwarg, arg, build.string(arg['name'])],
                    ensure_native_compatibility=False,
                ),
            ) for arg in args if kwarg is not None
        ] + babel_node['body'])

    return {
        '__name__': build.identifier(node.name),
        'params': [
            build.rest(build.identifier(args_identifier))
            # build.array_destructuring(
            #     props=[
            #         (
            #             arg
            #             if defaults[i] is NO_DEFAULT_FOR_ARG
            #             else (arg, defaults[i])
            #         )
            #         for i, arg in enumerate(args)
            #     ],
            #     rest=vararg,
            #     bare_pattern=True,
            # ),
            # build.object_destructuring(
            #     props=[
            #         (
            #             kwonlyarg
            #             if kw_defaults[i] is None
            #             else (kwonlyarg, kw_defaults[i])
            #         )
            #         for i, kwonlyarg in enumerate(kwonlyargs)
            #     ],
            #     rest=kwarg,
            #     bare_pattern=True,
            # ),
        ],
        'body': {
            'type': 'BlockStatement',
            'body': body,
            'directives': [],
        },
    }
Ejemplo n.º 9
0
def map_set(babel_node, node, parents):
    return {
        'type': 'NewExpression',
        'callee': build.identifier('Set'),
        'arguments': babel_node['elts'],
    }
Ejemplo n.º 10
0
def map_name(babel_node, node, parents):
    # id = node.id
    # one of ast.Load, ast.Store, ast.Delete
    # ctx = node.ctx
    return build.identifier(node.id)
Ejemplo n.º 11
0
def map_attribute(babel_node, node, parents):
    return build.member_expression(
        object=babel_node['value'],
        property=build.identifier(node.attr),
    )
Ejemplo n.º 12
0
def map_keyword(babel_node, node, parents):
    return {
        'arg': None if node.arg is None else build.identifier(node.arg),
        'value': babel_node['value'],
    }