| 1 | #include <stdarg.h>  // va_list, etc.
 | 
| 2 | #include <stdio.h>
 | 
| 3 | 
 | 
| 4 | #include "_gen/asdl/examples/shared_variant.asdl.h"
 | 
| 5 | #include "_gen/asdl/examples/typed_arith.asdl.h"
 | 
| 6 | #include "_gen/asdl/examples/typed_demo.asdl.h"  // has simple Sum, etc
 | 
| 7 | #include "mycpp/runtime.h"
 | 
| 8 | #include "prebuilt/asdl/runtime.mycpp.h"
 | 
| 9 | #include "vendor/greatest.h"
 | 
| 10 | 
 | 
| 11 | using typed_arith_asdl::pipeline;
 | 
| 12 | 
 | 
| 13 | using typed_arith_asdl::arith_expr;    // variant type namespace
 | 
| 14 | using typed_arith_asdl::arith_expr_e;  // variant tag type
 | 
| 15 | using typed_arith_asdl::arith_expr_t;  // sum type
 | 
| 16 | 
 | 
| 17 | using typed_arith_asdl::arith_expr__Big;
 | 
| 18 | using typed_arith_asdl::arith_expr__Const;
 | 
| 19 | using typed_arith_asdl::arith_expr__FuncCall;
 | 
| 20 | using typed_arith_asdl::arith_expr__Unary;
 | 
| 21 | using typed_arith_asdl::arith_expr__Var;
 | 
| 22 | 
 | 
| 23 | using typed_demo_asdl::bool_expr__Binary;
 | 
| 24 | using typed_demo_asdl::bool_expr__LogicalBinary;
 | 
| 25 | using typed_demo_asdl::op_array;
 | 
| 26 | using typed_demo_asdl::op_id_e;
 | 
| 27 | 
 | 
| 28 | using hnode_asdl::hnode__Leaf;
 | 
| 29 | using hnode_asdl::hnode_e;
 | 
| 30 | 
 | 
| 31 | void PrintTag(arith_expr_t* a) {
 | 
| 32 |   switch (a->tag()) {
 | 
| 33 |   case arith_expr_e::Const:
 | 
| 34 |     log("Const");
 | 
| 35 |     break;
 | 
| 36 |   case arith_expr_e::Var:
 | 
| 37 |     log("Var");
 | 
| 38 |     break;
 | 
| 39 |   default:
 | 
| 40 |     log("OTHER");
 | 
| 41 |   }
 | 
| 42 |   log("");
 | 
| 43 | }
 | 
| 44 | 
 | 
| 45 | TEST misc_test() {
 | 
| 46 |   auto c = Alloc<arith_expr::Const>(42);
 | 
| 47 |   log("sizeof *c = %d", sizeof *c);  // 16 bytes
 | 
| 48 | 
 | 
| 49 |   ASSERT_EQ_FMT(42, c->i, "%d");
 | 
| 50 |   log("c->tag = %d", c->tag());
 | 
| 51 |   PrintTag(c);
 | 
| 52 | 
 | 
| 53 |   auto v = Alloc<arith_expr__Var>(StrFromC("foo"));
 | 
| 54 |   log("sizeof *v = %d", sizeof *v);  // 24 bytes
 | 
| 55 | 
 | 
| 56 |   ASSERT(str_equals(StrFromC("foo"), v->name));
 | 
| 57 |   log("v->tag = %d", v->tag());
 | 
| 58 |   PrintTag(v);
 | 
| 59 | 
 | 
| 60 |   auto u = Alloc<arith_expr__Unary>(StrFromC("-"), v);
 | 
| 61 |   log("u->op = %s", u->op->data_);
 | 
| 62 | 
 | 
| 63 |   auto v1 = Alloc<arith_expr__Var>(StrFromC("v1"));
 | 
| 64 |   auto v2 = Alloc<arith_expr__Var>(StrFromC("v2"));
 | 
| 65 |   auto args = NewList<arith_expr_t*>({v1, v2});
 | 
| 66 | 
 | 
| 67 |   auto f = Alloc<arith_expr__FuncCall>(StrFromC("f"), args);
 | 
| 68 |   log("f->name = %s", f->name->data_);
 | 
| 69 | 
 | 
| 70 |   auto p = Alloc<pipeline>(true);
 | 
| 71 |   log("p->negated = %d", p->negated);
 | 
| 72 | 
 | 
| 73 | #if 0
 | 
| 74 |   if (t->tag() == hnode_e::Leaf) {
 | 
| 75 |     hnode__Leaf* t2 = static_cast<hnode__Leaf*>(t);
 | 
| 76 |     log("%s", hnode_str(t2->tag()));
 | 
| 77 |     log("%s", color_str(t2->color));
 | 
| 78 |     log("%s", t2->s->data_);
 | 
| 79 |   }
 | 
| 80 | #endif
 | 
| 81 | 
 | 
| 82 |   // NOTE: This is self-initialization!!!
 | 
| 83 |   /*
 | 
| 84 |   if (t->tag == hnode_e::Leaf) {
 | 
| 85 |     hnode__Leaf* t = static_cast<hnode__Leaf*>(t);
 | 
| 86 |     log("%s", hnode_str(t->tag));
 | 
| 87 |     log("%s", color_str(t->color));
 | 
| 88 |     log("%s", t->s->data_);
 | 
| 89 |   }
 | 
| 90 |   */
 | 
| 91 | 
 | 
| 92 |   PASS();
 | 
| 93 | }
 | 
| 94 | 
 | 
| 95 | using shared_variant_asdl::DoubleQuoted;
 | 
| 96 | using shared_variant_asdl::word_part_e;
 | 
| 97 | using shared_variant_asdl::word_part_t;
 | 
| 98 | 
 | 
| 99 | using shared_variant_asdl::tok;
 | 
| 100 | using shared_variant_asdl::tok_e;
 | 
| 101 | using shared_variant_asdl::tok_t;
 | 
| 102 | using shared_variant_asdl::Token;
 | 
| 103 | 
 | 
| 104 | TEST shared_variant_test() {
 | 
| 105 |   auto* dq = Alloc<DoubleQuoted>(0, Alloc<List<BigStr*>>());
 | 
| 106 | 
 | 
| 107 |   word_part_t* wp = nullptr;
 | 
| 108 |   wp = dq;  // assign to base type
 | 
| 109 | 
 | 
| 110 |   log("wp->tag() %d", wp->tag());
 | 
| 111 | 
 | 
| 112 |   auto* token = Alloc<Token>(0, StrFromC("hi"));
 | 
| 113 |   tok_t* tok = nullptr;
 | 
| 114 |   tok = token;
 | 
| 115 | 
 | 
| 116 |   log("tok->tag() for Token = %d", tok->tag());
 | 
| 117 | 
 | 
| 118 |   auto* eof = tok::Eof;
 | 
| 119 |   tok = eof;
 | 
| 120 |   log("tok->tag() for Eof = %d", tok->tag());
 | 
| 121 | 
 | 
| 122 |   PASS();
 | 
| 123 | }
 | 
| 124 | 
 | 
| 125 | using typed_demo_asdl::bool_expr_str;
 | 
| 126 | 
 | 
| 127 | TEST pretty_print_test() {
 | 
| 128 |   // typed_demo.asdl
 | 
| 129 | 
 | 
| 130 |   // auto o = op_id_e::Plus;
 | 
| 131 |   // Note: this is NOT prevented at compile time, even though it's illegal.
 | 
| 132 |   // left and right are not optional.
 | 
| 133 |   // auto b = new bool_expr__LogicalBinary(o, nullptr, nullptr);
 | 
| 134 | 
 | 
| 135 |   auto w1 = Alloc<typed_demo_asdl::word>(StrFromC("left"));
 | 
| 136 |   auto w2 = Alloc<typed_demo_asdl::word>(StrFromC("right"));
 | 
| 137 |   auto b = Alloc<bool_expr__Binary>(w1, w2);
 | 
| 138 | 
 | 
| 139 |   hnode_t* t1 = b->PrettyTree();
 | 
| 140 |   ASSERT_EQ_FMT(hnode_e::Record, t1->tag(), "%d");
 | 
| 141 | 
 | 
| 142 |   auto f = mylib::Stdout();
 | 
| 143 |   auto ast_f = Alloc<format::TextOutput>(f);
 | 
| 144 |   format::PrintTree(t1, ast_f);
 | 
| 145 |   printf("\n");
 | 
| 146 | 
 | 
| 147 |   log("bool_expr_str = %s", bool_expr_str(b->tag())->data_);
 | 
| 148 |   ASSERT(str_equals0("bool_expr.Binary", bool_expr_str(b->tag())));
 | 
| 149 | 
 | 
| 150 |   ASSERT(str_equals0("Binary", bool_expr_str(b->tag(), false)));
 | 
| 151 | 
 | 
| 152 |   // typed_arith.asdl
 | 
| 153 |   auto c = Alloc<arith_expr__Const>(42);
 | 
| 154 |   hnode_t* t2 = c->PrettyTree();
 | 
| 155 |   ASSERT_EQ(hnode_e::Record, t2->tag());
 | 
| 156 |   format::PrintTree(t2, ast_f);
 | 
| 157 |   printf("\n");
 | 
| 158 | 
 | 
| 159 |   auto big = Alloc<arith_expr__Big>(mops::BigInt(INT64_MAX));
 | 
| 160 |   hnode_t* t3 = big->PrettyTree();
 | 
| 161 |   ASSERT_EQ(hnode_e::Record, t3->tag());
 | 
| 162 |   format::PrintTree(t3, ast_f);
 | 
| 163 |   printf("\n");
 | 
| 164 | 
 | 
| 165 |   PASS();
 | 
| 166 | }
 | 
| 167 | 
 | 
| 168 | TEST dicts_test() {
 | 
| 169 |   auto m = typed_demo_asdl::Dicts::CreateNull();
 | 
| 170 |   log("m.ss = %p", m->ss);
 | 
| 171 |   log("m.ib = %p", m->ib);
 | 
| 172 | 
 | 
| 173 |   m->ss = Alloc<Dict<BigStr*, BigStr*>>();
 | 
| 174 |   m->ib = Alloc<Dict<int, bool>>();
 | 
| 175 | 
 | 
| 176 |   m->ss->set(StrFromC("foo"), StrFromC("bar"));
 | 
| 177 | 
 | 
| 178 |   m->ib->set(42, true);
 | 
| 179 |   // note: Dict<int, bool>::get() doesn't compile because nullptr isn't valid
 | 
| 180 |   // to return.  But Dict<int, bool>::index() does compile.
 | 
| 181 |   log("mm.ib[42] = %d", m->ib->at(42));
 | 
| 182 | 
 | 
| 183 |   hnode_t* t = m->PrettyTree();
 | 
| 184 |   auto f = mylib::Stdout();
 | 
| 185 |   auto ast_f = Alloc<format::TextOutput>(f);
 | 
| 186 |   // fails with repr(void *)
 | 
| 187 |   // OK change the pretty printer!
 | 
| 188 |   format::PrintTree(t, ast_f);
 | 
| 189 | 
 | 
| 190 |   PASS();
 | 
| 191 | }
 | 
| 192 | 
 | 
| 193 | using typed_demo_asdl::flag_type;
 | 
| 194 | using typed_demo_asdl::flag_type__Bool;
 | 
| 195 | using typed_demo_asdl::SetToArg_;
 | 
| 196 | 
 | 
| 197 | ObjHeader make_global(ObjHeader header) {
 | 
| 198 |   header.heap_tag = HeapTag::Global;
 | 
| 199 |   return header;
 | 
| 200 | }
 | 
| 201 | 
 | 
| 202 | // TODO: We should always use these, rather than 'new flag_type::Bool()'
 | 
| 203 | GcGlobal<flag_type__Bool> g_ft = {make_global(flag_type__Bool::obj_header())};
 | 
| 204 | 
 | 
| 205 | // Use __ style
 | 
| 206 | using typed_demo_asdl::cflow__Return;
 | 
| 207 | GcGlobal<cflow__Return> g_ret = {make_global(cflow__Return::obj_header()), {5}};
 | 
| 208 | 
 | 
| 209 | int i0 = 7;
 | 
| 210 | 
 | 
| 211 | // NOTE: This causes an failed assert() in the GC runtime
 | 
| 212 | #if 0
 | 
| 213 | List<int>* g_list = NewList<int>({i0, 8, 9});
 | 
| 214 | #endif
 | 
| 215 | 
 | 
| 216 | // Dict<BigStr*, int> g_dict = {4, 5, 6};
 | 
| 217 | 
 | 
| 218 | TEST literal_test() {
 | 
| 219 |   // Interesting, initializer list part of the constructor "runs".  Otherwise
 | 
| 220 |   // this doesn't work.
 | 
| 221 |   log("g_ft.tag() = %d", g_ft.obj.tag());
 | 
| 222 |   auto ft = flag_type::Bool;
 | 
| 223 |   ASSERT_EQ(g_ft.obj.tag(), ft->tag());
 | 
| 224 | 
 | 
| 225 |   log("g_ret.tag() = %d", g_ret.obj.tag());
 | 
| 226 |   log("g_ret.status = %d", g_ret.obj.status);
 | 
| 227 |   auto ret = Alloc<cflow__Return>(5);
 | 
| 228 |   ASSERT_EQ(g_ret.obj.tag(), ret->tag());
 | 
| 229 |   ASSERT_EQ(g_ret.obj.status, ret->status);
 | 
| 230 | 
 | 
| 231 | #if 0
 | 
| 232 |   // Wow this works too?  Is it the the constexpr interpreter, or is this code
 | 
| 233 |   // inserted before main()?
 | 
| 234 |   ASSERT_EQ(3, len(g_list));
 | 
| 235 |   ASSERT_EQ_FMT(7, g_list->at(0), "%d");
 | 
| 236 |   ASSERT_EQ_FMT(8, g_list->at(1), "%d");
 | 
| 237 |   ASSERT_EQ_FMT(9, g_list->at(2), "%d");
 | 
| 238 | #endif
 | 
| 239 | 
 | 
| 240 |   PASS();
 | 
| 241 | }
 | 
| 242 | 
 | 
| 243 | TEST string_defaults_test() {
 | 
| 244 |   auto st = Alloc<typed_demo_asdl::Strings>(kEmptyString, kEmptyString);
 | 
| 245 |   ASSERT_EQ(kEmptyString, st->required);
 | 
| 246 |   ASSERT_EQ(kEmptyString, st->optional);
 | 
| 247 | 
 | 
| 248 |   st = typed_demo_asdl::Strings::CreateNull();
 | 
| 249 |   ASSERT_EQ(kEmptyString, st->required);
 | 
| 250 |   ASSERT_EQ(nullptr, st->optional);
 | 
| 251 | 
 | 
| 252 |   st = Alloc<typed_demo_asdl::Strings>(kEmptyString, nullptr);
 | 
| 253 |   ASSERT_EQ(kEmptyString, st->required);
 | 
| 254 |   ASSERT_EQ(nullptr, st->optional);
 | 
| 255 | 
 | 
| 256 |   PASS();
 | 
| 257 | }
 | 
| 258 | 
 | 
| 259 | TEST list_defaults_test() {
 | 
| 260 |   auto o = op_array::CreateNull();
 | 
| 261 |   ASSERT_EQ(nullptr, o->ops);
 | 
| 262 | 
 | 
| 263 |   // Empty list
 | 
| 264 |   auto o2 = op_array::CreateNull(true);
 | 
| 265 |   ASSERT_EQ(0, len(o2->ops));
 | 
| 266 | 
 | 
| 267 |   PASS();
 | 
| 268 | }
 | 
| 269 | 
 | 
| 270 | GREATEST_MAIN_DEFS();
 | 
| 271 | 
 | 
| 272 | int main(int argc, char** argv) {
 | 
| 273 |   gHeap.Init();
 | 
| 274 | 
 | 
| 275 |   GREATEST_MAIN_BEGIN();
 | 
| 276 | 
 | 
| 277 |   RUN_TEST(misc_test);
 | 
| 278 |   RUN_TEST(shared_variant_test);
 | 
| 279 |   RUN_TEST(pretty_print_test);
 | 
| 280 |   RUN_TEST(dicts_test);
 | 
| 281 |   RUN_TEST(literal_test);
 | 
| 282 |   RUN_TEST(string_defaults_test);
 | 
| 283 |   RUN_TEST(list_defaults_test);
 | 
| 284 | 
 | 
| 285 |   gHeap.CleanProcessExit();
 | 
| 286 | 
 | 
| 287 |   GREATEST_MAIN_END();
 | 
| 288 | 
 | 
| 289 |   return 0;
 | 
| 290 | }
 |