Changeset 135
- Timestamp:
- 01/18/08 08:38:00 (10 months ago)
- Files:
-
- branches/1.9/bin/walnut.exe (modified) (previous)
- branches/1.9/bin/walnut.lib (modified) (previous)
- branches/1.9/documentation/ECMA Violations.txt (modified) (1 diff)
- branches/1.9/source/interpreter.d (modified) (24 diffs)
- branches/1.9/source/value.d (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.9/documentation/ECMA Violations.txt
r123 r135 5 5 4.2 I have defined a "primitive Value" as inclusive of Function, Array and Object types. 6 6 7.5.3 Future Reserved Keywords are not reserved. 7 7.6 Identifiers do not support \uXXXX notation as part of the identifier. 8 8.6.2, 9 8.7 These Internal Properties and Methods are NOT and will not be implemented as per ECMA spec. 10 8.8 The List Type is not used. Instead, dynamic D arrays are. 11 8.9 The Completion Type may or may not be used. 12 9.1 ToPrimitive is implicit and inlined for all Objects where (___value__ != this) 13 9.5-9.7 toInteger covers ToInt32, ToInt16, ToUInt32, ToUInt16; and only returns the "int" D type. 14 15 10.X I have not yet examined thoroughly. 16 17 11.1 PrimaryExpression is currently any result of parseOperand branches/1.9/source/interpreter.d
r134 r135 11 11 12 12 /* 13 Bug: 14 dumpTree is demonstrating that somewhere between expressions and statements, we're generating a shadow token tree. 15 This will have to be cleaned up before continuing further. 16 17 Code naturally matches to matching parens, so if we encounter one of ], }, ) in code, we know we're unmatched. 18 The opposite case of never finding a ], }, ) for some [, {, ( is already tackled. 13 BUG: 7.9.1 14 see also (interesting) 7.9.2 on page 22/23 15 If a TOKEN NEWLINE } sequence is found, it may be transformed to TOKEN SEMI NEWLINE } if the former is invalid. 19 16 */ 20 17 … … 98 95 if(c[1] == '*') { 99 96 for(c++; c[0] != 0x00 && !(c[0] == '*' && (++c)[0] == '/'); c++) 100 {} 97 { 98 if(c[0] == '\n') 99 line++; 100 if(c[0] == '\r' && c[1] != '\n') { 101 line++; 102 c++; 103 } 104 } 101 105 continue; 102 106 } … … 107 111 } 108 112 109 110 113 /** 114 Status: (pass) 115 Synopsis: consumes an operator if it's there and stores it in v. 116 */ 117 void parseBinaryOperator() 118 { 119 printf("!%d : parseBinaryOperator()\n",c); 120 switch(c[0]) { 121 case '+': 122 if(c[1] == '=') { 123 c+=2; 124 v.type = TYPE.ADDA; 125 return; 126 } 127 c++; 128 v.type = TYPE.ADD; 129 return; 130 case '-': 131 if(c[1] == '=') { 132 c+=2; 133 v.type = TYPE.SUBA; 134 return; 135 } 136 c++; 137 v.type = TYPE.SUB; 138 return; 139 case '*': 140 if(c[1] == '=') { 141 c+=2; 142 v.type = TYPE.MULA; 143 return; 144 } 145 c++; 146 v.type = TYPE.MUL; 147 return; 148 case '/': 149 if(c[1] == '=') { 150 c+=2; 151 v.type = TYPE.DIVA; 152 return; 153 } 154 c++; 155 v.type = TYPE.DIV; 156 return; 157 case '%': 158 if(c[1] == '=') { 159 c+=2; 160 v.type = TYPE.MODA; 161 return; 162 } 163 c++; 164 v.type = TYPE.MOD; 165 return; 166 case '~': 167 if(c[1] == '=') { 168 c+=2; 169 v.type = TYPE.NOTA; 170 return; 171 } 172 c++; 173 v.type = TYPE.NOT; 174 return; 175 case '&': 176 if(c[1] == '&') { 177 c+=2; 178 v.type = TYPE.LOGAND; 179 return; 180 } 181 if(c[1] == '=') { 182 c+=2; 183 v.type = TYPE.ANDA; 184 return; 185 } 186 c++; 187 v.type = TYPE.AND; 188 return; 189 case '|': 190 if(c[1] == '|') { 191 c+=2; 192 v.type = TYPE.LOGOR; 193 return; 194 } 195 if(c[1] == '=') { 196 c+=2; 197 v.type = TYPE.ORA; 198 return; 199 } 200 c++; 201 v.type = TYPE.OR; 202 return; 203 case '=': 204 if(c[1] == '=') { 205 if(c[2] == '=') { 206 c+=3; 207 v.type = TYPE.EQUIV; 208 return; 209 } 210 c+=2; 211 v.type = TYPE.CMPE; 212 return; 213 } 214 c++; 215 v.type = TYPE.MOV; 216 return; 217 case '!': 218 if(c[1] == '=') { 219 if(c[2] == '=') { 220 c+=3; 221 v.type = TYPE.NEQUIV; 222 return; 223 } 224 c+=2; 225 v.type = TYPE.CMPNE; 226 return; 227 } 228 assert(0, TEXT._unexpected_token); 229 case '<': 230 if(c[1] == '<') { 231 if(c[2] == '=') { 232 c+=3; 233 v.type = TYPE.SHLA; 234 return; 235 } 236 c+=2; 237 v.type = TYPE.SHL; 238 return; 239 } 240 if(c[1] == '=') { 241 c+=2; 242 v.type = TYPE.CMPLE; 243 } 244 c++; 245 v.type = TYPE.CMPL; 246 return; 247 case '>': 248 if(c[1] == '>') { 249 if(c[2] == '=') { 250 c+=3; 251 v.type = TYPE.SHRA; 252 return; 253 } 254 if(c[2] == '>') { 255 if(c[3] == '=') { 256 c+=4; 257 v.type = TYPE.SARA; 258 return; 259 } 260 c+=3; 261 v.type = TYPE.SAR; 262 return; 263 } 264 c+=2; 265 v.type = TYPE.SHR; 266 return; 267 } 268 if(c[1] == '=') { 269 c+=2; 270 v.type = TYPE.CMPGE; 271 } 272 c++; 273 v.type = TYPE.CMPG; 274 return; 275 case '.': 276 c++; 277 v.type = TYPE.DOT; 278 return; 279 case 'i': 280 if(c[1] == 'n' && (0x61 > c[2] || c[2] > 0x7A) && (0x41 > c[2] || c[2] > 0x5A) && c[2] != '$') { 281 c+=2; 282 v.type = TYPE.KEYin; 283 return; 284 } 285 default: 286 } 287 } 288 289 /** 290 Primary Expression 111 291 Status: 112 292 strings (pass) … … 134 314 case '\'': 135 315 case '"': 136 // String literal 316 /* 317 String literal. 318 BUG: 7.8.4 319 The code point value of \X string escape code sequences is currently '\','X' 320 I'm hesitant to touch this because I don't want to have to cumulate individual characters 321 into the new produced string? Perhaps one could cumulate slices up to and after 322 escape sequences? 323 */ 137 324 for(c++; c[0] != cMark[0]; c++) { 138 325 assert(c[0] != 0x00, TEXT._unterminated_string); 139 if(c[0] == '\\') 326 if(c[0] == '\\') { 140 327 c++; 141 } 142 // NOTE: \n \u etc are being stored literally, not as 0x0D, etc. 328 switch(c[0]) { 329 case 'b': 330 case 't': 331 case 'n': 332 case 'v': 333 case 'f': 334 case 'r': 335 case '"': 336 case '\'': 337 case '\\': 338 default: 339 // see page 20 of ECMA-262.pdf for values. 340 } 341 } 342 } 143 343 v.s = cMark[1..(c-cMark)]; 144 344 v.type = TYPE.STRING; … … 336 536 v.values = &b2[0]; 337 537 v.type = TYPE.OBJECT; 538 /+ 539 // BUG: this causes an access violation!?!? 540 v.opIndexAssign(v,TEXT.___value__); 541 +/ 338 542 return; 339 543 default: 340 544 // Identifier 341 for(cMark = c; (0x41 <= c[0] && c[0] <= 0x5A) || (0x61 <= c[0] && c[0] <= 0x7A) ; c++)545 for(cMark = c; (0x41 <= c[0] && c[0] <= 0x5A) || (0x61 <= c[0] && c[0] <= 0x7A) || c[0] == '$' || c[0] == '_'; c++) 342 546 {} 343 547 if(cMark < c) { … … 347 551 switch(s) { 348 552 case TEXT._break: 553 /* Break Statement 12.8 page 67; related to continue, return, goto */ 349 554 v.type = TYPE.KEYbreak; 350 555 buffer ~= v; 351 parseOptionalWS(); 556 int lineMark = line; 557 parseOptionalWS(); 558 assert(lineMark == line, TEXT._unexpected_token); 559 cMark = c; 352 560 parseOperand(); 353 if(v.type == TYPE.IDENT) { 561 if(cMark < c) { 562 assert(v.type == TYPE.IDENT, TEXT._unexpected_token); 354 563 buffer ~= v; 355 564 v.a = buffer; 356 565 v.type = TYPE.EXPRESSION; 357 return;566 parseOptionalWS(); 358 567 } 568 assert(c[0] == ';', TEXT._unexpected_token); 569 c++; 359 570 return; 360 571 case TEXT._case: … … 374 585 v.type = TYPE.KEYcatch; 375 586 buffer ~= v; 376 v = UNDEFINED;377 587 parseOptionalWS(); 378 588 assert(c[0] == '(', TEXT._unexpected_token); 379 589 c++; 380 590 parseOptionalWS(); 591 cMark = c; 381 592 parseOperand(); 382 assert( v.type == TYPE.IDENT, TEXT._unexpected_token);593 assert(cMark < c && v.type == TYPE.IDENT, TEXT._unexpected_token); 383 594 buffer ~= v; 384 595 parseOptionalWS(); … … 386 597 c++; 387 598 parseOptionalWS(); 599 cMark = c; 388 600 parseStatement(); 389 assert( v.type == TYPE.STATEMENTS, TEXT._unexpected_token);601 assert(cMark < c && v.type == TYPE.STATEMENTS, TEXT._unexpected_token); 390 602 buffer ~= v; 391 603 v.a = buffer; … … 393 605 return; 394 606 case TEXT._continue: 607 /* Continue Statement 12.7 page 66; related to break, return, goto */ 395 608 v.type = TYPE.KEYcontinue; 396 609 buffer ~= v; 397 parseOptionalWS(); 610 int lineMark = line; 611 parseOptionalWS(); 612 assert(lineMark == line, TEXT._unexpected_token); 613 cMark = c; 398 614 parseOperand(); 399 if(v.type == TYPE.IDENT) { 615 if(cMark < c) { 616 assert(v.type == TYPE.IDENT, TEXT._unexpected_token); 400 617 buffer ~= v; 401 618 v.a = buffer; 402 619 v.type = TYPE.EXPRESSION; 403 return;620 parseOptionalWS(); 404 621 } 622 assert(c[0] == ';', TEXT._unexpected_token); 623 c++; 405 624 return; 406 625 case TEXT._default: … … 419 638 return; 420 639 case TEXT._do: 640 /* 641 DoWhile Statement 12.6 page 64 642 BUG: incomplete. 643 */ 421 644 v.type = TYPE.KEYdo; 422 645 return; … … 434 657 return; 435 658 case TEXT._for: 659 /* For Statement 12.6 page 64 660 BUG: does not accept the (x in y) form. 661 BUG?: currently accepts a much broader range of tokens, verify correctness later. 662 */ 436 663 v.type = TYPE.KEYfor; 664 buffer ~= v; 665 parseOptionalWS(); 666 assert(c[0] == '(', TEXT._unexpected_token); 667 for(i = 0; i < 3; i++) { 668 parseOptionalWS(); 669 v = UNDEFINED; 670 parseExpression(); 671 buffer ~= v; // yes, even if it's undefined, we need a placeholder so we consume all 3. 672 } 673 parseOptionalWS(); 674 assert(c[0] == ')', TEXT._unexpected_token); 675 parseOptionalWS(); 676 cMark = c; 677 parseStatement(); 678 assert(cMark < c, TEXT._unexpected_token); 679 buffer ~= v; 680 v.a = buffer; 681 v.type = TYPE.EXPRESSION; 437 682 return; 438 683 case TEXT._goto: … … 448 693 return; 449 694 case TEXT._if: 695 /* If Statement, 12.5 page 63 696 BUG: 697 Does not consume ELSE STATEMENT 698 */ 450 699 v.type = TYPE.KEYif; 700 buffer ~= v; 701 parseOptionalWS(); 702 assert(c[0] == '(', TEXT._unexpected_token); 703 c++; 704 parseOptionalWS(); 705 cMark = c; 706 parseOperand(); 707 assert(cMark < c && v.type == TYPE.IDENT, TEXT._unexpected_token); 708 buffer ~= v; 709 parseOptionalWS(); 710 assert(c[0] == ')', TEXT._unexpected_token); 711 c++; 712 parseOptionalWS(); 713 cMark = c; 714 parseStatement(); 715 assert(cMark < c && v.type == TYPE.STATEMENTS, TEXT._unexpected_token); 716 buffer ~= v; 717 v.a = buffer; 718 v.type = TYPE.EXPRESSION; 451 719 return; 452 720 case TEXT._instanceof: … … 454 722 return; 455 723 case TEXT._in: 456 v.type = TYPE.KEYin; 724 // in cannot be used as an operand, because it's an operator 725 assert(0,TEXT._unexpected_token); 457 726 return; 458 727 case TEXT._new: … … 460 729 return; 461 730 case TEXT._return: 731 /* Return Statement 12.9 page 67 */ 462 732 v.type = TYPE.KEYreturn; 733 int lineMark = line; 734 parseOptionalWS(); 735 buffer ~= v; 736 v = UNDEFINED; 737 assert(lineMark == line, TEXT._unexpected_token); 738 parseExpression(); 739 if(v != UNDEFINED) 740 buffer ~= v; 741 parseOptionalWS(); 742 assert(c[0] == ';', TEXT._unexpected_token); 743 c++; 463 744 return; 464 745 case TEXT._switch: 746 /* Switch Statement 12.11 page 68 */ 465 747 v.type = TYPE.KEYswitch; 466 748 return; 467 749 case TEXT._throw: 750 /* Throw Statement 12.13 page 69 */ 468 751 v.type = TYPE.KEYthrow; 752 int lineMark = line; 753 parseOptionalWS(); 754 buffer ~= v; 755 assert(lineMark == line, TEXT._unexpected_token); 756 cMark = c; 757 parseExpression(); 758 assert(cMark < c, TEXT._unexpected_token); 759 buffer ~= v; 760 parseOptionalWS(); 761 assert(c[0] == ';', TEXT._unexpected_token); 762 c++; 763 v.a = buffer; 764 v.type = TYPE.EXPRESSION; 469 765 return; 470 766 case TEXT._try: 767 /* Try Statement 12.14 page 70 768 BUG: should consume catch and finally. 769 */ 471 770 v.type = TYPE.KEYtry; 472 771 buffer ~= v; … … 483 782 return; 484 783 case TEXT._var: 784 /* Variable statement 12.2 page 62 */ 485 785 Value v2; 486 786 v2.type = TYPE.KEYvar; … … 504 804 return; 505 805 case TEXT._while: 806 /* While Statement 12.6.2 page 64 */ 506 807 v.type = TYPE.KEYwhile; 808 buffer ~= v; 809 parseOptionalWS(); 810 assert(c[0] == '(', TEXT._unexpected_token); 811 c++; 812 parseOptionalWS(); 813 cMark = c; 814 parseOperand(); 815 assert(cMark < c && v.type == TYPE.IDENT, TEXT._unexpected_token); 816 buffer ~= v; 817 parseOptionalWS(); 818 assert(c[0] == ')', TEXT._unexpected_token); 819 c++; 820 parseOptionalWS(); 821 cMark = c; 822 parseStatement(); 823 assert(cMark < c && v.type == TYPE.STATEMENTS, TEXT._unexpected_token); 824 buffer ~= v; 825 v.a = buffer; 826 v.type = TYPE.EXPRESSION; 507 827 return; 508 828 case TEXT._with: 829 /* With Statement 12.10, page 67 */ 509 830 v.type = TYPE.KEYwith; 831 buffer ~= v; 832 parseOptionalWS(); 833 assert(c[0] == '(', TEXT._unexpected_token); 834 c++; 835 parseOptionalWS(); 836 cMark = c; 837 parseOperand(); 838 assert(cMark < c && v.type == TYPE.IDENT, TEXT._unexpected_token); 839 buffer ~= v; 840 parseOptionalWS(); 841 assert(c[0] == ')', TEXT._unexpected_token); 842 c++; 843 parseOptionalWS(); 844 cMark = c; 845 parseStatement(); 846 assert(cMark < c && v.type == TYPE.STATEMENTS, TEXT._unexpected_token); 847 buffer ~= v; 848 v.a = buffer; 849 v.type = TYPE.EXPRESSION; 510 850 return; 511 851 default: … … 513 853 v.type = TYPE.IDENT; 514 854 assert(c[0] != '[',"Parser doesn't support array indexes yet"); 855 if(c[0] == '[') { 856 c++; 857 // parse array index 858 } 515 859 /* 516 860 BUG: this is where we parse array indices. Accept a unaryexpression inside; test that the result is a number or string at evaluation. 517 861 We don't allow whitespace between idents and their array indices, so try parsing it from here. 518 862 */ 519 int lineMark = line; 520 parseOptionalWS(); 521 if(lineMark != line) 522 return; 863 parseOptionalWS(); 523 864 assert(c[0] != '(',"Parser doesn't support function parameters yet"); 865 if(c[0] == '(') { 866 c++; 867 // parse function parameters. 868 } 524 869 /* 525 870 BUG: this is where we parse params. 526 We do allow whitespace between a function ident and it's parameters, but not new lines? 527 so we should try that from here? 528 529 Is it possible to see an ident followed by () for any other legal case? 871 We do allow whitespace between a function ident and it's parameters, including new lines. 530 872 */ 531 873 return; … … 537 879 538 880 /** 539 Status: (pass) 540 Synopsis: consumes an operator if it's there and stores it in v. 541 */ 542 void parseBinaryOperator() 543 { 544 printf("!%d : parseBinaryOperator()\n",c); 545 switch(c[0]) { 546 case '+': 547 if(c[1] == '=') { 548 c+=2; 549 v.type = TYPE.ADDA; 550 return; 551 } 552 c++; 553 v.type = TYPE.ADD; 554 return; 555 case '-': 556 if(c[1] == '=') { 557 c+=2; 558 v.type = TYPE.SUBA; 559 return; 560 } 561 c++; 562 v.type = TYPE.SUB; 563 return; 564 case '*': 565 if(c[1] == '=') { 566 c+=2; 567 v.type = TYPE.MULA; 568 return; 569 } 570 c++; 571 v.type = TYPE.MUL; 572 return; 573 case '/': 574 if(c[1] == '=') { 575 c+=2; 576 v.type = TYPE.DIVA; 577 return; 578 } 579 c++; 580 v.type = TYPE.DIV; 581 return; 582 case '%': 583 if(c[1] == '=') { 584 c+=2; 585 v.type = TYPE.MODA; 586 return; 587 } 588 c++; 589 v.type = TYPE.MOD; 590 return; 591 case '~': 592 if(c[1] == '=') { 593 c+=2; 594 v.type = TYPE.NOTA; 595 return; 596 } 597 c++; 598 v.type = TYPE.NOT; 599 return; 600 case '&': 601 if(c[1] == '&') { 602 c+=2; 603 v.type = TYPE.LOGAND; 604 return; 605 } 606 if(c[1] == '=') { 607 c+=2; 608 v.type = TYPE.ANDA; 609 return; 610 } 611 c++; 612 v.type = TYPE.AND; 613 return; 614 case '|': 615 if(c[1] == '|') { 616 c+=2; 617 v.type = TYPE.LOGOR; 618 return; 619 } 620 if(c[1] == '=') { 621 c+=2; 622 v.type = TYPE.ORA; 623 return; 624 } 625 c++; 626 v.type = TYPE.OR; 627 return; 628 case '=': 629 if(c[1] == '=') { 630 c+=2; 631 v.type = TYPE.CMPE; 632 return; 633 } 634 c++; 635 v.type = TYPE.MOV; 636 return; 637 case '!': 638 if(c[1] == '=') { 639 c+=2; 640 v.type = TYPE.CMPNE; 641 return; 642 } 643 assert(0, TEXT._unexpected_token); 644 case '<': 645 if(c[1] == '<') { 646 if(c[2] == '=') { 647 c+=3; 648 v.type = TYPE.SHLA; 649 return; 650 } 651 c+=2; 652 v.type = TYPE.SHL; 653 return; 654 } 655 if(c[1] == '=') { 656 c+=2; 657 v.type = TYPE.CMPLE; 658 } 659 c++; 660 v.type = TYPE.CMPL; 661 return; 662 case '>': 663 if(c[1] == '>') { 664 if(c[2] == '=') { 665 c+=3; 666 v.type = TYPE.SHRA; 667 return; 668 } 669 if(c[2] == '>') { 670 if(c[3] == '=') { 671 c+=4; 672 v.type = TYPE.SARA; 673 return; 674 } 675 c+=3; 676 v.type = TYPE.SAR; 677 return; 678 } 679 c+=2; 680 v.type = TYPE.SHR; 681 return; 682 } 683 if(c[1] == '=') { 684 c+=2; 685 v.type = TYPE.CMPGE; 686 } 687 c++; 688 v.type = TYPE.CMPG; 689 return; 690 case '.': 691 c++; 692 v.type = TYPE.DOT; 693 return; 694 default: 695 } 696 } 697 698 /** 699 Status: (pass) 700 Synopsis: consumes (!|++|--)operand(++|--) 881 BUG 11.3, 11.4 on page 45 882 This should be replaced with parseUnaryOperator, which is assumed to be prefix. 883 The postfix ++ and -- should be handled separately. 884 885 Synopsis: consumes (!|++|--)operand(++|--|:) 701 886 */ 702 887 void parseUnaryExpression() … … 749 934 buffer ~= v; 750 935 } 936 break; 937 case ':': 938 c++; 939 bFlag = true; 940 v.type = TYPE.COLON; 941 buffer ~= v; 751 942 default: 752 943 } … … 759 950 760 951 /** 761 Status: (pass) 952 Expression Statement, 12.4, page 63 953 BUG: 954 The start of one expression can be *immediately* after the end of the last. 955 Exerpt: NOTE 956 For example: 957 3in 958 is an error and not the two input elements 3 and in. 959 960 BUG: 11.5, 11.6, 11.7, 11.8, 11.9, 11.10, 11.11, 11.13 page 48 961 Higher precedence operators need to be moved left after parseExpression is mostly complete. 962 963 BUG: 11.12 page 58 964 need to be able to correctly consume ? and : characters to build conditionals. 965 966 BUG: 11.14 page 60 967 need to correctly parse commas in expressions. 968 762 969 Synopsis: Consumes unaryExpression [ binaryOperator unaryExpression ]* 763 970 */ … … 773 980 assert(cMark < c, TEXT._unexpected_token); 774 981 do { 775 // printf("!%.*s\n",std.string.toString(v.type));776 982 buffer ~= v; 777 // now we need to read however many combos of binaryOperator unaryExpression we get.778 983 parseOptionalWS(); 779 984 cMark = c; 780 985 parseBinaryOperator(); 781 if(cMark == c) // okay, we're done986 if(cMark == c) 782 987 break; 783 988 bFlag = true; … … 788 993 assert(cMark < c, TEXT._unexpected_token); 789 994 } while(1); 995 /* Empty Statement 12.3 page 63 */ 790 996 if(c[0] == ';') 791 997 c++; 792 793 // if we've got more than a unaryexpression794 998 if(bFlag) { 795 999 v.a = buffer.dup; … … 797 1001 return; 798 1002 } 799 // what unaryexpression returned800 1003 v = buffer[0]; 801 1004 } … … 816 1019 817 1020 /* 818 Bug: how do we differentiate this from an object literal?!? 819 It's quite possible to start with one. 1021 12.1 Block 1022 1023 Bug: 1024 How do we differentiate this from an object literal at the beginning of a statement? 820 1025 */ 821 1026 if(c[0] == '{') { branches/1.9/source/value.d
r130 r135 86 86 NEG = 43, 87 87 AND = 44, 88 OR = 45,88 OR = 45, 89 89 SHL = 46, 90 90 SHR = 47, … … 94 94 CMPNE = 50, 95 95 CMPL = 51, 96 CMPLE = 52,96 CMPLE = 52, 97 97 CMPG = 53, 98 98 CMPGE = 54, 99 EQUIV = 82, 100 NEQUIV = 83, 99 101 100 102 LOGOR = 55, … … 130 132 131 133 /// ACCESS can be checked at runtime to find out whether an Object slot should be accessed a certain way 134 /* 135 BUG: These should be named ReadOnly, DontEnum, DontDelete, Internal as per 8.6.1, page 26 136 Internal would be useful for __value__ if we assume it takes the first slot; and isn't accessible by the script. 137 */ 132 138 enum ACCESS : ubyte {
