Пример #1
0
def jsify_for(node: ast.For) -> typing.List[unholy.Compilable]:
    # 'target', 'iter', 'body', 'orelse', 'type_comment',
    output = []
    var_name = unholy.jsify_node(node.target)
    if isinstance(node.iter, ast.Call) and isinstance(
            node.iter.func, ast.Name) and node.iter.func.id == 'range':
        # range loop
        start, end, step = _parse_range_arguments(node.iter)
        output.append(
            unholy.JSStatement('for ', [
                '(let ', *var_name, ' = ', *start, '; (', *step, ' >= 0 ? (',
                *var_name, ' < ', *end, ') : ', *var_name, ' > ', *end, '); ',
                *var_name, '+=', *step, ')'
            ],
                               has_semicolon=False))
    else:
        iterator = unholy.jsify_node(node.iter)
        output.append(
            unholy.JSStatement('for ', [
                '(const ', *var_name, ' of ', f'{unholy.map_name("iter")}(',
                *iterator, '))'
            ],
                               has_semicolon=False))
    body = []
    for i in node.body:
        body.append(unholy.JSStatement('', unholy.jsify_node(i)))
    output.append(unholy.JSBlock(body))
    return output
Пример #2
0
def jsify_assign(
    node: typing.Union[ast.Assign, ast.AnnAssign]
) -> typing.List[unholy.Compilable]:
    # targets?, value, type_comment
    if isinstance(node, ast.Assign):
        t = node.targets
    else:
        t = [node.target]

    targets = []

    for i in t:
        targets.extend(unholy.jsify_node(i))
    if len(targets) == 1:
        return [
            unholy.JSExpression(
                [targets[0], ' = ', *unholy.jsify_node(node.value)])
        ]
    else:
        output = ['[']
        for i in targets:
            output.append(i)
            output.append(', ')
        output.append('] =')
        output.extend(unholy.jsify_node(node.value))
        return [unholy.JSExpression(output)]
Пример #3
0
def jsify_dict(node: ast.Dict) -> List[Compilable]:
    # keys, values
    output = []
    for k, v in zip(node.keys, node.values):
        jk = jsify_node(k)
        jv = jsify_node(v)
        if len(jk) != 1:
            raise CompilationError(
                f'Dict key: Expected only one JSExpression (or Compilable) while got '
                f'{len(jk)}: {jk!r}')
        if len(jv) != 1:
            raise CompilationError(
                f'Dict value: Expected only one JSExpression (or Compilable) while got '
                f'{len(jv)}: {jv!r}')

        output.append(
            JSExpression([
                JSExpression(['[', jk[0], ']', ':']),
                jv[0],
            ]))
    return [JSExpression([
        '{',
        JSExpression(output),
        '}',
    ])]
Пример #4
0
def jsify_formatted_value(node: ast.FormattedValue) -> typing.List[Compilable]:
    value = jsify_node(node.value)
    if node.format_spec:
        fspec = jsify_node(node.format_spec)
        return [
            JSExpression(['unholy_js.py__format(', *value, ', ', *fspec, ')'])
        ]
    else:
        return value
Пример #5
0
def jsify_call(node: ast.Call) -> typing.List[unholy.Compilable]:
    func_name = unholy.jsify_node(node.func)
    args = []
    for i in node.args:
        args.extend(unholy.jsify_node(i))

    if node.keywords:
        warnings.warn(
            f'keyword arguments were ignored while calling {func_name}')
    return [unholy.JSExpression([func_name[0], '(', *args, ')'])]
Пример #6
0
def jsify_if(node: ast.If) -> typing.List[unholy.Compilable]:
    # test, body, orelse,
    body = []
    for i in node.body:
        body.extend(unholy.jsify_node(i))
    return [
        unholy.JSStatement('if ', ['(', *unholy.jsify_node(node.test), ')'],
                           has_semicolon=False),
        unholy.JSBlock(body)
    ]
Пример #7
0
def jsify_fstring(node: ast.JoinedStr) -> typing.List[Compilable]:
    values = []
    for i in node.values:
        if isinstance(i, ast.FormattedValue):
            values.append(JSExpression(['${', *jsify_node(i), '}']))
        else:
            if isinstance(i, ast.Constant):
                values.append(JSExpression([i.value]))
            else:
                values.extend(jsify_node(i))

    return [JSExpression(['`', *values, '`'])]
Пример #8
0
def jsify_subscript(node: ast.Subscript) -> typing.List[unholy.Compilable]:
    # value, slice, ctx,
    v = unholy.jsify_node(node.value)
    # node.slice: typing.Union[ast.Slice, ast.Index]
    if isinstance(node.slice, ast.Slice):
        raise unholy.CompilationError('Slicing is not yet implemented')
    elif isinstance(node.slice, ast.Index):
        return [
            unholy.JSExpression([*v, *unholy.jsify_node(node.slice.value)])
        ]
    elif isinstance(node.slice, (ast.Constant, ast.Name)):
        return [
            unholy.JSExpression([*v, '[', *unholy.jsify_node(node.slice), ']'])
        ]
    else:
        raise unholy.CompilationError(
            f'Unknown index type: {type(node.slice)}. No way to js-ify. Aborting'
        )
Пример #9
0
def _jsify_sequential_container(node, prefix, suffix) -> List[Compilable]:
    elts = []
    for i in node.elts:
        v = jsify_node(i)
        if len(v) != 1:
            raise CompilationError(
                f'Expected only one JSExpression (or Compilable) while got {len(v)}: {v!r}'
            )
        elts.append(v[0])
        elts.append(', ')

    return [JSExpression([prefix, JSExpression(elts), suffix])]
Пример #10
0
def jsify_module(node: ast.Module) -> typing.List[unholy.Compilable]:
    body = []
    for i in node.body:
        body.extend(unholy.jsify_node(i))
    logging.debug(body)
    return [
        unholy.JSBlock([
            unholy.JSStatement(
                'const unholy_js = require("./not_python/unholy_js.js")'),
            *body
        ],
                       has_braces=False)
    ]
Пример #11
0
def jsify_function_definition(
    node: typing.Union[ast.FunctionDef, ast.AsyncFunctionDef]
) -> typing.List[unholy.Compilable]:
    name = node.name
    decorators = []
    for i in node.decorator_list:
        decorators.extend(unholy.jsify_node(i))
        decorators.append('(')

    if decorators:
        decorators.pop(-1)  # remove unnecessary '('

    arguments: typing.List[ast.arg] = node.args.args
    arg_list = ', '.join([i.arg for i in arguments])
    if node.args.kwarg:
        arg_list += f', options'
    if node.args.vararg:
        arg_list += f', ...{node.args.vararg.arg}'
    body = []
    for i in node.body:
        body.extend(unholy.jsify_node(i))
    if isinstance(node, ast.FunctionDef):
        keyword = 'function'
    elif isinstance(node, ast.AsyncFunctionDef):
        keyword = 'async function'
    else:
        raise unholy.CompilationError(
            'Expected a FunctionDev or AsyncFunctionDef. Something broke.')
    return [
        # unholy.JSStatement(f'let {name} = {decorators}(function {name}({arg_list})', has_semicolon=False),
        unholy.JSStatement('let ', [
            name, ' = ', *decorators, f'({keyword}', name, '(', arg_list, ')'
        ],
                           has_semicolon=False),
        unholy.JSBlock(body),
        unholy.JSStatement(')' * (len(node.decorator_list) + 1),
                           force_concat=True)
    ]
Пример #12
0
def jsify_lambda(node: ast.Lambda) -> typing.List[unholy.Compilable]:
    # args, body
    arguments: typing.List[ast.arg] = node.args.args
    arg_list = ', '.join([i.arg for i in arguments])
    if node.args.kwarg:
        arg_list += f', options'
    if node.args.vararg:
        arg_list += f', ...{node.args.vararg.arg}'
    return [
        unholy.JSExpression([
            unholy.JSExpression([f'({arg_list}) =>']),
            unholy.JSBlock(unholy.jsify_node(node.body))
        ])
    ]
Пример #13
0
def _parse_range_arguments(call: ast.Call):
    if len(call.args) == 1:
        return [unholy.JSExpression(['0'])], unholy.jsify_node(
            call.args[0]), [unholy.JSExpression(['1'])]
    elif len(call.args) == 2:
        return unholy.jsify_node(call.args[0]), unholy.jsify_node(
            call.args[1]), [unholy.JSExpression(['1'])]
    elif len(call.args) == 3:
        return unholy.jsify_node(call.args[0]), unholy.jsify_node(
            call.args[1]), unholy.jsify_node(call.args[2])
    else:
        raise unholy.CompilationError(
            'Bad arguments for range() function in for loop.')
Пример #14
0
import ast
from typing import List

# noinspection PyUnresolvedReferences
from typechecker import ensure_typecheck
from unholy import jsify_node
# noinspection PyUnresolvedReferences
from unholy.classes import Compilable, CompilationError, JSExpression

PY_TO_JS_OPERATORS = {
    ast.Mult: lambda l, r: JSExpression([
        *jsify_node(l),
        '*',
        *jsify_node(r),
    ]),
    ast.Div: lambda l, r: JSExpression([
        *jsify_node(l),
        '/',
        *jsify_node(r),
    ]),
    ast.Add: lambda l, r: JSExpression([
        *jsify_node(l),
        '+',
        *jsify_node(r),
    ]),
    ast.Pow: lambda l, r: JSExpression([
        *jsify_node(l),
        '**',
        *jsify_node(r),
    ]),
    ast.USub: lambda l, r: JSExpression([
Пример #15
0
def jsify_return(node: ast.Return) -> typing.List[unholy.Compilable]:
    # 'value',
    # noinspection PyTypeChecker
    v: unholy.JSStatement = unholy.jsify_node(node.value)[0]
    v.force_concat = True
    return [unholy.JSStatement(f'return'), v]
Пример #16
0
def jsify_delete(node: ast.Delete) -> typing.List[unholy.Compilable]:
    # 'targets',
    return [
        unholy.JSStatement('delete ', unholy.jsify_node(i))
        for i in node.targets
    ]
Пример #17
0
def jsify_attribute(node: ast.Attribute) -> typing.List[unholy.Compilable]:
    # value, attr, ctx
    return [
        unholy.JSExpression([*unholy.jsify_node(node.value), '.', node.attr])
    ]
Пример #18
0
def jsify_expr(node: ast.Expr) -> typing.List[unholy.Compilable]:
    # 'value',
    return unholy.jsify_node(node.value)
Пример #19
0
def jsify_await(node: ast.Await) -> typing.List[unholy.Compilable]:
    return [unholy.JSExpression(['await', *unholy.jsify_node(node.value)])]