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; }
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; }
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(); } }
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(); } }