Ejemplo n.º 1
0
djinni::Handle<DjinniRecordHandle> DjinniExtendedRecord::fromCpp(const ::testsuite::ExtendedRecord& dr) {

    djinni::Handle<DjinniRecordHandle> _aux(
        s_py_callback_extended_record_python_create_extended_record(
            dr.foo),
        extended_record___delete);
    return _aux;
}
Ejemplo n.º 2
0
djinni::Handle<DjinniRecordHandle> DjinniMapRecord::fromCpp(const ::testsuite::MapRecord& dr) {
    auto  _field_map = DjinniMapStringInt64T::fromCpp(dr.map);
    auto  _field_imap = DjinniMapInt32TInt32T::fromCpp(dr.imap);

    djinni::Handle<DjinniRecordHandle> _aux(
        s_py_callback_map_record_python_create_map_record(
            _field_map.release(),
            _field_imap.release()),
        map_record___delete);
    return _aux;
}
Ejemplo n.º 3
0
    void desugar(AST *&ast_)
    {
        if (auto *ast = dynamic_cast<Apply*>(ast_)) {
                
            desugar(ast->target);
            for (AST *&arg : ast->arguments)
                desugar(arg);

        } else if (auto *ast = dynamic_cast<Array*>(ast_)) {
            for (AST *&el : ast->elements)
                desugar(el);

        } else if (auto *ast = dynamic_cast<ArrayComprehension*>(ast_)) {
            for (ComprehensionSpec &spec : ast->specs)
                desugar(spec.expr);
            desugar(ast->body);

            int n = ast->specs.size();
            AST *zero = make<LiteralNumber>(E, 0.0);
            AST *one = make<LiteralNumber>(E, 1.0);
            auto *_r = id(U"$r");
            auto *_l = id(U"$l");
            std::vector<const Identifier*> _i(n);
            for (int i = 0; i < n ; ++i) {
                StringStream ss;
                ss << U"$i_" << i;
                _i[i] = id(ss.str());
            }
            std::vector<const Identifier*> _aux(n);
            for (int i = 0; i < n ; ++i) {
                StringStream ss;
                ss << U"$aux_" << i;
                _aux[i] = id(ss.str());
            }

            // Build it from the inside out.  We keep wrapping 'in' with more ASTs.
            assert(ast->specs[0].kind == ComprehensionSpec::FOR);

            int last_for = n - 1;
            while (ast->specs[last_for].kind != ComprehensionSpec::FOR)
                last_for--;
            // $aux_{last_for}($i_{last_for} + 1, $r + [body])
            AST *in = make<Apply>(
                ast->body->location,
                var(_aux[last_for]),
                std::vector<AST*> {
                    make<Binary>(E, var(_i[last_for]), BOP_PLUS, one),
                    make<Binary>(E, var(_r), BOP_PLUS, singleton(ast->body))
                },
                true  // tailstrict
            );
            for (int i = n - 1; i >= 0 ; --i) {
                const ComprehensionSpec &spec = ast->specs[i];
                AST *out;
                if (i > 0) {
                    int prev_for = i - 1;
                    while (ast->specs[prev_for].kind != ComprehensionSpec::FOR)
                        prev_for--;

                    // aux_{prev_for}($i_{prev_for} + 1, $r)
                    out = make<Apply>(  // False branch.
                        E,
                        var(_aux[prev_for]), 
                        std::vector<AST*> {
                            make<Binary>(E, var(_i[prev_for]), BOP_PLUS, one), var(_r)},
                        true  // tailstrict
                    );
                } else {
                    out = var(_r);
                }
                switch (spec.kind) {
                    case ComprehensionSpec::IF: {
                        /*
                            if [[[...cond...]]] then
                                [[[...in...]]]
                            else
                                [[[...out...]]]
                        */
                        in = make<Conditional>(
                            ast->location,
                            spec.expr,
                            in,  // True branch.
                            out);  // False branch.
                    } break;
                    case ComprehensionSpec::FOR: {
                        /*
                            local $l = [[[...array...]]];
                            local aux_{i}(i_{i}, r) =
                                if i_{i} >= std.length(l) then
                                    [[[...out...]]]
                                else
                                    local [[[...var...]]] = l[i_{i}];
                                    [[[...in...]]]
                            aux_{i}(0, r) tailstrict;
                        */
                        in = make<Local>(
                            ast->location,
                            Local::Binds {
                                {_l, spec.expr},
                                {_aux[i], make<Function>(
                                    ast->location,
                                    std::vector<const Identifier*>{_i[i], _r},
                                    make<Conditional>(
                                        ast->location, 
                                        make<Binary>(
                                            E, var(_i[i]), BOP_GREATER_EQ, length(var(_l))),
                                        out,
                                        make<Local>(
                                            ast->location,
                                            Local::Binds {{
                                                spec.var,
                                                make<Index>(E, var(_l), var(_i[i]))
                                            }},
                                            in)
                                    )
                                )}},
                                make<Apply>(
                                    E,
                                    var(_aux[i]),
                                    std::vector<AST*> {
                                        zero,
                                        i == 0 ? make<Array>(E, std::vector<AST*>{})
                                               : static_cast<AST*>(var(_r))
                                    },
                                    true));  // tailstrict
                    } break;
                }
            }
                    
            ast_ = in;

        } else if (auto *ast = dynamic_cast<Binary*>(ast_)) {
            desugar(ast->left);
            desugar(ast->right);

        } else if (dynamic_cast<const BuiltinFunction*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Conditional*>(ast_)) {
            desugar(ast->cond);
            desugar(ast->branchTrue);
            desugar(ast->branchFalse);

        } else if (auto *ast = dynamic_cast<Error*>(ast_)) {
            desugar(ast->expr);

        } else if (auto *ast = dynamic_cast<Function*>(ast_)) {
            desugar(ast->body);

        } else if (dynamic_cast<const Import*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const Importstr*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Index*>(ast_)) {
            desugar(ast->target);
            desugar(ast->index);

        } else if (auto *ast = dynamic_cast<Local*>(ast_)) {
            for (auto &bind: ast->binds)
                desugar(bind.second);
            desugar(ast->body);

        } else if (dynamic_cast<const LiteralBoolean*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const LiteralNumber*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const LiteralString*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const LiteralNull*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Object*>(ast_)) {
            for (auto &assert : ast->asserts) {
                desugar(assert);
            }
            for (auto &field : ast->fields) {
                desugar(field.name);
                desugar(field.body);
            }

        } else if (auto *ast = dynamic_cast<ObjectComprehension*>(ast_)) {
            for (ComprehensionSpec &spec : ast->specs)
                desugar(spec.expr);
            desugar(ast->field);
            desugar(ast->value);

            /*  {
                    [arr[0]]: local x = arr[1], y = arr[2], z = arr[3]; val_expr
                    for arr in [ [key_expr, x, y, z] for ...  ]
                }
            */
            auto *_arr = id(U"$arr");
            AST *zero = make<LiteralNumber>(E, 0.0);
            int counter = 1;
            Local::Binds binds;
            auto arr_e = std::vector<AST*> {ast->field};
            for (ComprehensionSpec &spec : ast->specs) {
                if (spec.kind == ComprehensionSpec::FOR) {
                    binds[spec.var] =
                        make<Index>(E, var(_arr), make<LiteralNumber>(E, double(counter++)));
                    arr_e.push_back(var(spec.var));
                }
            }
            AST *arr = make<ArrayComprehension>(
                ast->location,
                make<Array>(ast->location, arr_e),
                ast->specs);
            desugar(arr);
            ast_ = make<ObjectComprehensionSimple>(
                ast->location,
                make<Index>(E, var(_arr), zero),
                make<Local>(
                    ast->location,
                    binds,
                    ast->value),
                _arr,
                arr);

        } else if (auto *ast = dynamic_cast<ObjectComprehensionSimple*>(ast_)) {
            desugar(ast->field);
            desugar(ast->value);
            desugar(ast->array);

        } else if (dynamic_cast<const Self*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const Super*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Unary*>(ast_)) {
            desugar(ast->expr);

        } else if (dynamic_cast<const Var*>(ast_)) {
            // Nothing to do.

        } else {
            std::cerr << "INTERNAL ERROR: Unknown AST: " << ast_ << std::endl;
            std::abort();

        }
    }
Ejemplo n.º 4
0
    void desugar(AST *&ast_, unsigned obj_level)
    {
        if (auto *ast = dynamic_cast<Apply*>(ast_)) {
            desugar(ast->target, obj_level);
            for (Apply::Arg &arg : ast->args)
                desugar(arg.expr, obj_level);

        } else if (auto *ast = dynamic_cast<ApplyBrace*>(ast_)) {
            desugar(ast->left, obj_level);
            desugar(ast->right, obj_level);
            ast_ = alloc->make<Binary>(ast->location, ast->openFodder,
                                       ast->left, EF, BOP_PLUS, ast->right);

        } else if (auto *ast = dynamic_cast<Array*>(ast_)) {
            for (auto &el : ast->elements)
                desugar(el.expr, obj_level);

        } else if (auto *ast = dynamic_cast<ArrayComprehension*>(ast_)) {
            for (ComprehensionSpec &spec : ast->specs)
                desugar(spec.expr, obj_level);
            desugar(ast->body, obj_level + 1);

            int n = ast->specs.size();
            AST *zero = make<LiteralNumber>(E, EF, "0.0");
            AST *one = make<LiteralNumber>(E, EF, "1.0");
            auto *_r = id(U"$r");
            auto *_l = id(U"$l");
            std::vector<const Identifier*> _i(n);
            for (int i = 0; i < n ; ++i) {
                StringStream ss;
                ss << U"$i_" << i;
                _i[i] = id(ss.str());
            }
            std::vector<const Identifier*> _aux(n);
            for (int i = 0; i < n ; ++i) {
                StringStream ss;
                ss << U"$aux_" << i;
                _aux[i] = id(ss.str());
            }

            // Build it from the inside out.  We keep wrapping 'in' with more ASTs.
            assert(ast->specs[0].kind == ComprehensionSpec::FOR);

            int last_for = n - 1;
            while (ast->specs[last_for].kind != ComprehensionSpec::FOR)
                last_for--;
            // $aux_{last_for}($i_{last_for} + 1, $r + [body])
            AST *in = make<Apply>(
                ast->body->location,
                EF,
                var(_aux[last_for]),
                EF,
                Apply::Args {
                    { make<Binary>(E, EF, var(_i[last_for]), EF, BOP_PLUS, one), EF},
                    { make<Binary>(E, EF, var(_r), EF, BOP_PLUS, singleton(ast->body)), EF}
                },
                false,  // trailingComma
                EF,
                EF,
                true  // tailstrict
            );
            for (int i = n - 1; i >= 0 ; --i) {
                const ComprehensionSpec &spec = ast->specs[i];
                AST *out;
                if (i > 0) {
                    int prev_for = i - 1;
                    while (ast->specs[prev_for].kind != ComprehensionSpec::FOR)
                        prev_for--;

                    // aux_{prev_for}($i_{prev_for} + 1, $r)
                    out = make<Apply>(  // False branch.
                        E,
                        EF,
                        var(_aux[prev_for]),
                        EF,
                        Apply::Args {
                            { make<Binary>(E, EF, var(_i[prev_for]), EF, BOP_PLUS, one), EF, },
                            { var(_r), EF, }
                        },
                        false, // trailingComma
                        EF,
                        EF,
                        true  // tailstrict
                    );
                } else {
                    out = var(_r);
                }
                switch (spec.kind) {
                    case ComprehensionSpec::IF: {
                        /*
                            if [[[...cond...]]] then
                                [[[...in...]]]
                            else
                                [[[...out...]]]
                        */
                        in = make<Conditional>(
                            ast->location,
                            EF,
                            spec.expr,
                            EF,
                            in,  // True branch.
                            EF,
                            out);  // False branch.
                    } break;
                    case ComprehensionSpec::FOR: {
                        /*
                            local $l = [[[...array...]]]
                                  aux_{i}(i_{i}, r) =
                                if i_{i} >= std.length($l) then
                                    [[[...out...]]]
                                else
                                    local [[[...var...]]] = $l[i_{i}];
                                    [[[...in...]]];`
                            if std.type($l) != "array" then
                                error "In comprehension, can only iterate over array.."
                            else
                                aux_{i}(0, r) tailstrict;
                        */
                        in = make<Local>(
                            ast->location,
                            EF,
                            Local::Binds {
                                bind(_l, spec.expr),  // Need to check expr is an array
                                bind(_aux[i], make<Function>(
                                    ast->location,
                                    EF,
                                    EF,
                                    std::vector<Param>{Param(EF, _i[i], EF), Param(EF, _r, EF)},
                                    false,  // trailingComma
                                    EF,
                                    make<Conditional>(
                                        ast->location,
                                        EF,
                                        make<Binary>(
                                            E, EF, var(_i[i]), EF, BOP_GREATER_EQ, length(var(_l))),
                                        EF,
                                        out,
                                        EF,
                                        make<Local>(
                                            ast->location,
                                            EF,
                                            singleBind(
                                                spec.var,
                                                make<Index>(E, EF, var(_l), EF, false, var(_i[i]),
                                                            EF, nullptr, EF, nullptr, EF)
                                            ),
                                            in)
                                    )
                                ))},
                            make<Conditional>(
                                ast->location,
                                EF,
                                equals(ast->location, type(var(_l)), str(U"array")),
                                EF,
                                make<Apply>(
                                    E,
                                    EF,
                                    var(_aux[i]),
                                    EF,
                                    Apply::Args {
                                        {zero, EF},
                                        {
                                            i == 0
                                            ? make<Array>(E, EF, Array::Elements{}, false, EF)
                                            : static_cast<AST*>(var(_r)),
                                            EF,
                                        }
                                    },
                                    false,  // trailingComma
                                    EF,
                                    EF,
                                    true),  // tailstrict
                                EF,
                                error(ast->location,
                                      U"In comprehension, can only iterate over array.")));
                    } break;
                }
            }

            ast_ = in;

        } else if (auto *ast = dynamic_cast<Assert*>(ast_)) {
            desugar(ast->cond, obj_level);
            if (ast->message == nullptr) {
                ast->message = str(U"Assertion failed.");
            }
            desugar(ast->message, obj_level);
            desugar(ast->rest, obj_level);

            // if cond then rest else error msg
            AST *branch_false = alloc->make<Error>(ast->location, EF, ast->message);
            ast_ = alloc->make<Conditional>(ast->location, ast->openFodder,
                                            ast->cond, EF, ast->rest, EF, branch_false);

        } else if (auto *ast = dynamic_cast<Binary*>(ast_)) {
            desugar(ast->left, obj_level);
            desugar(ast->right, obj_level);

            bool invert = false;

            switch (ast->op) {
                case BOP_PERCENT: {
                    AST *f_mod = alloc->make<Index>(E, EF, std(), EF, false, str(U"mod"), EF,
                                                    nullptr, EF, nullptr, EF);
                    Apply::Args args = {{ast->left, EF}, {ast->right, EF}};
                    ast_ = alloc->make<Apply>(ast->location, ast->openFodder, f_mod, EF, args,
                                              false, EF, EF, false);
                } break;

                case BOP_MANIFEST_UNEQUAL:
                invert = true;
                case BOP_MANIFEST_EQUAL: {
                    ast_ = equals(ast->location, ast->left, ast->right);
                    if (invert)
                        ast_ = alloc->make<Unary>(ast->location, ast->openFodder, UOP_NOT, ast_);
                }
                break;

                default:;
                // Otherwise don't change it.
            }

        } else if (dynamic_cast<const BuiltinFunction*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Conditional*>(ast_)) {
            desugar(ast->cond, obj_level);
            desugar(ast->branchTrue, obj_level);
            if (ast->branchFalse == nullptr)
                ast->branchFalse = alloc->make<LiteralNull>(LocationRange(), EF);
            desugar(ast->branchFalse, obj_level);

        } else if (auto *ast = dynamic_cast<Dollar*>(ast_)) {
            if (obj_level == 0) {
                throw StaticError(ast->location, "No top-level object found.");
            }
            ast_ = alloc->make<Var>(ast->location, EF, alloc->makeIdentifier(U"$"));

        } else if (auto *ast = dynamic_cast<Error*>(ast_)) {
            desugar(ast->expr, obj_level);

        } else if (auto *ast = dynamic_cast<Function*>(ast_)) {
            desugar(ast->body, obj_level);

        } else if (dynamic_cast<const Import*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const Importstr*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<Index*>(ast_)) {
            desugar(ast->target, obj_level);
            if (ast->isSlice) {
                if (ast->index == nullptr)
                    ast->index = make<LiteralNull>(ast->location, EF);
                desugar(ast->index, obj_level);

                if (ast->end == nullptr)
                    ast->end = make<LiteralNull>(ast->location, EF);
                desugar(ast->end, obj_level);

                if (ast->step == nullptr)
                    ast->step = make<LiteralNull>(ast->location, EF);
                desugar(ast->step, obj_level);

                ast_ = make<Apply>(
                    ast->location,
                    EF,
                    make<Index>(
                        E, EF, std(), EF, false, str(U"slice"), EF, nullptr, EF, nullptr, EF),
                    EF,
                    std::vector<Apply::Arg>{
                        {ast->target, EF},
                        {ast->index, EF},
                        {ast->end, EF},
                        {ast->step, EF},
                    },
                    false,  // trailing comma
                    EF,
                    EF,
                    false  // tailstrict
                );
            } else {
                if (ast->id != nullptr) {
                    assert(ast->index == nullptr);
                    ast->index = str(ast->id->name);
                    ast->id = nullptr;
                }
                desugar(ast->index, obj_level);
            }

        } else if (auto *ast = dynamic_cast<Local*>(ast_)) {
            for (auto &bind: ast->binds)
                desugar(bind.body, obj_level);
            desugar(ast->body, obj_level);

            for (auto &bind: ast->binds) {
                if (bind.functionSugar) {
                    bind.body = alloc->make<Function>(
                        ast->location, ast->openFodder, bind.parenLeftFodder, bind.params, false,
                        bind.parenRightFodder, bind.body);
                    bind.functionSugar = false;
                    bind.params.clear();
                }
            }

        } else if (dynamic_cast<const LiteralBoolean*>(ast_)) {
            // Nothing to do.

        } else if (dynamic_cast<const LiteralNumber*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<LiteralString*>(ast_)) {
            if (ast->tokenKind != LiteralString::BLOCK) {
                ast->value = jsonnet_string_unescape(ast->location, ast->value);
            }
            ast->tokenKind = LiteralString::DOUBLE;
            ast->blockIndent.clear();

        } else if (dynamic_cast<const LiteralNull*>(ast_)) {
            // Nothing to do.

        } else if (auto *ast = dynamic_cast<DesugaredObject*>(ast_)) {
            for (auto &field : ast->fields) {
                desugar(field.name, obj_level);
                desugar(field.body, obj_level + 1);
            }
            for (AST *assert : ast->asserts) {
                desugar(assert, obj_level + 1);
            }

        } else if (auto *ast = dynamic_cast<Object*>(ast_)) {
            // Hidden variable to allow outer/top binding.
            if (obj_level == 0) {
                const Identifier *hidden_var = alloc->makeIdentifier(U"$");
                auto *body = alloc->make<Self>(E, EF);
                ast->fields.push_back(ObjectField::Local(EF, EF, hidden_var, EF, body, EF));
            }

            desugarFields(ast, ast->fields, obj_level);

            DesugaredObject::Fields new_fields;
            ASTs new_asserts;
            for (const ObjectField &field : ast->fields) {
                if (field.kind == ObjectField::ASSERT) {
                    new_asserts.push_back(field.expr2);
                } else if (field.kind == ObjectField::FIELD_EXPR) {
                    new_fields.emplace_back(field.hide, field.expr1, field.expr2);
                } else {
                    std::cerr << "INTERNAL ERROR: field should have been desugared: "
                              << field.kind << std::endl;
                }
            }
            ast_ = alloc->make<DesugaredObject>(ast->location, new_asserts, new_fields);

        } else if (auto *ast = dynamic_cast<ObjectComprehension*>(ast_)) {
            // Hidden variable to allow outer/top binding.
            if (obj_level == 0) {
                const Identifier *hidden_var = alloc->makeIdentifier(U"$");
                auto *body = alloc->make<Self>(E, EF);
                ast->fields.push_back(ObjectField::Local(EF, EF, hidden_var, EF, body, EF));
            }

            desugarFields(ast, ast->fields, obj_level);

            for (ComprehensionSpec &spec : ast->specs)
                desugar(spec.expr, obj_level);

            AST *field = ast->fields.front().expr1;
            AST *value = ast->fields.front().expr2;

            /*  {
                    [arr[0]]: local x = arr[1], y = arr[2], z = arr[3]; val_expr
                    for arr in [ [key_expr, x, y, z] for ...  ]
                }
            */
            auto *_arr = id(U"$arr");
            AST *zero = make<LiteralNumber>(E, EF, "0.0");
            int counter = 1;
            Local::Binds binds;
            Array::Elements arr_e {Array::Element(field, EF)};
            for (ComprehensionSpec &spec : ast->specs) {
                if (spec.kind == ComprehensionSpec::FOR) {
                    std::stringstream num;
                    num << counter++;
                    binds.push_back(bind(
                        spec.var,
                        make<Index>(E, EF, var(_arr), EF, false,
                                    make<LiteralNumber>(E, EF, num.str()), EF, nullptr, EF, nullptr,
                                    EF)));
                    arr_e.emplace_back(var(spec.var), EF);
                }
            }
            AST *arr = make<ArrayComprehension>(
                ast->location,
                EF,
                make<Array>(ast->location, EF, arr_e, false, EF),
                EF,
                false,
                ast->specs,
                EF);
            desugar(arr, obj_level);
            ast_ = make<ObjectComprehensionSimple>(
                ast->location,
                make<Index>(E, EF, var(_arr), EF, false, zero, EF, nullptr, EF, nullptr, EF),
                make<Local>(
                    ast->location,
                    EF,
                    binds,
                    value),
                _arr,
                arr);

        } else if (auto *ast = dynamic_cast<ObjectComprehensionSimple*>(ast_)) {
            desugar(ast->field, obj_level);
            desugar(ast->value, obj_level + 1);
            desugar(ast->array, obj_level);

        } else if (auto *ast = dynamic_cast<Parens*>(ast_)) {
            // Strip parens.
            desugar(ast->expr, obj_level);
            ast_ = ast->expr;

        } else if (dynamic_cast<const Self*>(ast_)) {
            // Nothing to do.

        } else if (auto * ast = dynamic_cast<SuperIndex*>(ast_)) {
            if (ast->id != nullptr) {
                assert(ast->index == nullptr);
                ast->index = str(ast->id->name);
                ast->id = nullptr;
            }
            desugar(ast->index, obj_level);

        } else if (auto *ast = dynamic_cast<Unary*>(ast_)) {
            desugar(ast->expr, obj_level);

        } else if (dynamic_cast<const Var*>(ast_)) {
            // Nothing to do.

        } else {
            std::cerr << "INTERNAL ERROR: Unknown AST: " << ast_ << std::endl;
            std::abort();

        }
    }