text:
// Copyright 2021 The XLS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "xls/dslx/bytecode_interpreter.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/match.h"
#include "xls/common/file/temp_file.h"
#include "xls/common/status/matchers.h"
#include "xls/dslx/bytecode_emitter.h"
#include "xls/dslx/create_import_data.h"
#include "xls/dslx/import_data.h"
#include "xls/dslx/interp_value.h"
#include "xls/dslx/parse_and_typecheck.h"
#include "xls/dslx/run_routines.h"

namespace xls::dslx {
namespace {

using status_testing::IsOkAndHolds;
using status_testing::StatusIs;
using testing::HasSubstr;

TEST(BytecodeInterpreterTest, TraceDataToString) {
  std::vector<InterpValue> stack = {
      InterpValue::MakeUBits(8, /*value=*/0x42),
      InterpValue::MakeUBits(3, /*value=*/4),
  };
  XLS_ASSERT_OK_AND_ASSIGN(std::vector<FormatStep> steps,
                           ParseFormatString("x: {:x} y: {}"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::string result, BytecodeInterpreter::TraceDataToString(steps, stack));
  EXPECT_TRUE(stack.empty());
  EXPECT_EQ("x: 42 y: 4", result);
}

absl::StatusOr<InterpValue> Interpret(ImportData* import_data,
                                      std::string_view program,
                                      std::string_view entry,
                                      std::vector<InterpValue> args = {}) {
  XLS_ASSIGN_OR_RETURN(
      TypecheckedModule tm,
      ParseAndTypecheck(program, "test.x", "test", import_data));

  XLS_ASSIGN_OR_RETURN(Function * f,
                       tm.module->GetMemberOrError<Function>(entry));
  XLS_ASSIGN_OR_RETURN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(import_data, tm.type_info, f, SymbolicBindings()));

  return BytecodeInterpreter::Interpret(import_data, bf.get(), args);
}

static const Pos kFakePos("fake.x", 0, 0);
static const Span kFakeSpan = Span(kFakePos, kFakePos);

TEST(BytecodeInterpreterTest, DupLiteral) {
  std::vector<Bytecode> bytecodes;
  bytecodes.emplace_back(kFakeSpan, Bytecode::Op::kLiteral,
                         InterpValue::MakeU32(42));
  bytecodes.emplace_back(kFakeSpan, Bytecode::Op::kDup);
  XLS_ASSERT_OK_AND_ASSIGN(
      auto bfunc,
      BytecodeFunction::Create(/*owner=*/nullptr, /*source_fn=*/nullptr,
                               /*type_info=*/nullptr, std::move(bytecodes)));
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue result,
                           BytecodeInterpreter::Interpret(
                               /*import_data=*/nullptr, bfunc.get(), {}));
  EXPECT_EQ(result.ToString(), "u32:42");
}

TEST(BytecodeInterpreterTest, DupEmptyStack) {
  std::vector<Bytecode> bytecodes;
  bytecodes.emplace_back(kFakeSpan, Bytecode::Op::kDup);
  XLS_ASSERT_OK_AND_ASSIGN(
      auto bfunc,
      BytecodeFunction::Create(/*owner=*/nullptr, /*source_fn=*/nullptr,
                               /*type_info=*/nullptr, std::move(bytecodes)));
  ASSERT_THAT(
      BytecodeInterpreter::Interpret(/*import_data=*/nullptr, bfunc.get(), {}),
      StatusIs(absl::StatusCode::kInternal,
               ::testing::HasSubstr("!stack_.empty()")));
}

// Interprets a nearly-minimal bytecode program; the same from
// BytecodeEmitterTest.SimpleTranslation.
TEST(BytecodeInterpreterTest, PositiveSmokeTest) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  let a = u32:1;
  a + u32:2
}
)";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_EQ(value, InterpValue::MakeU32(3));
}

// Tests that a failing assert_eq is interpreted correctly. Again, a
// continuation of a test from BytecodeEmitterTest. Get used to it.
TEST(BytecodeInterpreterTest, AssertEqFail) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32{
  let a = u32:3;
  let _ = assert_eq(a, u32:2);
  a
}
)";

  ImportData import_data(CreateImportDataForTest());
  absl::StatusOr<InterpValue> value = Interpret(&import_data, kProgram, "main");
  EXPECT_THAT(value.status(), StatusIs(absl::StatusCode::kInternal,
                                       HasSubstr("were not equal")));
}

TEST(BytecodeInterpreterTest, AssertLtFail) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32{
  let a = u32:3;
  let _ = assert_lt(a, u32:2);
  a
}
)";

  ImportData import_data(CreateImportDataForTest());
  absl::StatusOr<InterpValue> value = Interpret(&import_data, kProgram, "main");
  EXPECT_THAT(value.status(), StatusIs(absl::StatusCode::kInternal,
                                       HasSubstr("not less than")));
}

// This test won't work unless BytecodeEmitterTest.DestructuringLet works!
TEST(BytecodeInterpreterTest, DestructuringLet) {
  constexpr std::string_view kProgram = R"(
fn has_name_def_tree() -> (u32, u64, uN[128]) {
  let (a, b, (c, d)) = (u4:0, u8:1, (u16:2, (u32:3, u64:4, uN[128]:5)));
  let _ = assert_eq(a, u4:0);
  let _ = assert_eq(b, u8:1);
  let _ = assert_eq(c, u16:2);
  let _ = assert_eq(d, (u32:3, u64:4, uN[128]:5));
  d
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "has_name_def_tree"));

  ASSERT_TRUE(value.IsTuple());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t num_elements, value.GetLength());
  ASSERT_EQ(num_elements, 3);
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue element,
                           value.Index(InterpValue::MakeU32(0)));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 3);

  XLS_ASSERT_OK_AND_ASSIGN(element, value.Index(InterpValue::MakeU32(1)));
  XLS_ASSERT_OK_AND_ASSIGN(bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 4);

  XLS_ASSERT_OK_AND_ASSIGN(element, value.Index(InterpValue::MakeU32(2)));
  XLS_ASSERT_OK_AND_ASSIGN(bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 5);
}

TEST(BytecodeInterpreterTest, RunMatchArms) {
  constexpr std::string_view kProgram = R"(
fn main(x: u32) -> u32 {
  match x {
    u32:42 => u32:64,
    u32:64 => u32:42,
    _ => x + u32:1
  }
})";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, BytecodeInterpreter::Interpret(
                                                  &import_data, bf.get(),
                                                  {InterpValue::MakeU32(42)}));
  EXPECT_EQ(value, InterpValue::MakeU32(64)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(&import_data, bf.get(),
                                            {InterpValue::MakeU32(64)}));
  EXPECT_EQ(value, InterpValue::MakeU32(42)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(&import_data, bf.get(),
                                            {InterpValue::MakeU32(77)}));
  EXPECT_EQ(value, InterpValue::MakeU32(78)) << value.ToString();
}

TEST(BytecodeInterpreterTest, RunMatchArmsTuplePattern) {
  constexpr std::string_view kProgram = R"(
fn main(t: (u32, u32)) -> u32 {
  match t {
    (u32:42, u32:64) => u32:1,
    (u32:64, u32:42) => u32:2,
    _ => u32:3,
  }
})";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  auto tuple_one = InterpValue::MakeTuple(
      {InterpValue::MakeU32(42), InterpValue::MakeU32(64)});
  auto tuple_two = InterpValue::MakeTuple(
      {InterpValue::MakeU32(64), InterpValue::MakeU32(42)});
  auto tuple_three = InterpValue::MakeTuple(
      {InterpValue::MakeU32(64), InterpValue::MakeU32(64)});
  auto tuple_four = InterpValue::MakeTuple(
      {InterpValue::MakeU32(42), InterpValue::MakeU32(42)});

  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(&import_data, bf.get(), {tuple_one}));
  EXPECT_EQ(value, InterpValue::MakeU32(1)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(value, BytecodeInterpreter::Interpret(
                                      &import_data, bf.get(), {tuple_two}));
  EXPECT_EQ(value, InterpValue::MakeU32(2)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(value, BytecodeInterpreter::Interpret(
                                      &import_data, bf.get(), {tuple_three}));
  EXPECT_EQ(value, InterpValue::MakeU32(3)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(value, BytecodeInterpreter::Interpret(
                                      &import_data, bf.get(), {tuple_four}));
  EXPECT_EQ(value, InterpValue::MakeU32(3)) << value.ToString();
}

TEST(BytecodeInterpreterTest, RunMatchArmIrrefutablePattern) {
  constexpr std::string_view kProgram = R"(
fn main(x: u32) -> u32 {
  match x {
    u32:42 => u32:64,
    y => y + u32:1,
    _ => u32:128,
  }
})";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, BytecodeInterpreter::Interpret(
                                                  &import_data, bf.get(),
                                                  {InterpValue::MakeU32(42)}));
  EXPECT_EQ(value, InterpValue::MakeU32(64)) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(&import_data, bf.get(),
                                            {InterpValue::MakeU32(43)}));
  EXPECT_EQ(value, InterpValue::MakeU32(44)) << value.ToString();
}

TEST(BytecodeInterpreterTest, RunMatchNoTrailingWildcard) {
  constexpr std::string_view kProgram = R"(
fn main(x: u32) -> u32 {
  match x {
    y => y + u32:1,
  }
})";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, BytecodeInterpreter::Interpret(
                                                  &import_data, bf.get(),
                                                  {InterpValue::MakeU32(1)}));
  EXPECT_EQ(value, InterpValue::MakeU32(2));
}

TEST(BytecodeInterpreterTest, RunMatchNoMatch) {
  constexpr std::string_view kProgram = R"(
fn main(x: u32) -> u32 {
  match x {
    u32:1 => u32:2,
  }
})";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));
  absl::StatusOr<InterpValue> value = BytecodeInterpreter::Interpret(
      &import_data, bf.get(), {InterpValue::MakeU32(2)});
  EXPECT_THAT(value.status(), StatusIs(absl::StatusCode::kInternal,
                                       HasSubstr("The value was not matched")));
}

TEST(BytecodeInterpreterTest, RunMatchWithNameRefs) {
  constexpr std::string_view kProgram = R"(
fn main(x: u32, y: u32, z: u32) -> u32 {
  match x {
    y => x + y,
    z => x + z,
    _ => u32:0xdeadbeef,
  }
}
)";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, /*path=*/"test.x", /*module_name=*/"test",
                        &import_data));
  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  InterpValue one(InterpValue::MakeU32(1));
  InterpValue two(InterpValue::MakeU32(2));
  InterpValue three(InterpValue::MakeU32(3));
  InterpValue four(InterpValue::MakeU32(4));
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(&import_data, bf.get(), {one, one, two}));
  EXPECT_EQ(value, two) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(value, BytecodeInterpreter::Interpret(
                                      &import_data, bf.get(), {two, one, two}));
  EXPECT_EQ(value, four) << value.ToString();

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(&import_data, bf.get(),
                                            {three, one, two}));
  EXPECT_EQ(value, InterpValue::MakeU32(0xdeadbeef)) << value.ToString();
}

TEST(BytecodeInterpreterTest, RunTernaryConsequent) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  if true { u32:42 } else { u32:64 }
}
)";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_EQ(value, InterpValue::MakeU32(42)) << value.ToString();
}

TEST(BytecodeInterpreterTest, RunTernaryAlternate) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  if false { u32:42 } else { u32:64 }
}
)";

  ImportData import_data(CreateImportDataForTest());
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_EQ(value, InterpValue::MakeU32(64)) << value.ToString();
}

TEST(BytecodeInterpreterTest, BinopAnd) {
  constexpr std::string_view kProgram = R"(
fn do_and() -> u32 {
  let a = u32:0xa5a5a5a5;
  let b = u32:0xffffffff;
  a & b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_and"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0xa5a5a5a5ll);
}

TEST(BytecodeInterpreterTest, BinopConcat) {
  constexpr std::string_view kProgram = R"(
fn do_concat() -> u64 {
  let a = u32:0xa5a5a5a5;
  let b = u32:0xffffffff;
  a ++ b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_concat"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0xa5a5a5a5ffffffffll);
}

TEST(BytecodeInterpreterTest, BinopDiv) {
  constexpr std::string_view kProgram = R"(
fn do_div() -> u32 {
  let a = u32:0x84208420;
  let b = u32:0x4;
  a / b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_div"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x21082108);
}

TEST(BytecodeInterpreterTest, BinopMul) {
  constexpr std::string_view kProgram = R"(
fn do_mul() -> u32 {
  let a = u32:0x21082108;
  let b = u32:0x4;
  a * b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_mul"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x84208420);
}

TEST(BytecodeInterpreterTest, BinopOr) {
  constexpr std::string_view kProgram = R"(
fn do_or() -> u32 {
  let a = u32:0xa5a5a5a5;
  let b = u32:0x5a5a5a5a;
  a | b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_or"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0xffffffff);
}

TEST(BytecodeInterpreterTest, BinopShll) {
  constexpr std::string_view kProgram = R"(
fn do_shll() -> u32 {
  let a = u32:0x21082108;
  let b = u32:0x2;
  a << b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_shll"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x84208420);
}

TEST(BytecodeInterpreterTest, BinopShra) {
  constexpr std::string_view kProgram = R"(
fn do_shrl() -> s32 {
  let a = s32:-128;
  let b = u32:2;
  a >> b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_shrl"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_val, bits.ToInt64());
  EXPECT_EQ(int_val, -32);
}

TEST(BytecodeInterpreterTest, BinopShrl) {
  constexpr std::string_view kProgram = R"(
fn do_shrl() -> u32 {
  let a = u32:0x84208420;
  let b = u32:0x2;
  a >> b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_shrl"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x21082108);
}

TEST(BytecodeInterpreterTest, BinopSub) {
  constexpr std::string_view kProgram = R"(
fn do_sub() -> u32 {
  let a = u32:0xa5a5a5a5;
  let b = u32:0x5a5a5a5a;
  a - b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_sub"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x4b4b4b4b);
}

TEST(BytecodeInterpreterTest, BinopXor) {
  constexpr std::string_view kProgram = R"(
fn do_xor() -> u32 {
  let a = u32:0xa5a5ffff;
  let b = u32:0x5a5affff;
  a ^ b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "do_xor"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0xffff0000);
}

TEST(BytecodeInterpreterTest, Unops) {
  constexpr std::string_view kProgram = R"(
fn unops() -> s32 {
  let a = s32:1;
  let b = !a;
  -b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "unops"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x2);
}

TEST(BytecodeInterpreterTest, CreateArray) {
  constexpr std::string_view kProgram = R"(
fn arrays() -> u32[3] {
  let a = u32:32;
  u32[3]:[u32:0, u32:1, a]
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "arrays"));
  ASSERT_TRUE(value.IsArray());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t num_elements, value.GetLength());
  ASSERT_EQ(num_elements, 3);
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue element,
                           value.Index(InterpValue::MakeU32(0)));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 0);

  XLS_ASSERT_OK_AND_ASSIGN(element, value.Index(InterpValue::MakeU32(1)));
  XLS_ASSERT_OK_AND_ASSIGN(bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 1);

  XLS_ASSERT_OK_AND_ASSIGN(element, value.Index(InterpValue::MakeU32(2)));
  XLS_ASSERT_OK_AND_ASSIGN(bit_value, element.GetBitValueInt64());
  EXPECT_EQ(bit_value, 32);
}

TEST(BytecodeInterpreterTest, IndexArray) {
  constexpr std::string_view kProgram = R"(
fn index_array() -> u32 {
  let a = u32[3]:[0, 1, 2];
  let b = bits[32][3]:[3, 4, 5];

  a[u32:0] + b[u32:1]
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "index_array"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToInt64());
  EXPECT_EQ(int_value, 4);
}

TEST(BytecodeInterpreterTest, IndexTuple) {
  constexpr std::string_view kProgram = R"(
fn index_tuple() -> u32 {
  let a = (u32:0, (u32:1, u32:2));
  let b = ((u32:3, (u32:4,)), u32:5);

  a.1.1 + b.0.1.0
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "index_tuple"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToInt64());
  EXPECT_EQ(int_value, 6);
}

TEST(BytecodeInterpreterTest, SimpleBitSlice) {
  constexpr std::string_view kProgram = R"(
fn simple_slice() -> u16 {
  let a = u32:0xdeadbeef;
  a[16:32]
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "simple_slice"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0xdead);
}

// Tests a slice from the start: a[-x:].
TEST(BytecodeInterpreterTest, NegativeStartSlice) {
  constexpr std::string_view kProgram = R"(
fn negative_start_slice() -> u16 {
  let a = u32:0xdeadbeef;
  a[-16:]
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      Interpret(&import_data, kProgram, "negative_start_slice"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0xdead);
}

// Tests a slice from the end: a[:-x].
TEST(BytecodeInterpreterTest, NegativeEndSlice) {
  constexpr std::string_view kProgram = R"(
fn negative_end_slice() -> u16 {
  let a = u32:0xdeadbeef;
  a[:-16]
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "negative_end_slice"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0xbeef);
}

TEST(BytecodeInterpreterTest, WidthSlice) {
  constexpr std::string_view kProgram = R"(
fn width_slice() -> s16 {
  let a = u32:0xdeadbeef;
  a[u32:8 +: s16]
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "width_slice"));
  ASSERT_TRUE(value.IsBits());
  ASSERT_TRUE(value.IsSigned());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0xadbe);
}

// Makes sure we properly handle an OOB width slice and don't leave an extra
// value on the stack.
TEST(BytecodeInterpreterTest, OobWidthSlice) {
  constexpr std::string_view kProgram = R"(
fn oob_slicer(a: u32) -> (u32, u32) {
  let b = u32:0xfeedf00d;
  let c = uN[128]:0xffffffffffffffffffffffffffffffff;
  let d = (u32:0xffffffff)[c +: u16];
  (a, b)
}

fn oob_width_slice() -> (u32, u32)[4] {
  let a = u32[4]:[u32:0, u32:1, u32:2, u32:3];
  map(a, oob_slicer)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue result, Interpret(&import_data, kProgram, "oob_width_slice"));
  XLS_ASSERT_OK_AND_ASSIGN(const std::vector<InterpValue>* array_elements,
                           result.GetValues());
  for (int i = 0; i < array_elements->size(); i++) {
    XLS_ASSERT_OK_AND_ASSIGN(const std::vector<InterpValue>* tuple_elements,
                             array_elements->at(i).GetValues());
    XLS_ASSERT_OK_AND_ASSIGN(uint64_t value,
                             tuple_elements->at(0).GetBitValueUint64());
    EXPECT_EQ(value, i);
    XLS_ASSERT_OK_AND_ASSIGN(value, tuple_elements->at(1).GetBitValueUint64());
    EXPECT_EQ(value, 0xfeedf00d);
  }
}

TEST(BytecodeInterpreterTest, WidthSliceWithZext) {
  constexpr std::string_view kProgram = R"(
fn width_slice() -> u32 {
  let a = u32:0xdeadbeef;
  a[u32:16 +: u32]
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "width_slice"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0x0000dead);
}

// Tests a slice from both ends: a[-x:-y].
TEST(BytecodeInterpreterTest, BothNegativeSlice) {
  constexpr std::string_view kProgram = R"(
fn both_negative_slice() -> u8 {
  let a = u32:0xdeadbeef;
  a[-16:-8]
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "both_negative_slice"));
  ASSERT_TRUE(value.IsBits());
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitsOrDie().ToUint64());
  EXPECT_EQ(int_value, 0xad);
}

TEST(BytecodeInterpreterTest, CastBits_Extend) {
  constexpr std::string_view kProgram = R"(
fn cast_extend() -> u32 {
  let a = u16:0xa5a5;
  let b = s16:0x8000;
  a as u32 + ((b as s32) as u32)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "cast_extend"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x25a5);
}

TEST(BytecodeInterpreterTest, CastBits_SignExtend) {
  constexpr std::string_view kProgram = R"(
fn cast_sign_extend() -> s32 {
  let a = s16:0xffff;
  a as s32
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value, Interpret(&import_data, kProgram, "cast_sign_extend"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToInt64());
  EXPECT_EQ(int_val, -1);
}

TEST(BytecodeInterpreterTest, CastBits_Shrink) {
  constexpr std::string_view kProgram = R"(
fn cast_shrink() -> u16 {
  let a = u32:0x0000a5a5;
  let b = s32:0x8fff5a5a;
  a as u16 + b as u16
})";
  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "cast_shrink"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0xffff);
}

TEST(BytecodeInterpreterTest, CastArrayToBits) {
  constexpr std::string_view kProgram = R"(
fn cast_array_to_bits() -> u32 {
  let a = u8[4]:[0xc, 0xa, 0xf, 0xe];
  a as u32
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "cast_array_to_bits"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x0c0a0f0e);
}

TEST(BytecodeInterpreterTest, CastBitsToArray) {
  constexpr std::string_view kProgram = R"(
fn cast_bits_to_array() -> u8 {
  let a = u32:0x0c0a0f0e;
  let b = a as u8[4];
  b[u32:2]
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "cast_bits_to_array"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 0x0f);
}

TEST(BytecodeInterpreterTest, CastEnumToBits) {
  constexpr std::string_view kProgram = R"(enum MyEnum : u3 {
  VAL_0 = 0,
  VAL_1 = 1,
  VAL_2 = 2,
  VAL_3 = 3,
}

fn cast_enum_to_bits() -> u3 {
  let a = MyEnum::VAL_3;
  a as u3
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "cast_enum_to_bits"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 3);
}

TEST(BytecodeInterpreterTest, CastBitsToEnum) {
  constexpr std::string_view kProgram = R"(enum MyEnum : u3 {
  VAL_0 = 0,
  VAL_1 = 1,
  VAL_2 = 2,
  VAL_3 = 3,
}

fn cast_bits_to_enum() -> MyEnum {
  let a = u3:2;
  a as MyEnum
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value, Interpret(&import_data, kProgram,
                                                        "cast_bits_to_enum"));
  InterpValue::EnumData enum_data = value.GetEnumData().value();
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, enum_data.value.ToUint64());
  EXPECT_EQ(int_val, 2);
}

TEST(BytecodeInterpreterTest, CastWithMissingData) {
  constexpr std::string_view kProgram = R"(enum MyEnum : u3 {
  VAL_0 = 0,
  VAL_1 = 1,
  VAL_2 = 2,
  VAL_3 = 3,
}

fn cast_bits_to_enum() -> MyEnum {
  let a = u3:2;
  a as MyEnum
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(
      Function * f, tm.module->GetMemberOrError<Function>("cast_bits_to_enum"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  // Get a modifiable copy of the bytecodes.
  std::vector<Bytecode> bytecodes = bf->CloneBytecodes();

  // Clear out the data element of the last bytecode, the cast op.
  bytecodes[bytecodes.size() - 1] = Bytecode(Span::Fake(), Bytecode::Op::kCast);
  XLS_ASSERT_OK_AND_ASSIGN(bf,
                           BytecodeFunction::Create(f->owner(), f, tm.type_info,
                                                    std::move(bytecodes)));
  absl::StatusOr<InterpValue> value =
      BytecodeInterpreter::Interpret(&import_data, bf.get(), {});
  EXPECT_THAT(value.status(),
              StatusIs(absl::StatusCode::kInternal,
                       HasSubstr("Cast op requires ConcreteType data.")));
}

TEST(BytecodeInterpreterTest, Params) {
  constexpr std::string_view kProgram = R"(
fn has_params(x: u32, y: u64) -> u48 {
  let a = u48:100;
  let x = x as u48 + a;
  let y = x + y as u48;
  x + y
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("has_params"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  std::vector<InterpValue> params;
  params.push_back(InterpValue::MakeU32(1));
  params.push_back(InterpValue::MakeU64(10));
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(&import_data, bf.get(), params));

  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 212);
}

TEST(BytecodeInterpreterTest, SimpleFnCall) {
  constexpr std::string_view kProgram = R"(
fn callee(x: u32, y: u32) -> u32 {
  x + y
}

fn caller() -> u32{
  let a = u32:100;
  let b = u32:200;
  callee(a, b)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "caller"));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 300);
}

TEST(BytecodeInterpreterTest, NestedFnCalls) {
  constexpr std::string_view kProgram = R"(
fn callee_callee(x: u32) -> u32 {
  x + u32:100
}

fn callee(x: u32, y: u32) -> u32 {
  x + callee_callee(y)
}

fn caller(a: u32) -> u32{
  let b = u32:200;
  callee(a, b)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("caller"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));
  std::vector<InterpValue> params;
  params.push_back(InterpValue::MakeU32(100));
  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(&import_data, bf.get(), params));

  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  XLS_ASSERT_OK_AND_ASSIGN(uint64_t int_val, bits.ToUint64());
  EXPECT_EQ(int_val, 400);
}

TEST(BytecodeInterpreterTest, SimpleParametric) {
  constexpr std::string_view kProgram = R"(
fn foo<N: u32>(x: uN[N]) -> uN[N] {
  x * x
}

fn main() -> u32 {
  let a = foo<u32:16>(u16:4);
  let b = foo(u32:8);
  a as u32 + b
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueInt64());
  EXPECT_EQ(int_value, 80);
}

TEST(BytecodeInterpreterTest, NestedParametric) {
  constexpr std::string_view kProgram = R"(
fn second<N: u32, M: u32, O: u32>(x: uN[N], y: uN[M]) -> uN[O] {
  x as uN[O] + y as uN[O]
}

fn first<N:u32>(x: uN[N]) -> uN[N] {
  second<N, u32:48, u32:64>(x, u48:7) as uN[N]
}

fn main() -> u32 {
  first(u32:5)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueInt64());
  EXPECT_EQ(int_value, 12);
}

TEST(BytecodeInterpreterTest, ParametricStruct) {
  constexpr std::string_view kProgram = R"(
struct MyStruct<N: u32, M: u32 = N * u32:2> {
  x: uN[N],
  y: uN[M]
}

fn foo<N: u32, M: u32>(x: MyStruct<N, M>) -> u32 {
  x.x as u32 + x.y as u32
}

fn main() -> u32 {
  foo(MyStruct { x: u16:100, y: u32:200 })
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueInt64());
  EXPECT_EQ(int_value, 300);
}

TEST(BytecodeInterpreterTest, BuiltinAddWithCarry) {
  constexpr std::string_view kProgram = R"(
fn main() -> (u1, u8) {
  let x = u8:0xff;
  let y = u8:0x2;
  add_with_carry(x, y)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue actual,
                           Interpret(&import_data, kProgram, "main"));
  InterpValue expected(InterpValue::MakeTuple(
      {InterpValue::MakeUBits(1, 1), InterpValue::MakeUBits(8, 1)}));
  EXPECT_TRUE(expected.Eq(actual));
}

TEST(BytecodeInterpreterTest, BuiltinBitSlice) {
  constexpr std::string_view kProgram = R"(
fn main() -> u16 {
  bit_slice(u32:0xdeadbeef, u16:8, u16:16)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0xadbe);
}

TEST(BytecodeInterpreterTest, BuiltinBitSliceUpdate) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  bit_slice_update(u32:0xbeefbeef, u32:16, u32:0xdead)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0xdeadbeef);
}

TEST(BytecodeInterpreterTest, BuiltinClz) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  clz(u32:0xbeef)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 16);
}

TEST(BytecodeInterpreterTest, BuiltinCtz) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  ctz(u32:0xbeef0000)
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 16);
}

TEST(BytecodeInterpreterTest, BuiltinOneHot) {
  constexpr std::string_view kProgram = R"(
fn main() -> u8 {
  let input = u3:0x5;
  let r0 = one_hot(input, false);
  let r1 = one_hot(input, true);
  r0 ++ r1
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0x41);
}

TEST(BytecodeInterpreterTest, BuiltinOneHotSel) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  let cases = u32[8]:[u32:0x1, u32:0x20, u32:0x300, u32:0x4000,
                      u32:0x50000, u32:0x600000, u32:0x7000000, u32:0x80000000];
  let selector = u8:0xaa;
  one_hot_sel(selector, cases)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0x80604020);
}

TEST(BytecodeInterpreterTest, BuiltinPrioritySel) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32 {
  let cases = u32[8]:[u32:0x1, u32:0x20, u32:0x300, u32:0x4000,
                      u32:0x50000, u32:0x600000, u32:0x7000000, u32:0x80000000];
  let selector = u8:0xaa;
  priority_sel(selector, cases)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0x00000020);
}

TEST(BytecodeInterpreterTest, BuiltinRange) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32[5] {
  range(u32:100, u32:105)
}
)";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(const std::vector<InterpValue>* elements,
                           value.GetValues());
  EXPECT_EQ(elements->size(), 5);
  for (int i = 0; i < elements->size(); i++) {
    XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value,
                             elements->at(i).GetBitValueUint64());
    EXPECT_EQ(int_value, i + 100);
  }
}

TEST(BytecodeInterpreterTest, BuiltinGate) {
  constexpr std::string_view kProgram = R"(
fn main(p: bool, x: u32) -> u32 {
  gate!(p, x)
})";
  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));
  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(
          &import_data, bf.get(),
          {InterpValue::MakeBool(true), InterpValue::MakeU32(0xbeef)}));
  XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0xbeef);

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(
                 &import_data, bf.get(),
                 {InterpValue::MakeBool(false), InterpValue::MakeU32(0xbeef)}));
  XLS_ASSERT_OK_AND_ASSIGN(int_value, value.GetBitValueUint64());
  EXPECT_EQ(int_value, 0x0);
}

TEST(BytecodeInterpreterTest, BuiltinSMulp) {
  constexpr std::string_view kProgram = R"(
fn main(x: s10, y: s10) -> s10 {
  let mulp = smulp(x, y);
  mulp.0 + mulp.1
})";
  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));

  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(
          &import_data, bf.get(),
          {InterpValue::MakeSBits(10, 3), InterpValue::MakeSBits(10, -5)}));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(-15));

  XLS_ASSERT_OK_AND_ASSIGN(
      value, BytecodeInterpreter::Interpret(&import_data, bf.get(),
                                            {InterpValue::MakeSBits(10, 511),
                                             InterpValue::MakeSBits(10, -5)}));
  XLS_ASSERT_OK_AND_ASSIGN(bits, value.GetBits());
  EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(-507));
}

TEST(BytecodeInterpreterTest, BuiltinUMulp) {
  constexpr std::string_view kProgram = R"(
fn main(x: u10, y: u10) -> u10 {
  let mulp = umulp(x, y);
  mulp.0 + mulp.1
})";
  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(
      TypecheckedModule tm,
      ParseAndTypecheck(kProgram, "test.x", "test", &import_data));

  XLS_ASSERT_OK_AND_ASSIGN(Function * f,
                           tm.module->GetMemberOrError<Function>("main"));

  XLS_ASSERT_OK_AND_ASSIGN(
      std::unique_ptr<BytecodeFunction> bf,
      BytecodeEmitter::Emit(&import_data, tm.type_info, f, SymbolicBindings()));

  XLS_ASSERT_OK_AND_ASSIGN(
      InterpValue value,
      BytecodeInterpreter::Interpret(
          &import_data, bf.get(),
          {InterpValue::MakeUBits(10, 3), InterpValue::MakeUBits(10, 5)}));
  XLS_ASSERT_OK_AND_ASSIGN(Bits bits, value.GetBits());
  EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(15));

  XLS_ASSERT_OK_AND_ASSIGN(value, BytecodeInterpreter::Interpret(
                                      &import_data, bf.get(),
                                      {InterpValue::MakeUBits(10, 1023),
                                       InterpValue::MakeUBits(10, 1000)}));
  XLS_ASSERT_OK_AND_ASSIGN(bits, value.GetBits());
  EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(24));
}

TEST(BytecodeInterpreterTest, RangeExpr) {
  constexpr std::string_view kProgram = R"(
fn main() -> u32[8] {
  u32:8..u32:16
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  XLS_ASSERT_OK_AND_ASSIGN(const std::vector<InterpValue>* elements,
                           value.GetValues());
  EXPECT_EQ(elements->size(), 8);
  for (int i = 0; i < elements->size(); i++) {
    XLS_ASSERT_OK_AND_ASSIGN(int64_t int_value,
                             elements->at(i).GetBitValueUint64());
    EXPECT_EQ(int_value, i + 8);
  }
}

TEST(BytecodeInterpreterTest, TypeMaxExprU7) {
  constexpr std::string_view kProgram = R"(
fn main() -> u7 {
  u7::MAX
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_THAT(value.GetBitValueUint64(), IsOkAndHolds(0x7f));
}

TEST(BytecodeInterpreterTest, TypeMaxExprS7) {
  constexpr std::string_view kProgram = R"(
fn main() -> s3 {
  s3::MAX
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_THAT(value.GetBitValueInt64(), IsOkAndHolds(3));
}

TEST(BytecodeInterpreterTest, TypeMaxExprTypeAlias) {
  constexpr std::string_view kProgram = R"(
type MyU9 = uN[9];
fn main() -> MyU9 {
  MyU9::MAX
})";

  auto import_data = CreateImportDataForTest();
  XLS_ASSERT_OK_AND_ASSIGN(InterpValue value,
                           Interpret(&import_data, kProgram, "main"));
  EXPECT_THAT(value.GetBitValueUint64(), IsOkAndHolds(0x1ff));
}

TEST(BytecodeInterpreterTest, DistinctNestedParametricProcs) {
  // Tests that B, which has one set of parameters, can instantiate A, which has
  // a different set of parameters.
  // TODO(rspringer): Once this goes in, open a bug: if init() is changed to
  // "{ N }", it fails, because N can't be evaluated to a value: it's computed
  // without applying the caller bindings.
  constexpr std::string_view kProgram = R"(
proc A<N: u32> {
    data_in: chan<u32> in;
    data_out: chan<u32> out;

    init {
        N
    }
    config(data_in: chan<u32> in, data_out: chan<u32> out) {
        (data_in, data_out)
    }
    next(tok: token, state: u32) {
        let (tok, x) = recv(tok, data_in);
        let tok = send(tok, data_out, x + N + state);
        state + u32:1
    }
}

proc B<M: u32, N: u32> {
    data_in: chan<u32> in;
    data_out: chan<u32> out;

    init { () }
    config(data_in: chan<u32> in, data_out: chan<u32> out) {
        spawn A<N>(data_in, data_out);
        (data_in, data_out)
    }
    next(tok: token, state: ()) {
        ()
    }
}

#[test_proc]
proc BTester {
    data_in: chan<u32> out;
    data_out: chan<u32> in;
    terminator: chan<bool> out;

    init { () }

    config(terminator: chan<bool> out) {
        let (data_in_p, data_in_c) = chan<u32>;
        let (data_out_p, data_out_c) = chan<u32>;
        spawn B<u32:5, u32:3>(data_in_c, data_out_p);
        (data_in_p, data_out_c, terminator)
    }

    next(tok: token, state: ()) {
        let tok = send(tok, data_in, u32:3);
        let (tok, result) = recv(tok, data_out);
        let _ = assert_eq(result, u32:9);
        let tok = send(tok, terminator, true);
        ()
    }
})";

  XLS_ASSERT_OK_AND_ASSIGN(auto temp_file,
                           TempFile::CreateWithContent(kProgram, "_test.x"));
  constexpr std::string_view kModuleName = "test";
  ParseAndTestOptions options;
  absl::StatusOr<TestResult> result = ParseAndTest(
      kProgram, kModuleName, std::string{temp_file.path()}, options);
  EXPECT_THAT(result, status_testing::IsOkAndHolds(TestResult::kAllPassed));
}

TEST(BytecodeInterpreterTest, PrettyPrintsStructs) {
  constexpr std::string_view kProgram = R"(
struct InnerStruct {
    x: u32,
    y: u32,
}

struct MyStruct {
    a: u32,
    b: u16[4],
    c: InnerStruct,
}

fn doomed() {
    let a = MyStruct {
        a: u32:0,
        b: u16[4]:[u16:1, u16:2, u16:3, u16:4],
        c: InnerStruct {
            x: u32:5,
            y: u32:6,
        }
    };

    let b = MyStruct {
        a: u32:7,
        b: u16[4]:[u16:8, ...],
        c: InnerStruct {
            x: u32:12,
            y: u32:13,
        }
    };

    assert_eq(a, b)
})";

  ImportData import_data(CreateImportDataForTest());
  absl::StatusOr<InterpValue> value =
      Interpret(&import_data, kProgram, "doomed");
  EXPECT_THAT(value.status(), StatusIs(absl::StatusCode::kInternal,
                                       HasSubstr("were not equal")));
  EXPECT_TRUE(absl::StrContains(value.status().message(),
                                R"(lhs: MyStruct {
    a: u32:0
    b: uN[16][4]:[u16:1, u16:2, u16:3, u16:4]
    c: InnerStruct {
        x: u32:5
        y: u32:6
    }
})"));
}

TEST(BytecodeInterpreterTest, PrettyPrintsArrays) {
  constexpr std::string_view kProgram = R"(
struct InnerStruct {
    x: u32,
    y: u32,
}

struct MyStruct {
    c: InnerStruct[2],
}

fn doomed() {
    let a = MyStruct {
        c: InnerStruct[2]:[
            InnerStruct {
                x: u32:1,
                y: u32:2,
            },
            InnerStruct {
                x: u32:3,
                y: u32:4,
            }
        ],
    };
    let b = MyStruct {
        c: InnerStruct[2]:[
            InnerStruct {
                x: u32:5,
                y: u32:6,
            },
            InnerStruct {
                x: u32:7,
                y: u32:8,
            },
        ],
    };

    assert_eq(a, b)
})";

  ImportData import_data(CreateImportDataForTest());
  absl::StatusOr<InterpValue> value =
      Interpret(&import_data, kProgram, "doomed");
  EXPECT_THAT(value.status(), StatusIs(absl::StatusCode::kInternal,
                                       HasSubstr("were not equal")));
  EXPECT_TRUE(absl::StrContains(value.status().message(),
                                R"(lhs: MyStruct {
    c: InnerStruct[2]:[
        InnerStruct {
            x: u32:1
            y: u32:2
        },
        InnerStruct {
            x: u32:3
            y: u32:4
        }
    ])"));
}

}  // namespace
}  // namespace xls::dslx


text:
<?php

namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP;

use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff as GenericForbiddenFunctionsSniff;

class DiscouragedFunctionsSniff extends GenericForbiddenFunctionsSniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists. IE, the
     * function should just not be used.
     *
     * @var array<string, string|null>
     */
    public $forbiddenFunctions = [
        'error_log' => null,
        'print_r'   => null,
        'var_dump'  => null,
    ];

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var boolean
     */
    public $error = false;

}//end class

redpajama_set_name: RedPajamaGithub


text:
package com.dianping.cat.report.alert.sender;

import java.util.Arrays;
import java.util.Map;

import junit.framework.Assert;

import org.junit.Test;
import org.unidal.lookup.ComponentTestCase;

import com.dianping.cat.report.alert.AlertType;
import com.dianping.cat.report.alert.sender.AlertMessageEntity;
import com.dianping.cat.report.alert.sender.sender.MailSender;
import com.dianping.cat.report.alert.sender.sender.Sender;
import com.dianping.cat.report.alert.sender.sender.SmsSender;
import com.dianping.cat.report.alert.sender.sender.WeixinSender;

public class SenderTest extends ComponentTestCase {

	@Test
	public void test() {
		Map<String, Sender> mailSender = lookupMap(Sender.class);

        // [CAT StorageSQL告警] [数据库: ws] [监控项: 172.16.2.187;select;avg]
[实际值:768 ] [最大阈值: 300 ][告警时间:2016-10-12 18:04:13]

		String content = "[CAT 第三方告警] [项目: ] : [[type=get, details=HTTP URL[1234568888888888.com?] GET访问出现异常]][时间: 2015-01-15 18:20] \n点击此处查看详情";
		AlertMessageEntity entity = new AlertMessageEntity("CAT", "[CAT第三方告警] [项目: ]", AlertType.ThirdParty.getName(),
		      content, Arrays.asList("jialin.sun@dianping.com"));
		AlertMessageEntity entity2 = new AlertMessageEntity("CAT", "[CAT第三方告警] [项目: ]", AlertType.ThirdParty.getName(),
		      content, Arrays.asList("15201789489"));

		// Assert.assertEquals(true, mailSender.get(MailSender.ID).send(entity));
		Assert.assertEquals(true, mailSender.get(WeixinSender.ID).send(entity));
		// Assert.assertEquals(true, mailSender.get(SmsSender.ID).send(entity2));
	}

//    @Test
//    public void testJson() {
//        SubItem item = new SubItem();
//        item.setTest("subTest");
//
//        Item i = new Item();
//        i.setTest("test");
//        i.setItem(item);
//
//        JsonBuilder jsonBuilder = new JsonBuilder();
//        String json = jsonBuilder.toJson(i);
//        System.out.println(json);
//        Item result = (Item) jsonBuilder.parse(json, Item.class);
//        System.out.println(jsonBuilder.toJson(result));
//    }

    public static class Item {
        private String test;

        private SubItem item;

        public String getTest() {
            return test;
        }

        public void setTest(String test) {
            this.test = test;
        }

        public SubItem getItem() {
            return item;
        }

        public void setItem(SubItem item) {
            this.item = item;
        }

    }

    public static class SubItem {
        private String test;

        public String getTest() {
            return test;
        }

        public void setTest(String test) {
            this.test = test;
        }
    }
}


text:
<title>
Arrogance of American empire
</title>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<?php include "../../legacy-includes/Script.htmlf" ?>

<?php include "../../legacy-includes/TopLogo.htmlf" ?>

<?php include "../../legacy-includes/TopAd.htmlf" ?>

<?php include "../../legacy-includes/LeftButtons.htmlf" ?>

<?php include "../../legacy-includes/BodyInsert.htmlf" ?>

WHAT WE THINK

Arrogance of American empire

June 6, 2003 | Page 3

WHEN JULIUS Caesar conquered Gaul, he parlayed his victory over what is now modern-day France into becoming leader of the Roman Empire. Today's would-be emperor, George W. Bush, also plans to succeed at France's expense--not only because France opposed the U.S. invasion of Iraq, but to keep Europe divided and Washington on top of the world. "Punish France, ignore Germany, forgive Russia: that was the succinct reaction by Condoleezza Rice, America's National Security Adviser, to those countries' opposition to the second Gulf war," observed London's Daily Telegraph.

In its coverage of the Group of Eight (G8) summit in Evian, France, the U.S. media analyzed the warmth of Bush's handshakes with world leaders like society gossip columnists reporting on who's "in" or "out." After meeting with French President Jacques Chirac, Bush snubbed his host by leaving Evian early to attend a Middle East summit in Egypt.

Coming from the same White House image-makers who came up with Bush's prime-time TV landing on an aircraft carrier last month, the message couldn't be clearer: We run the world, and you'd better know your place. As Rice said at a Washington press conference before the Evian trip, "It isn't the power of the United States that needs to 'be checked.' It's the power of the United States that needs to work cooperatively with others who share the same values to achieve common goals."

Or as the Financial Times put it: "U.S. vision requires 'old Europe' to toe the line." By playing up "new Europe" countries like Poland at the expense of old allies Germany and France, Washington wants to ensure that the European Union doesn't coalesce into a political and military rival or an economic competitor.

Meanwhile, the world economy remains mired in stagnation and slump, and the leaders of G8--created in the 1970s to forge common economic policies among the world's most powerful countries--didn't have the least answer to offer. But if the other G8 players rankle at U.S. domination, they share Washington's goal of dominating the world's poor and developing nations.

While Bush made much of the U.S. pledge of $15 billion to fight AIDS at the global level--an amount that France's Chirac promised to match--the real impact remains to be seen. After all, last year's G8 meeting included a promise of $100 billion in debt relief--a number greatly inflated by money that was already committed.

This year, G8 leaders again gave lip service to the problem of Third World debt--but will continue to tighten the screws on poor countries through the International Monetary Fund. The G8 leaders' real views on global justice were reflected in the vicious police crackdown on protesters, who were forced to gather across the border in Switzerland after being banned in France.

The rivalries among G8 leaders are about whether Washington can rule the world alone--not whether the world should be ruled by a handful of the most powerful governments. The real opposition to empire won't be found in presidential palaces or at summit meetings, but in protests and struggle from below.

<?php include "../../legacy-includes/BottomNavLinks.htmlf" ?>

<?php include "../../legacy-includes/RightAdFolder.htmlf" ?>


text:
<!DOCTYPE html>
<meta charset="utf-8">
<title>Empty test page</title>


text:
package com.kostassoid.serializers

import org.scalatest.{BeforeAndAfter, FreeSpec, Matchers}

abstract class SerializerSpec(newSerializer: => CanSerialize) extends FreeSpec with Matchers with BeforeAndAfter {

  @volatile var serializer: CanSerialize = _

  before {
    serializer = newSerializer
  }

  "can serialize string" in {
    val source = "Some string"

    val serialized = serializer.write(source)
    val deserialized = serializer.read[AnyRef](serialized)

    serialized shouldBe "\"Some string\""
    deserialized shouldBe source
  }

  "can serialize List" in {
    val source = "one" :: "two" :: "three" :: Nil

    val serialized = serializer.write(source)
    val deserialized = serializer.read[AnyRef](serialized)

    serialized shouldBe """["one","two","three"]"""
    deserialized shouldBe source
  }
}

class Json4sSpec extends SerializerSpec(new Json4sSerializer)

class SpraySpec extends SerializerSpec(new SpraySerializer)

class PicklingSpec extends SerializerSpec(new PicklingSerializer)

class PicklerSpec extends SerializerSpec(new PicklerSerializer)


text:
package jp.dodododo.dao.handler.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import jp.dodododo.dao.IterationCallback;
import jp.dodododo.dao.columns.ResultSetColumn;
import jp.dodododo.dao.util.CaseInsensitiveMap;
import jp.dodododo.dao.util.ResultSetUtil;

public class MapResultSetHandler extends AbstractResultSetHandler<Map<String, Object>> {

	protected Map<String, Object> arg;

	protected MapResultSetHandler() {
	}

	public MapResultSetHandler(IterationCallback<Map<String, Object>> callback) {
		this(callback, null);
	}

	public MapResultSetHandler(IterationCallback<Map<String, Object>> callback, Map<String, Object> arg) {
		super(callback);
		this.arg = arg;
	}

	@Override
	protected Map<String, Object> createRow(final ResultSet rs, List<ResultSetColumn> resultSetColumnList) throws SQLException {
		Map<String, Object> row = newInstance();

		resultSetColumnList.forEach(column -> {
			String name = column.getName();
			Object value = ResultSetUtil.getObject(rs, name);
			row.put(name, value);
		});
		return row;
	}

	protected Map<String, Object> newInstance() {
		CaseInsensitiveMap<Object> ret = new CaseInsensitiveMap<>();
		ret.putAll(arg);
		return ret;
	}
}


text:
#ifndef ONTREE_TREE_HPP
#define ONTREE_TREE_HPP

#include <ontree/base.hpp>
#include <ontree/zone.hpp>
#include <ontree/text.hpp>
#include <cstring>
#include <algorithm>
#include <new>

ONT_NAMESPACE_BEGIN

enum type_e
{
  type_object,
  type_array,
  type_number,
  type_string,
  type_predicate,
  type_null,
  type_undefined, // node itsself is null: used by var_t
  types
};

class node_t
{
public:
  node_t(node_t* parent, type_e t)
	: m_parent(parent), m_type(t) {}
  ~node_t() { assert(!"should never be deleted!"); }
  type_e type() const { return m_type; }
  node_t* parent() const { return m_parent; }
private:
  node_t(const node_t&);
  const node_t& operator=(const node_t&);
private:
  node_t* m_parent;
  type_e m_type;
};

template<class T, type_e N>
class leaf_t : public node_t
{
public:
  typedef T value_type;
  leaf_t(node_t* parent, const value_type& val)
	: node_t(parent, N), m_value(val) {}
  value_type value() const { return m_value; }
  void set_value(value_type val) { m_value = val; }
private:
  value_type m_value;
};

typedef leaf_t<real_t, type_number>  number_t;
typedef leaf_t<text_t, type_string>  string_t;
typedef leaf_t<bool, type_predicate> predicate_t;
typedef leaf_t<none_t, type_null>    null_t;

template<class Child>
class child_iterator_t
{
public:
  typedef Child child_type;
  typedef child_iterator_t self_type;
  typedef node_t value_type;

  child_iterator_t(child_type* child) : m_child(child) {}

  self_type& operator++() { increment(); return *this; }
  self_type  operator++(int) { self_type ret = *this; increment(); return ret; }
  value_type* operator->() const { return m_child->node(); }
  value_type& operator*() const { return *(m_child->node()); }

  text_t name() const { return m_child->name(); }
  value_type* node() const { return m_child ? m_child->node() : 0; }
  child_type* child() const { return m_child; }

  bool operator==(const child_iterator_t& that) const { return this->m_child == that.m_child; }
  bool operator!=(const child_iterator_t& that) const { return !(*this == that); }
private:
  void increment() { m_child = m_child->next(); }
private:
  child_type* m_child;
};

template<class Child>
class parent_t : public node_t
{
public:
  typedef Child child_type;
  typedef child_iterator_t<child_type> iterator_type;

  parent_t(node_t* parent, type_e t) : node_t(parent, t), m_first(0), m_last(0), m_size(0) {}

  iterator_type begin() const { return iterator_type(m_first); }
  iterator_type end() const { return iterator_type(0); }
  size_t size() const { return m_size; }

public: // used from tree_t
  void insert(child_type* child)
  {
	if (!m_first) {	m_first = child; }
	if (m_last) { m_last->set_next(child); }
	m_last = child;
	m_size++;
  }
private:
  child_type* m_first;
  child_type* m_last;
  size_t m_size;
};

class member_t
{
public:
  member_t(const text_t& name) : m_name(name), m_next(0) {}

  const text_t& name() const { return m_name; }
  member_t* next() const { return m_next; }
  void set_next(member_t* n) { m_next = n; }

  const node_t* node() const
  {
	return reinterpret_cast<const node_t*>
	  (reinterpret_cast<const byte_t*>(this) + sizeof(member_t));
  }

  node_t* node()
  {
	assert(this);
	return reinterpret_cast<node_t*>
	  (reinterpret_cast<byte_t*>(this) + sizeof(member_t));
  }

  static member_t* unnode(node_t* node)
  {
	assert(node->parent()->type() == type_object);
	return reinterpret_cast<member_t*>
	  (reinterpret_cast<byte_t*>(node) - sizeof(member_t));
  }

  type_e node_type() const { return node()->type(); }

private:
  text_t m_name;
  member_t* m_next;
};

typedef child_iterator_t<member_t> member_iterator_t;

class object_t : public parent_t<member_t>
{
public:
  typedef parent_t<member_t> base_type;
  typedef base_type::iterator_type iterator_type;

  explicit object_t(node_t* parent) : base_type(parent, type_object) {}

  iterator_type find(const const_range_t& name) const
  {
	for (iterator_type i=begin(); i != end(); ++i) {
	  if (i.name() == name) {
		return i;
	  }
	}

	return end();
  }

  iterator_type find(const char* name) const { return find(const_range_t(name, strlen(name))); }
};

class element_t
{
public:
  element_t() :  m_next(0) {}

  text_t name() const { return text_t(0, 0); } // for member_t compatility. almost useless.
  element_t* next() const { return m_next; }
  void set_next(element_t* n) { m_next = n; }

  const node_t* node() const
  {
	assert(this);
	return reinterpret_cast<const node_t*>
	  (reinterpret_cast<const byte_t*>(this) + sizeof(element_t));
  }

  node_t* node()
  {
	return reinterpret_cast<node_t*>
	  (reinterpret_cast<byte_t*>(this) + sizeof(element_t));
  }

  static element_t* unnode(node_t* node)
  {
	assert(node->parent()->type() == type_array);
	return reinterpret_cast<element_t*>
	  (reinterpret_cast<byte_t*>(node) - sizeof(element_t));
  }

  type_e node_type() const { return node()->type(); }

private:
  element_t* m_next;
};

typedef child_iterator_t<element_t> element_iterator_t;

class array_t : public parent_t<element_t>
{
public:
  typedef parent_t<element_t> base_type;
  typedef base_type::iterator_type iterator_type;

  explicit array_t(node_t* parent) : base_type(parent, type_array) {}

  iterator_type at(size_t n) const
  {
	size_t off = 0;
	for (iterator_type i=begin(); i != end(); ++i, ++off) {
	  if (off == n) {
		return i;
	  }
	}

	return end();
  }
};

/*
 * node type tricks
 */
template<class T> inline type_e node_type();
template<> inline type_e node_type<number_t>() { return type_number; }
template<> inline type_e node_type<string_t>() { return type_string; }
template<> inline type_e node_type<predicate_t>() { return type_predicate; }
template<> inline type_e node_type<null_t>() { return type_null; }
template<> inline type_e node_type<object_t>() { return type_object; }
template<> inline type_e node_type<array_t>() { return type_array; }

template<class T, class ChildIterator>
inline T* child_cast(ChildIterator i)
{
  assert(node_type<T>() == i->type());
  return static_cast<T*>(i.node());
}

template<class T>
inline T* node_cast(node_t* node)
{
  assert(node_type<T>() == node->type());
  return static_cast<T*>(node);
}

class tree_t
{
public:
  explicit tree_t(size_t page_size=zone_t::default_page_size)
	: m_zone(page_size), m_root(0), m_size(1) {}

  tree_t(const tree_t& that)
	: m_zone(that.page_size()), m_root(0), m_size(1)
  {
	insert_children(root(), that.root());
  }

  explicit tree_t(const tree_t& that, const object_t* that_child)
	: m_zone(that.page_size()), m_root(0), m_size(1)
  {
	insert_children(root(), that_child);
  }

  const tree_t& operator=(const tree_t& that)
  {
	if (this != &that) {
	  tree_t copy(that);
	  copy.swap(*this);
	}

	return *this;
  }

  size_t size() const { return m_size; }

  object_t* root() const
  {
	if (!m_root) {
	  m_root = new (const_cast<tree_t*>(this)->m_zone.allocate(sizeof(object_t))) object_t(0);
	}

	return m_root;
  }

  number_t* insert_leaf(object_t* parent, const char* name, real_t val)
  {
	return insert_leaf(parent, new_text(name), val);
  }

  number_t* insert_leaf(object_t* parent, const text_t& name, real_t val)
  {
	return new (insert_member(parent, name, sizeof(number_t))->node()) number_t(parent, val);
  }

  number_t* insert_leaf(array_t* parent, real_t val)
  {
	return new (insert_element(parent, sizeof(number_t))->node())
	  number_t(parent, val);

  }

  string_t* insert_leaf(object_t* parent, const char* name, const char* value)
  {
	return insert_leaf(parent, new_text(name), new_text(value));
  }

  string_t* insert_leaf(object_t* parent, const text_t& name, const text_t& value)
  {
	return new (insert_member(parent, name, sizeof(string_t))->node()) string_t(parent, value);
  }

  string_t* insert_leaf(array_t* parent, const text_t& value)
  {
	return new
	  (insert_element(parent, sizeof(string_t))->node())
	  string_t(parent, value);
  }

  string_t* insert_leaf(array_t* parent, const char* value)
  {
	return insert_leaf(parent, new_text(value));
  }

  predicate_t* insert_leaf(object_t* parent, const char* name, bool val)
  {
	return insert_leaf(parent, new_text(name), val);
  }

  predicate_t* insert_leaf(object_t* parent, const text_t& name, bool val)
  {
	return new (insert_member(parent, name, sizeof(predicate_t))->node())
	  predicate_t(parent, val);
  }

  predicate_t* insert_leaf(array_t* parent, bool val)
  {
	return new (insert_element(parent, sizeof(predicate_t))->node())
	  predicate_t(parent, val);
  }

  null_t* insert_leaf(object_t* parent, const char* name, const none_t& none)
  {
	return insert_leaf(parent, new_text(name), none);
  }

  null_t* insert_leaf(object_t* parent, const text_t& name, const none_t&)
  {
	return new (insert_member(parent, name, sizeof(null_t))->node()) null_t(parent, none_t());
  }

  null_t* insert_leaf(array_t* parent, const none_t&)
  {
	return new (insert_element(parent, sizeof(null_t))->node()) null_t(parent, none_t());
  }

  object_t* insert_object(object_t* parent, const char* name)
  {
	return insert_object(parent, new_text(name));
  }

  object_t* insert_object(object_t* parent, const text_t& name)
  {
	return new (insert_member(parent, name, sizeof(object_t))->node()) object_t(parent);
  }

  object_t* insert_object(array_t* parent)
  {
	return new (insert_element(parent, sizeof(object_t))->node()) object_t(parent);
  }

  array_t* insert_array(object_t* parent, const char* name)
  {
	return insert_array(parent, new_text(name));
  }

  array_t* insert_array(object_t* parent, const text_t& name)
  {
	return new (insert_member(parent, name, sizeof(array_t))->node()) array_t(parent);
  }

  array_t* insert_array(array_t* parent)
  {
	return new (insert_element(parent, sizeof(array_t))->node()) array_t(parent);
  }

  text_t new_text(size_t size)
  {
	char* s = reinterpret_cast<char*>(m_zone.allocate(size+1));
	return text_t(s, size);
  }

  text_t new_text(const char* str)
  {
	size_t len = strlen(str);
	text_t ret = new_text(len);
	memcpy(ret.data(), str, len);
	ret.data()[len] = '\0';
	return ret;
  }

  void swap(tree_t& that)
  {
	std::swap(this->m_root, that.m_root);
	std::swap(this->m_size, that.m_size);
	this->m_zone.swap(that.m_zone);
  }

  size_t page_size() const { return m_zone.page_size(); }

  void insert_subtree(object_t* dst_parent, const char* name, node_t* src)
  {
	switch (src->type()) {
	case type_object: {
	  object_t* dst = insert_object(dst_parent, name);
	  for (member_iterator_t i = node_cast<object_t>(src)->begin(), end = node_cast<object_t>(src)->end();
		   i != end; ++i) {
		insert_subtree(dst, i.name().c_str(), i.node());
	  }
	}   break;
	case type_array: {
	  array_t* dst = insert_array(dst_parent, name);
	  for (element_iterator_t i = node_cast<array_t>(src)->begin(), end = node_cast<array_t>(src)->end();
		   i != end; ++i) {
		insert_subtree(dst, i.node());
	  }
	}   break;
	case type_string:
	  // make copy of text_t instead of share storage instance...
	  insert_leaf(dst_parent, new_text(name),
				  new_text(node_cast<string_t>(src)->value().c_str()));
	  break;
	case type_number:
	  insert_leaf(dst_parent, new_text(name), node_cast<number_t>(src)->value());
	  break;
	case type_predicate:
	  insert_leaf(dst_parent, new_text(name), node_cast<predicate_t>(src)->value());
	  break;
	case type_null:
	  insert_leaf(dst_parent, new_text(name), none_t());
	  break;
	default:
	  ONT_SHOULD_NOT_BE_REACHED();
	  break;
	}
  }

  void insert_subtree(array_t* dst_parent, node_t* src)
  {
	switch (src->type()) {
	case type_object: {
	  object_t* dst = insert_object(dst_parent);
	  for (member_iterator_t i = node_cast<object_t>(src)->begin(), end = node_cast<object_t>(src)->end();
		   i != end; ++i) {
		insert_subtree(dst, i.name().c_str(), i.node());
	  }
	}   break;
	case type_array: {
	  array_t* dst = insert_array(dst_parent);
	  for (element_iterator_t i = node_cast<array_t>(src)->begin(), end = node_cast<array_t>(src)->end();
		   i != end; ++i) {
		insert_subtree(dst, i.node());
	  }
	}   break;
	case type_string:
	  insert_leaf(dst_parent, node_cast<string_t>(src)->value());
	  break;
	case type_number:
	  insert_leaf(dst_parent, node_cast<number_t>(src)->value());
	  break;
	case type_predicate:
	  insert_leaf(dst_parent, node_cast<predicate_t>(src)->value());
	  break;
	case type_null:
	  insert_leaf(dst_parent, none_t());
	  break;
	default:
	  ONT_SHOULD_NOT_BE_REACHED();
	  break;
	}
  }

public: // for test
  void insert_children(object_t* src_parent, const object_t* dst_parent)
  {
	for (member_iterator_t i = dst_parent->begin();
		 i != dst_parent->end(); ++i) {
	  insert_subtree(src_parent, i.name().c_str(), i.node());
	}
  }

private:
  member_t* insert_member(object_t* parent, const text_t& name, size_t node_size)
  {
	member_t* m = new (m_zone.allocate(sizeof(member_t) + node_size)) member_t(name);
	// XXX: check duplication
	parent->insert(m);
	m_size++;
	return m;
  }

  element_t* insert_element(array_t* parent, size_t node_size)
  {
	element_t* e
	  = new (m_zone.allocate(sizeof(element_t) + node_size)) element_t();
	parent->insert(e);
	m_size++;
	return e;
  }

private:
  zone_t m_zone;
  mutable object_t* m_root;
  size_t m_size;
};

ONT_NAMESPACE_END

#endif//ONTREE_TREE_HPP

/* -*-
   Local Variables:
   mode: c++
   c-tab-always-indent: t
   c-indent-level: 2
   c-basic-offset: 2
   End:
   -*- */


text: window.report_result('classic script from dynamic2.wbn');


text:
package mockio

import (
	"io"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestStdout(t *testing.T) {
	stdout := Stdout()

	require.Empty(t, stdout.ReadNow(), "starts empty")

	_, err := stdout.ReadUntil('x', 1*time.Millisecond)
	require.Equal(t, io.EOF, err, "EOF when timeout expires")

	io.WriteString(stdout, "te")
	io.WriteString(stdout, "st")

	val, err := stdout.ReadUntil('s', 1*time.Millisecond)
	require.Nil(t, err, "no error when multiple writes")
	require.Equal(t, "tes", val, "read joins output from multiple writes")
	require.Equal(t, "t", stdout.ReadNow(), "remaining string after ReadUntil returned by ReadNow")

	wait := make(chan struct{})

	go (func(w io.Writer) {
		io.WriteString(w, "ab")
		io.WriteString(w, "cdef")
		wait <- struct{}{}
	})(stdout)

	<-wait
	val, err = stdout.ReadUntil('c', 1*time.Millisecond)
	require.Nil(t, err, "no error when multiple writes in goroutine")
	require.Equal(t, "abc", val, "read joins output from multiple writes in goroutine")
	require.Equal(t, "def", stdout.ReadNow(), "remaining string after ReadUntil returned by ReadNow")

	go (func(w io.Writer) {
		io.WriteString(w, "ab")
		wait <- struct{}{}
		<-wait
		io.WriteString(w, "cd")
		wait <- struct{}{}
	})(stdout)

	<-wait
	val, err = stdout.ReadUntil('d', 1*time.Millisecond)
	require.Equal(t, io.EOF, err, "EOF when delimiter write does not happen within timeout")
	require.Equal(t, "ab", val, "returns content written before timeout")

	wait <- struct{}{}
	<-wait
	require.Equal(t, "cd", stdout.ReadNow(), "continues normally after timeout")

	go func() {
		val, err = stdout.ReadUntil('b', 50*time.Millisecond)
		// This is a test of data races, the assertions are not very important.
		require.Equal(t, err, io.EOF)
		require.Equal(t, 50, len(val))
		wait <- struct{}{}
	}()
	for i := 0; i < 50; i++ {
		go (func(w io.Writer) {
			io.WriteString(w, "a")
		})(stdout)
	}
	<-wait

	bytes := []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
	for i := 0; i < 20; i++ {
		go (func(w io.Writer) {
			wait <- struct{}{}
			for _, b := range bytes {
				w.Write([]byte{b})
			}
		})(stdout)
		<-wait
		for _, b := range bytes {
			_, err = stdout.ReadUntil(b, 10*time.Millisecond)
			require.NoError(t, err)
		}
	}

	stdout.ShouldError(io.ErrClosedPipe)
	_, err = stdout.Write([]byte{','})
	require.Error(t, err, "next error on write")
	_, err = stdout.Write([]byte{':'})
	require.NoError(t, err, "next error is consumed")
}

func TestTiming(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping timing test in short mode.")
	}

	stdout := Stdout()
	wait := make(chan struct{})

	go (func(w io.Writer) {
		<-wait
		io.WriteString(w, "ab")
		time.Sleep(4 * time.Second)
		io.WriteString(w, "cd")
		time.Sleep(4 * time.Second)
		io.WriteString(w, "ef")
		time.Sleep(4 * time.Second)
		io.WriteString(w, "gh")
		time.Sleep(4 * time.Second)
		io.WriteString(w, "ijklmnop")
		wait <- struct{}{}
	})(stdout)

	wait <- struct{}{}
	val, err := stdout.ReadUntil('i', 10*time.Second)
	require.Equal(t, io.EOF, err, "EOF when delimiter write does not happen within timeout")
	require.Equal(t, "abcdef", val, "returns content written before timeout")

	val, err = stdout.ReadUntil('j', 8*time.Second)
	require.Equal(t, "ghij", val, "returns only content up to delimiter")
	require.NoError(t, err, "if delimiter is written within timeout")
	<-wait
	require.Equal(t, "klmnop", stdout.ReadNow(), "subsequent readnow returns content after timeout")
}

func TestWaiting(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping waiting test in short mode.")
	}

	stdout := Stdout()

	io.WriteString(stdout, "123")
	_, err := stdout.ReadUntil('3', time.Second)
	require.NoError(t, err)

	require.False(t, stdout.WaitForWrite(time.Second),
		"wait when buffer is empty")

	wait := make(chan struct{})

	go (func(w io.Writer) {
		<-wait
		io.WriteString(w, "ab")
		<-wait
		time.Sleep(4 * time.Second)
		io.WriteString(w, "cd")
	})(stdout)

	wait <- struct{}{}
	require.True(t, stdout.WaitForWrite(time.Second),
		"wait when buffer is not empty")
	require.True(t, stdout.WaitForWrite(time.Second),
		"wait when buffer is still not empty")

	stdout.ReadNow()
	wait <- struct{}{}
	require.False(t, stdout.WaitForWrite(time.Second),
		"wait after buffer is emptied")

	require.True(t, stdout.WaitForWrite(6*time.Second),
		"write before timeout expires")
}

func TestStdin(t *testing.T) {
	stdin := Stdin()

	type readResult struct {
		contents string
		err      error
	}

	request := make(chan int)
	result := make(chan readResult)

	go (func(reader io.Reader, result chan<- readResult) {
		for r := range request {
			out := make([]byte, r)
			count, err := reader.Read(out)
			result <- readResult{string(out)[:count], err}
		}
	})(stdin, result)

	resultOrTimeout := func(timeout time.Duration) (readResult, bool) {
		select {
		case r := <-result:
			return r, true
		case <-time.After(timeout):
			return readResult{}, false
		}
	}

	request <- 1
	r, ok := resultOrTimeout(time.Millisecond)
	require.False(t, ok, "read should not return when nothing has been written")

	stdin.WriteString("")
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read returns empty string if written")
	require.Equal(t, readResult{"", nil}, r, "read returns empty string if written")

	stdin.WriteString("test")
	request <- 2
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read should not time out when content is available")
	require.Equal(t, readResult{"te", nil}, r, "read returns only requested content when more is available")

	request <- 2
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read should not time out when content is available")
	require.Equal(t, readResult{"st", nil}, r, "read returns leftover on subsequent call")

	stdin.WriteString("abcd")
	request <- 10
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read should not time out when returning partial content")
	require.Equal(t, readResult{"abcd", nil}, r, "read returns partial content if available")

	stdin.WriteString("12")
	stdin.WriteString("34")
	stdin.WriteString("56")
	stdin.WriteString("78")
	request <- 8
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read should not time out when concatenating")
	require.Equal(t, readResult{"12345678", nil}, r, "read returns concatenation of multiple writes")

	request <- 4
	r, ok = resultOrTimeout(time.Millisecond)
	require.False(t, ok, "read should wait for a write when buffer has been emptied")

	stdin.Write([]byte("xyz"))
	stdin.Write([]byte("abc"))
	r, ok = resultOrTimeout(time.Second)
	require.True(t, ok, "read does not time out when returning partial content")
	require.Equal(t, readResult{"xyz", nil}, r, "read returns contents of first write (does not wait)")

	request <- 1
	r = <-result
	require.Equal(t, readResult{"a", nil}, r, "remaining writes are read by later requests")

	request <- 10
	r = <-result
	require.Equal(t, readResult{"bc", nil}, r, "remaining writes are read by later requests")

	stdin.WriteString("foo")
	stdin.ShouldError(io.ErrClosedPipe)
	request <- 3
	r = <-result
	require.Error(t, r.err, "next error on read")
	request <- 3
	r = <-result
	require.NoError(t, r.err, "next error is consumed")
	require.Equal(t, "foo", r.contents)

	request <- 4
	// Give request some time to block.
	time.Sleep(10 * time.Millisecond)
	stdin.ShouldError(io.ErrShortBuffer)
	r = <-result
	require.Error(t, r.err, "ShouldError when Read is blocked")
}


text:
#import <UIKit/UIKit.h>

#import "ABI9_0_0RCTDefines.h"
#import "ABI9_0_0RCTResizeMode.h"

NS_ASSUME_NONNULL_BEGIN

/**
 * This function takes an source size (typically from an image), a target size
 * and scale that it will be drawn at (typically in a CGContext) and then
 * calculates the rectangle to draw the image into so that it will be sized and
 * positioned correctly according to the specified resizeMode.
 */
ABI9_0_0RCT_EXTERN CGRect ABI9_0_0RCTTargetRect(CGSize sourceSize, CGSize destSize,
                                CGFloat destScale, ABI9_0_0RCTResizeMode resizeMode);

/**
 * This function takes a source size (typically from an image), a target rect
 * that it will be drawn into (typically relative to a CGContext), and works out
 * the transform needed to draw the image at the correct scale and position.
 */
ABI9_0_0RCT_EXTERN CGAffineTransform ABI9_0_0RCTTransformFromTargetRect(CGSize sourceSize,
                                                        CGRect targetRect);

/**
 * This function takes an input content size & scale (typically from an image),
 * a target size & scale at which it will be displayed (typically in a
 * UIImageView) and then calculates the optimal size at which to redraw the
 * image so that it will be displayed correctly with the specified resizeMode.
 */
ABI9_0_0RCT_EXTERN CGSize ABI9_0_0RCTTargetSize(CGSize sourceSize, CGFloat sourceScale,
                                CGSize destSize, CGFloat destScale,
                                ABI9_0_0RCTResizeMode resizeMode, BOOL allowUpscaling);

/**
 * This function takes an input content size & scale (typically from an image),
 * a target size & scale that it will be displayed at, and determines if the
 * source will need to be upscaled to fit (which may result in pixelization).
 */
ABI9_0_0RCT_EXTERN BOOL ABI9_0_0RCTUpscalingRequired(CGSize sourceSize, CGFloat sourceScale,
                                     CGSize destSize, CGFloat destScale,
                                     ABI9_0_0RCTResizeMode resizeMode);

/**
 * This function takes the source data for an image and decodes it at the
 * specified size. If the original image is smaller than the destination size,
 * the resultant image's scale will be decreased to compensate, so the
 * width/height of the returned image is guaranteed to be >= destSize.
 * Pass a destSize of CGSizeZero to decode the image at its original size.
 */
ABI9_0_0RCT_EXTERN UIImage *__nullable ABI9_0_0RCTDecodeImageWithData(NSData *data,
                                                      CGSize destSize,
                                                      CGFloat destScale,
                                                      ABI9_0_0RCTResizeMode resizeMode);

/**
 * This function takes the source data for an image and decodes just the
 * metadata, without decompressing the image itself.
 */
ABI9_0_0RCT_EXTERN NSDictionary<NSString *, id> *__nullable ABI9_0_0RCTGetImageMetadata(NSData *data);

/**
 * Convert an image back into data. Images with an alpha channel will be
 * converted to lossless PNG data. Images without alpha will be converted to
 * JPEG. The `quality` argument controls the compression ratio of the JPEG
 * conversion, with 1.0 being maximum quality. It has no effect for images
 * using PNG compression.
 */
ABI9_0_0RCT_EXTERN NSData *__nullable ABI9_0_0RCTGetImageData(CGImageRef image, float quality);

/**
 * This function transforms an image. `destSize` is the size of the final image,
 * and `destScale` is its scale. The `transform` argument controls how the
 * source image will be mapped to the destination image.
 */
ABI9_0_0RCT_EXTERN UIImage *__nullable ABI9_0_0RCTTransformImage(UIImage *image,
                                                 CGSize destSize,
                                                 CGFloat destScale,
                                                 CGAffineTransform transform);

/*
 * Return YES if image has an alpha component
 */
ABI9_0_0RCT_EXTERN BOOL ABI9_0_0RCTImageHasAlpha(CGImageRef image);

NS_ASSUME_NONNULL_END


text:
#include <aws/greengrass/model/BulkDeploymentMetrics.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <utility>

using namespace Aws::Utils::Json;
using namespace Aws::Utils;

namespace Aws
{
namespace Greengrass
{
namespace Model
{

BulkDeploymentMetrics::BulkDeploymentMetrics() :
    m_invalidInputRecords(0),
    m_invalidInputRecordsHasBeenSet(false),
    m_recordsProcessed(0),
    m_recordsProcessedHasBeenSet(false),
    m_retryAttempts(0),
    m_retryAttemptsHasBeenSet(false)
{
}

BulkDeploymentMetrics::BulkDeploymentMetrics(JsonView jsonValue) :
    m_invalidInputRecords(0),
    m_invalidInputRecordsHasBeenSet(false),
    m_recordsProcessed(0),
    m_recordsProcessedHasBeenSet(false),
    m_retryAttempts(0),
    m_retryAttemptsHasBeenSet(false)
{
  *this = jsonValue;
}

BulkDeploymentMetrics& BulkDeploymentMetrics::operator =(JsonView jsonValue)
{
  if(jsonValue.ValueExists("InvalidInputRecords"))
  {
    m_invalidInputRecords = jsonValue.GetInteger("InvalidInputRecords");

    m_invalidInputRecordsHasBeenSet = true;
  }

  if(jsonValue.ValueExists("RecordsProcessed"))
  {
    m_recordsProcessed = jsonValue.GetInteger("RecordsProcessed");

    m_recordsProcessedHasBeenSet = true;
  }

  if(jsonValue.ValueExists("RetryAttempts"))
  {
    m_retryAttempts = jsonValue.GetInteger("RetryAttempts");

    m_retryAttemptsHasBeenSet = true;
  }

  return *this;
}

JsonValue BulkDeploymentMetrics::Jsonize() const
{
  JsonValue payload;

  if(m_invalidInputRecordsHasBeenSet)
  {
   payload.WithInteger("InvalidInputRecords", m_invalidInputRecords);

  }

  if(m_recordsProcessedHasBeenSet)
  {
   payload.WithInteger("RecordsProcessed", m_recordsProcessed);

  }

  if(m_retryAttemptsHasBeenSet)
  {
   payload.WithInteger("RetryAttempts", m_retryAttempts);

  }

  return payload;
}

} // namespace Model
} // namespace Greengrass
} // namespace Aws


text:
layout: posts
title:  "Return data after success AJAX call"
date:   2014-12-10 08:05:00
category: javascript
description: >
  The only way to return the data from the function would be
  to make a synchronous call instead of an asynchronous call,
  but that would freeze up the browser while it's waiting for
  the response. You can pass in a callback function that handles
  the result or even better you can use a promise.
  You can store your promise, you can pass it around, you can
  use it as an argument in function calls and you can return it
  from functions, but when you finally want to use your data that
  is returned by the AJAX call.
---

jQuery: Return data after success AJAX call
-------------------------------------------

---

#### Using a callback:

The only way to return the data from the function would be to make a synchronous call instead of an asynchronous call, but that would freeze up the browser while it's waiting for the response.

You can pass in a callback function that handles the result:

{% highlight js linenos %}
function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",
    success:function(data) {
      handleData(data);
    }
  });
}
{% endhighlight %}

Call it like this:

{% highlight js linenos %}
testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.
{% endhighlight %}

#### Using a promise:

You can't return anything from a function that is asynchronous. What you can return is a promise.
{% highlight js linenos %}
function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

// get your promise like this
var promise = testAjax();
{% endhighlight %}

You can store your promise, you can pass it around, you can use it as an argument in function calls and you can return it from functions, but when you finally want to use your data that is returned by the AJAX call, you have to do it like this:

{% highlight js linenos %}
promise.success(function (data) {
  alert(data);
});
{% endhighlight %}
Source [Stack Overflow](http://stackoverflow.com/questions/5316697/jquery-return-data-after-ajax-call-success)


text:
set -eux

if [ $# -lt 1 ]; then
  echo "usage $0 <version-name>"
  exit 1;
fi
readonly VERSION_NAME=$1
shift 1

$(dirname $0)/validate-dagger-version.sh "$VERSION_NAME"

# Publish javadocs to gh-pages
bazel build //:user-docs.jar

# If a token exists, then use the token to clone the repo. This allows our
# automated workflows to commit without manually authenticating.
if [[ ! -z "$GH_TOKEN" ]]; then
  git clone --quiet --branch=gh-pages https://x-access-token:${GH_TOKEN}@github.com/google/dagger gh-pages > /dev/null
else
  git clone --quiet --branch=gh-pages https://github.com/google/dagger gh-pages > /dev/null
fi

cd gh-pages
unzip ../bazel-bin/user-docs.jar -d api/$VERSION_NAME
rm -rf api/$VERSION_NAME/META-INF/
git add api/$VERSION_NAME
git commit -m "$VERSION_NAME docs"
git push origin gh-pages
cd ..
rm -rf gh-pages