Esempio n. 1
0
void cw__test_helpers_check_client_interface_args(DjinniWrapperClientInterface * i) {
    djinni::Handle<DjinniWrapperClientInterface> _i(i, client_interface___wrapper_dec_ref);
    try {
        ::testsuite::TestHelpers::check_client_interface_args(DjinniWrapperClientInterface::get(std::move(_i)));
    }
    CW_TRANSLATE_EXCEPTIONS_RETURN();
}
Esempio n. 2
0
DjinniRecordHandle * cw__test_helpers_assorted_primitives_id(DjinniRecordHandle * i) {
    djinni::Handle<DjinniRecordHandle> _i(i, assorted_primitives___delete);
    try {
        return DjinniAssortedPrimitives::fromCpp(::testsuite::TestHelpers::assorted_primitives_id(DjinniAssortedPrimitives::toCpp(std::move(_i)))).release();
    }
    CW_TRANSLATE_EXCEPTIONS_RETURN(0);
}
Esempio n. 3
0
EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
{
    EGLContext context = egl_tls_t::getContext();
    if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
        return EGL_NO_IMAGE_KHR;

    egl_context_t const * const c = get_context(context);
    if (c == NULL) // this should never happen, by construction
        return EGL_NO_IMAGE_KHR;

    egl_display_t* display = egl_display_t::get(c->dpy);
    if (display == NULL) // this should never happen, by construction
        return EGL_NO_IMAGE_KHR;

    ImageRef _i(display, image);
    if (!_i.get())
        return EGL_NO_IMAGE_KHR;

    // here we don't validate the context because if it's been marked for
    // termination, this call should still succeed since it's internal to
    // EGL.

    egl_image_t const * const i = get_image(image);
    return i->images[c->impl];
}
Esempio n. 4
0
int
main(int argc, char **argv)
{
    int		errflag = 0;
    int		sts;
    int		c;

    __pmSetProgname(argv[0]);

    indomp = (__pmInDom_int *)&indom;

    while ((c = getopt(argc, argv, "D:")) != EOF) {
	switch (c) {

#ifdef PCP_DEBUG
	case 'D':	/* debug flag */
	    sts = __pmParseDebug(optarg);
	    if (sts < 0) {
		fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n",
		    pmProgname, optarg);
		errflag++;
	    }
	    else
		pmDebug |= sts;
	    break;
#endif

	case '?':
	default:
	    errflag++;
	    break;
	}
    }

    if (errflag) {
	fprintf(stderr, "Usage: %s [-D...] [a|b|c|d|...|i 1|2|3}\n", pmProgname);
	exit(1);
    }

    while (optind < argc) {
	if (strcmp(argv[optind], "a") == 0) _a(0, 1, 1);
	else if (strcmp(argv[optind], "b") == 0) _b();
	else if (strcmp(argv[optind], "c") == 0) _c();
	else if (strcmp(argv[optind], "d") == 0) _a(1, 0, 1);
	else if (strcmp(argv[optind], "e") == 0) _e(0);
	else if (strcmp(argv[optind], "f") == 0) _e(3600);
	else if (strcmp(argv[optind], "g") == 0) _g();
	else if (strcmp(argv[optind], "h") == 0) _h();
	else if (strcmp(argv[optind], "i") == 0) {
	    optind++;
	    _i(atoi(argv[optind]));
	}
	else if (strcmp(argv[optind], "j") == 0) _j();
	else
	    fprintf(stderr, "torture_cache: no idea what to do with option \"%s\"\n", argv[optind]);
	optind++;
    }

    exit(0);
}
Esempio n. 5
0
DjinniBoxedI32 * cw__foo_receiver_cause_changes_int_optional_returned(DjinniWrapperFooReceiver * djinni_this, DjinniBoxedI32 * i, float f, DjinniString * s, DjinniBinary * binar, bool b, uint64_t d) {
    std::unique_ptr<DjinniBoxedI32> _i(i);
    std::unique_ptr<DjinniString> _s(s);
    std::unique_ptr<DjinniBinary> _binar(binar);
    try {
        return DjinniBoxedI32::fromCpp(djinni_this->wrapped_obj->cause_changes_int_optional_returned(DjinniBoxedI32::toCpp(std::move(_i)), f, DjinniOptionalString::toCpp(std::move(_s)), DjinniBinary::toCpp(std::move(_binar)), b, DjinniDate::toCpp(d))).release();
    } CW_TRANSLATE_EXCEPTIONS_RETURN(0);
}
Esempio n. 6
0
void
test1()
{
  long double x = operator"" _v(1.2L);
  assert(x == 2.2L);

  std::string s = operator"" _w(u"one", 3);
  assert(s == "boo");

  unsigned u = operator"" _w("Hello, World!");
  assert(u == 13U);

  std::complex<double> i = operator"" _i(2.0);
  assert(i == std::complex<double>(0.0, 2.0));
}
Esempio n. 7
0
/**
 * Drop the (unit) diagonal entries from a cholmod_sparse matrix
 *
 * @param chx   cholmod_sparse matrix.
 *              Note that the matrix "slots" are modified _in place_
 * @param uploT integer code (= +/- 1) indicating if chx is
 *              upper (+1) or lower (-1) triangular
 * @param do_realloc  Rboolean indicating, if a cholmod_sprealloc() should
 *              finalize the procedure; not needed, e.g. when the
 *              result is converted to a SEXP immediately afterwards.
 */
void chm_diagN2U(CHM_SP chx, int uploT, Rboolean do_realloc)
{
    int i, n = chx->nrow, nnz = (int)cholmod_nnz(chx, &c),
	n_nnz = nnz - n, /* the new nnz : we will have removed  n entries */
	i_to = 0, i_from = 0;

    if(chx->ncol != n)
	error(_("chm_diagN2U(<non-square matrix>): nrow=%d, ncol=%d"),
	      n, chx->ncol);

    if (!chx->sorted || !chx->packed) cholmod_sort(chx, &c);
				/* dimensions and nzmax */

#define _i(I) (   (int*) chx->i)[I]
#define _x(I) ((double*) chx->x)[I]
#define _p(I) (   (int*) chx->p)[I]

    /* work by copying from i_from to i_to ==> MUST i_to <= i_from */

    if(uploT == 1) { /* "U" : upper triangular */

	for(i = 0; i < n; i++) { /* looking at i-th column */
	    int j, n_i = _p(i+1) - _p(i); /* = #{entries} in this column */

	    /* 1) copy all but the last _above-diagonal_ column-entries: */
	    for(j = 1; j < n_i; j++, i_to++, i_from++) {
		_i(i_to) = _i(i_from);
		_x(i_to) = _x(i_from);
	    }

	    /* 2) drop the last column-entry == diagonal entry */
	    i_from++;
	}
    }
    else if(uploT == -1) { /* "L" : lower triangular */

	for(i = 0; i < n; i++) { /* looking at i-th column */
	    int j, n_i = _p(i+1) - _p(i); /* = #{entries} in this column */

	    /* 1) drop the first column-entry == diagonal entry */
	    i_from++;

	    /* 2) copy the other _below-diagonal_ column-entries: */
	    for(j = 1; j < n_i; j++, i_to++, i_from++) {
		_i(i_to) = _i(i_from);
		_x(i_to) = _x(i_from);
	    }
	}
    }
    else {
	error(_("chm_diagN2U(x, uploT = %d): uploT should be +- 1"), uploT);
    }

    /* the column pointers are modified the same in both cases :*/
    for(i=1; i <= n; i++)
	_p(i) -= i;

#undef _i
#undef _x
#undef _p

    if(do_realloc) /* shorten (i- and x-slots from nnz to n_nnz */
	cholmod_reallocate_sparse(n_nnz, chx, &c);
    return;
}
DjinniString * cw__reverse_client_interface_meth_taking_optional_interface(DjinniWrapperReverseClientInterface * djinni_this, DjinniWrapperReverseClientInterface * i) {
    djinni::Handle<DjinniWrapperReverseClientInterface> _i(i, reverse_client_interface___wrapper_dec_ref);
    try {
        return DjinniString::fromCpp(djinni_this->wrapped_obj->meth_taking_optional_interface(DjinniWrapperReverseClientInterface::get(std::move(_i)))).release();
    } CW_TRANSLATE_EXCEPTIONS_RETURN(0);
}
Esempio n. 9
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();

        }
    }
Esempio n. 10
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();

        }
    }