1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity very low) 4 module dil.ast.ASTSerializer; 5 6 import dil.ast.Visitor, 7 dil.ast.Node, 8 dil.ast.Declarations, 9 dil.ast.Expressions, 10 dil.ast.Statements, 11 dil.ast.Types, 12 dil.ast.Parameters; 13 import dil.lexer.IdTable; 14 import dil.semantic.Module; 15 import dil.Enums, 16 dil.Diagnostics, 17 dil.String; 18 import common; 19 20 /// Serializes a complete parse tree. 21 class ASTSerializer : Visitor2 22 { 23 static immutable HEADER = "DIL1.0AST\x1A\x04\n"; /// Appears at the start. 24 ubyte[] data; /// The binary text. 25 Token* firstToken; /// The first token in the token array. 26 27 /// An enumeration of types that may appear in the data. 28 enum TID : ubyte 29 { 30 Array = 'A', 31 Null, 32 Char, 33 Bool, 34 Uint, 35 TOK, 36 Protection, 37 LinkageType, 38 StorageClass, 39 NodeKind, 40 Node, 41 Declaration, 42 Statement, 43 Expression, 44 TypeNode, 45 Parameter, 46 TemplateParam, 47 Nodes, 48 Declarations, 49 Statements, 50 Expressions, 51 Types, 52 Parameters, 53 TemplateParams, 54 EnumMemberDecls, 55 BaseClassTypes, 56 CatchStmts, 57 Token, 58 Tokens, 59 TokenArrays, 60 } 61 62 this() 63 { 64 } 65 66 /// Starts serialization. 67 ubyte[] serialize(Module mod) 68 { 69 data ~= HEADER; 70 firstToken = mod.firstToken; 71 visitN(mod.root); 72 return data; 73 } 74 75 /// Returns the index number of a token. 76 /// If token is null, size_t.max is returned. 77 size_t indexOf(Token* token) 78 { 79 return token ? token - firstToken : size_t.max; 80 } 81 82 /// Writes 1 byte. 83 void write1B(ubyte x) 84 { 85 data ~= x; 86 } 87 88 /// Writes T.sizeof bytes. 89 void writeXB(T)(T x) 90 { 91 data ~= (cast(ubyte*)&x)[0..T.sizeof]; 92 } 93 94 /// Writes 2 bytes. 95 alias write2B = writeXB!(ushort); 96 97 /// Writes 4 bytes. 98 alias write4B = writeXB!(uint); 99 100 /// Writes size_t.sizeof bytes. 101 alias writeSB = writeXB!(size_t); 102 103 104 /// Writes the kind of a Node. 105 void write(NodeKind k) 106 { 107 static assert(NodeKind.max <= ubyte.max); 108 write1B(TID.NodeKind); 109 write1B(cast(ubyte)k); 110 } 111 112 /// Writes the protection attribute. 113 void write(Protection prot) 114 { 115 static assert(Protection.max <= ubyte.max); 116 write1B(TID.Protection); 117 write1B(cast(ubyte)prot); 118 } 119 120 /// Writes the StorageClass attribute. 121 void write(StorageClass stcs) 122 { 123 static assert(StorageClass.max <= uint.max); 124 write1B(TID.StorageClass); 125 write4B(cast(uint)stcs); 126 } 127 128 /// Writes the LinkageType attribute. 129 void write(LinkageType lnkg) 130 { 131 static assert(LinkageType.max <= ubyte.max); 132 write1B(TID.LinkageType); 133 write1B(cast(ubyte)lnkg); 134 } 135 136 /// Writes a node. 137 void write(Node n, TID tid) 138 { 139 if (n is null) { 140 write1B(TID.Null); 141 write1B(tid); 142 } 143 else 144 visitN(n); 145 } 146 147 void write(Node n) 148 { 149 write(n, TID.Node); 150 } 151 152 void write(Declaration n) 153 { 154 write(n, TID.Declaration); 155 } 156 157 void write(Statement n) 158 { 159 write(n, TID.Statement); 160 } 161 162 void write(Expression n) 163 { 164 write(n, TID.Expression); 165 } 166 167 void write(TypeNode n) 168 { 169 write(n, TID.TypeNode); 170 } 171 172 void write(Parameter n) 173 { 174 write(n, TID.Parameter); 175 } 176 177 void write(TemplateParam n) 178 { 179 write(n, TID.TemplateParam); 180 } 181 182 /// Writes the mangled array type and then visits each node. 183 void write(Node[] nodes, TID tid) 184 { 185 write1B(TID.Array); 186 write1B(tid); 187 writeSB(nodes.length); 188 foreach (n; nodes) 189 write(n, tid); 190 } 191 192 void write(Node[] nodes) 193 { 194 write(nodes, TID.Nodes); 195 } 196 197 void write(Declaration[] nodes) 198 { 199 write(cast(Node[])nodes, TID.Declarations); 200 } 201 202 void write(Statement[] nodes) 203 { 204 write(cast(Node[])nodes, TID.Statements); 205 } 206 207 void write(Expression[] nodes) 208 { 209 write(cast(Node[])nodes, TID.Expressions); 210 } 211 212 void write(TypeNode[] nodes) 213 { 214 write(cast(Node[])nodes, TID.Types); 215 } 216 217 void write(Parameter[] nodes) 218 { 219 write(cast(Node[])nodes, TID.Parameters); 220 } 221 222 void write(TemplateParam[] nodes) 223 { 224 write(cast(Node[])nodes, TID.TemplateParams); 225 } 226 227 void write(EnumMemberDecl[] nodes) 228 { 229 write(cast(Node[])nodes, TID.EnumMemberDecls); 230 } 231 232 void write(BaseClassType[] nodes) 233 { 234 write(cast(Node[])nodes, TID.BaseClassTypes); 235 } 236 237 void write(CatchStmt[] nodes) 238 { 239 write(cast(Node[])nodes, TID.CatchStmts); 240 } 241 242 /// Writes a char. 243 void write(char c) 244 { 245 write1B(TID.Char); 246 write1B(c); 247 } 248 249 /// Writes a boolean. 250 void write(bool b) 251 { 252 write1B(TID.Bool); 253 write1B(b); 254 } 255 256 /// Writes a uint. 257 void write(uint u) 258 { 259 write1B(TID.Uint); 260 write4B(u); 261 } 262 263 /// Writes a TOK. 264 void write(TOK tok) 265 { 266 assert(TOK.max <= ushort.max); 267 write1B(TID.TOK); 268 write2B(cast(ushort)tok); 269 } 270 271 /// Writes a Token. 272 void write(Token* t) 273 { 274 write1B(TID.Token); 275 writeSB(indexOf(t)); 276 } 277 278 /// Writes an array of Tokens. 279 void write(Token*[] tokens) 280 { 281 write1B(TID.Tokens); 282 writeSB(tokens.length); 283 foreach (t; tokens) 284 writeSB(indexOf(t)); 285 } 286 287 /// Writes an array of arrays of Tokens. 288 void write(Token*[][] tokenLists) 289 { 290 write1B(TID.TokenArrays); 291 writeSB(tokenLists.length); 292 foreach (tokens; tokenLists) 293 write(tokens); 294 } 295 296 // Visitor methods: 297 298 /// Generates a visit method for a specific Node. 299 mixin template visitX(N) 300 { 301 override void visit(N n) 302 { 303 alias Members = Array2Tuple!(N.CTTI_Members); 304 assert(n); 305 write1B(TID.Node); 306 write(n.kind); 307 write(n.begin); 308 write(n.end); 309 static if (is(N : Declaration)) 310 { // Write the attributes of Declarations. 311 write(n.stcs); 312 write(n.prot); 313 } 314 assert(Members.length < ubyte.max); 315 write1B(Members.length); 316 foreach (m; Members) 317 write(mixin("n."~m)); 318 } 319 } 320 321 /// Generates a list of mixin declarations for all Node classes. 322 /// E.g.: 323 /// --- 324 /// mixin visitX!(CompoundDecl); 325 /// mixin visitX!(CompoundStmt); 326 /// mixin visitX!(CondExpr); 327 /// --- 328 static char[] mixinVisitMethods() 329 { 330 char[] code; 331 foreach (name; NodeClassNames) 332 code ~= "mixin visitX!(" ~ name ~ ");\n"; 333 return code; 334 } 335 336 mixin(mixinVisitMethods()); 337 } 338 339 340 341 /// Deserializes a binary AST file. 342 class ASTDeserializer : Visitor 343 { 344 Token*[] tokens; /// The list of Tokens. 345 const(ubyte)* p; /// Current byte. 346 const(ubyte)* end; /// One past the last byte. 347 Diagnostics diag; /// For error messages. 348 349 /// Constructs an object. 350 this(Token*[] tokens, Diagnostics diag) 351 { 352 this.tokens = tokens; 353 this.diag = diag; 354 } 355 356 alias TID = ASTSerializer.TID; 357 358 /// Reads T.sizeof bytes. 359 bool readXB(T)(out T x) 360 { 361 if (p + T.sizeof > end) 362 return false; 363 x = *cast(const T*)p; 364 p += T.sizeof; 365 return true; 366 } 367 368 /// Reads 1 byte. 369 alias read1B = readXB!(ubyte); 370 371 /// Reads 2 bytes. 372 alias read2B = readXB!(ushort); 373 374 /// Reads 4 bytes. 375 alias read4B = readXB!(uint); 376 377 /// Reads size_t.sizeof bytes. 378 alias readSB = readXB!(size_t); 379 380 /// Creates an error message. 381 bool error(cstring msg, ...) 382 { 383 // TODO: 384 return false; 385 } 386 387 /// Reads a byte and checks if it equals tid. 388 bool check(TID tid) 389 { 390 ubyte x; 391 return read1B(x) && x == tid || error("expected ‘TID.{}’", tid); 392 } 393 394 /// Reads a type id. 395 bool read(out TID tid) 396 { 397 return read1B(tid); 398 } 399 400 /// Reads the kind of a Node. 401 bool read(out NodeKind k) 402 { 403 return check(TID.NodeKind) && read1B(*cast(ubyte*)&k) && 404 k <= NodeKind.max || error("NodeKind value out of range"); 405 } 406 407 /// Reads the protection attribute. 408 bool read(out Protection prot) 409 { 410 return check(TID.Protection) && read1B(*cast(ubyte*)&prot) && 411 prot <= Protection.max || error("Protection value out of range"); 412 } 413 414 /// Reads the StorageClass attribute. 415 bool read(out StorageClass stcs) 416 { 417 return check(TID.StorageClass) && read4B(*cast(uint*)&stcs); 418 } 419 420 /// Reads the LinkageType attribute. 421 bool read(out LinkageType lnkg) 422 { 423 return check(TID.LinkageType) && read1B(*cast(ubyte*)&lnkg); 424 } 425 426 /// Reads the mangled array type and then each node. 427 bool read(ref Node[] nodes, TID tid) 428 { 429 size_t len; 430 if (!check(TID.Array) || !check(tid) || !readSB(len)) 431 return false; 432 nodes = new Node[len]; 433 foreach (ref n; nodes) 434 if (!read(n)) 435 return false; 436 return true; 437 } 438 439 bool read(out Node[] nodes) 440 { 441 return read(nodes, TID.Nodes); 442 } 443 444 bool read(out Declaration[] nodes) 445 { 446 return read(*cast(Node[]*)&nodes, TID.Declarations); 447 } 448 449 bool read(out Statement[] nodes) 450 { 451 return read(*cast(Node[]*)&nodes, TID.Statements); 452 } 453 454 bool read(out Expression[] nodes) 455 { 456 return read(*cast(Node[]*)&nodes, TID.Expressions); 457 } 458 459 bool read(out TypeNode[] nodes) 460 { 461 return read(*cast(Node[]*)&nodes, TID.Types); 462 } 463 464 bool read(out Parameter[] nodes) 465 { 466 return read(*cast(Node[]*)&nodes, TID.Parameters); 467 } 468 469 bool read(out TemplateParam[] nodes) 470 { 471 return read(*cast(Node[]*)&nodes, TID.TemplateParams); 472 } 473 474 bool read(out EnumMemberDecl[] nodes) 475 { 476 return read(*cast(Node[]*)&nodes, TID.EnumMemberDecls); 477 } 478 479 bool read(out BaseClassType[] nodes) 480 { 481 return read(*cast(Node[]*)&nodes, TID.BaseClassTypes); 482 } 483 484 bool read(out CatchStmt[] nodes) 485 { 486 return read(*cast(Node[]*)&nodes, TID.CatchStmts); 487 } 488 489 /// Reads a char. 490 bool read(out char c) 491 { 492 return check(TID.Char) && read1B(*cast(ubyte*)&c); 493 } 494 495 /// Reads a boolean. 496 bool read(out bool b) 497 { 498 ubyte u; 499 auto a = check(TID.Bool) && read1B(u) && u <= 1; 500 if (a) 501 b = !!u; 502 return a; 503 } 504 505 /// Reads a uint. 506 bool read(out uint u) 507 { 508 return check(TID.Uint) && read4B(u); 509 } 510 511 /// Reads a TOK. 512 bool read(out TOK tok) 513 { 514 return check(TID.TOK) && read2B(tok) && tok <= TOK.max; 515 } 516 517 /// Reads a Token. 518 bool read(out Token* t) 519 { 520 size_t index; 521 bool b = check(TID.Token) && readSB(index); 522 if (b) 523 t = index == size_t.max ? null : tokens[index]; 524 return b; 525 } 526 527 /// Reads an array of Tokens. 528 bool read(out Token*[] tokens) 529 { 530 size_t len; 531 if (!check(TID.Tokens) || !readSB(len)) 532 return false; 533 tokens = new Token*[len]; 534 foreach (ref t; tokens) 535 if (!read(t)) 536 return false; 537 return true; 538 } 539 540 /// Reads an array of arrays of Tokens. 541 bool read(out Token*[][] tokenLists) 542 { 543 size_t len; 544 if (!check(TID.TokenArrays) || !readSB(len)) 545 return false; 546 tokenLists = new Token*[][len]; 547 foreach (ref tokens; tokenLists) 548 if (!read(tokens)) 549 return false; 550 return true; 551 } 552 553 bool read(ref Node n) 554 { 555 TID tid; 556 NodeKind kind; 557 Token* begin, end; 558 if (!read(tid) && tid == TID.Node || 559 !read(kind) || 560 !read(begin) || 561 !read(end)) 562 return false; // Error 563 n = dispatch(n, kind); 564 if (n is null) 565 return false; // Error 566 n.setTokens(begin, end); 567 return true; 568 } 569 570 bool read(out CompoundDecl n) 571 { 572 return read(*cast(Node*)&n); 573 } 574 575 bool read(out CompoundStmt n) 576 { 577 return read(*cast(Node*)&n); 578 } 579 580 bool read(out Declaration n) 581 { 582 return read(*cast(Node*)&n); 583 } 584 585 bool read(out Statement n) 586 { 587 return read(*cast(Node*)&n); 588 } 589 590 bool read(out Expression n) 591 { 592 return read(*cast(Node*)&n); 593 } 594 595 bool read(out TypeNode n) 596 { 597 return read(*cast(Node*)&n); 598 } 599 600 bool read(out TemplateParameters n) 601 { 602 return read(*cast(Node*)&n); 603 } 604 605 bool read(out Parameters n) 606 { 607 return read(*cast(Node*)&n); 608 } 609 610 bool read(out Parameter n) 611 { 612 return read(*cast(Node*)&n); 613 } 614 615 bool read(out FuncBodyStmt n) 616 { 617 return read(*cast(Node*)&n); 618 } 619 620 bool read(out TemplateArguments n) 621 { 622 return read(*cast(Node*)&n); 623 } 624 625 bool read(out FinallyStmt n) 626 { 627 return read(*cast(Node*)&n); 628 } 629 630 Module deserialize(const ubyte[] data) 631 { 632 p = data.ptr; 633 end = data.ptr + data.length; 634 Node rootDecl; 635 read(rootDecl); 636 return null; 637 } 638 639 mixin template visitX(N) 640 { 641 override returnType!(N) visit(N n) 642 { 643 mixin(generateReaders(N.CTTI_TypeStrs)); 644 static if (is(N : Declaration)) 645 { 646 StorageClass stcs; 647 Protection prot; 648 if (!read(stcs) || !read(prot)) 649 return null; 650 n.setStorageClass(stcs); 651 n.setProtection(prot); 652 } 653 return mixin(generateCtorCall(N.CTTI_Members.length)); 654 } 655 } 656 657 /// Generates e.g.: 658 /// --- 659 /// Token* _0; 660 /// if (!read(_0)) return null; 661 /// Token*[] _1; 662 /// if (!read(_1)) return null; 663 /// --- 664 static char[] generateReaders(string[] types) 665 { 666 char[] code; 667 foreach (i, t; types) 668 { 669 const arg = "_" ~ itoa(i); 670 code ~= t ~ " " ~ arg ~ ";\n" ~ 671 "if (!read(" ~ arg ~ ")) return null;\n"; 672 } 673 return code; 674 } 675 676 /// Generates e.g.: _0, _1, _2 677 static char[] generateCtorCall(size_t num) 678 { 679 char[] code = "new N( ".dup; 680 for (size_t i; i < num; i++) 681 code ~= "_" ~ itoa(i) ~ ","; 682 code[$-1] = ')'; 683 return code; 684 } 685 686 /// Generates e.g.: mixin visitX!(CompoundDecl); 687 static char[] generateMixins() 688 { 689 char[] code; 690 foreach (name; NodeClassNames) 691 code ~= "mixin visitX!(" ~ name ~ ");\n"; 692 return code; 693 } 694 695 mixin(generateMixins()); 696 }