|
109 | 109 | return x |
110 | 110 | } |
111 | 111 |
|
112 | | - toString() { |
113 | | - const stringify = (obj) => { |
114 | | - if (obj instanceof jwArray.Type) { |
115 | | - return `[${obj.array.map(item => stringify(item)).join(",")}]`; |
116 | | - } |
117 | | - if (isArray(obj)) { |
118 | | - return `[${obj.map(stringify).join(",")}]`; |
119 | | - } |
120 | | - if (obj instanceof dogeiscutObject.Type) { |
121 | | - return obj.toString(); |
122 | | - } |
123 | | - if (obj !== null && typeof obj === "object") { |
124 | | - if (typeof obj.dogeiscutObjectHandler == "function") { |
125 | | - return obj.dogeiscutObjectHandler() |
126 | | - } |
127 | | - if (typeof obj.jwArrayHandler == "function") { |
128 | | - return obj.jwArrayHandler() |
129 | | - } |
130 | | - const entries = Object.entries(obj) |
131 | | - .map(([key, value]) => `"${key.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}":${stringify(value)}`) |
132 | | - .join(","); |
133 | | - return `{${entries}}`; |
134 | | - } |
135 | | - if (obj === null || obj === undefined) return "null"; |
136 | | - if (typeof obj === "string") return JSON.stringify(obj); |
137 | | - if (typeof obj === "number" || typeof obj === "boolean") return obj.toString(); |
138 | | - return "?"; |
139 | | - }; |
140 | | - |
141 | | - return stringify(this.object); |
| 112 | + toString(pretty = false) { |
| 113 | + return JSON.stringify(this.object, null, pretty ? "\t" : null) |
142 | 114 | } |
143 | 115 |
|
144 | 116 | toVisualContent(border = '1px solid #ccc', keyBackground = '#f9f9f9', background = '#fff') { |
|
295 | 267 | Object.entries(this.object).map(([key, value]) => { |
296 | 268 | if (typeof value === "object" && value !== null) { |
297 | 269 | if (typeof value.toJSON === "function") return [key, value.toJSON()] |
298 | | - if (typeof value.toString === "function") return [key, value.toString()] |
| 270 | + //if (typeof value.toString === "function") return [key, value.toString()] |
299 | 271 | return [key, JSON.stringify(value)] |
300 | 272 | } |
301 | 273 | return [key, value] |
|
359 | 331 |
|
360 | 332 | class Extension { |
361 | 333 | constructor() { |
362 | | - vm.runtime.registerCompiledExtensionBlocks('dogeiscutObject', this.getCompileInfo()); |
363 | | - |
364 | 334 | vm.dogeiscutObject = dogeiscutObject |
365 | | - |
366 | 335 | vm.runtime.registerSerializer( |
367 | 336 | "dogeiscutObject", |
368 | 337 | v => { |
|
400 | 369 |
|
401 | 370 | if (!vm.jwArray) vm.extensionManager.loadExtensionIdSync('jwArray') |
402 | 371 | jwArray = vm.jwArray |
| 372 | + |
| 373 | + vm.runtime.registerCompiledExtensionBlocks('dogeiscutObject', this.getCompileInfo()); |
403 | 374 | } |
404 | 375 |
|
405 | 376 | getInfo() { |
|
453 | 424 | ARRAY: jwArray.Argument |
454 | 425 | } |
455 | 426 | }, |
| 427 | + // future idea |
| 428 | + // { |
| 429 | + // opcode: 'fromLists', |
| 430 | + // text: 'from lists keys: [KEY_LIST] values: [VALUE_LIST}', |
| 431 | + // ...dogeiscutObject.Block, |
| 432 | + // }, |
456 | 433 | '---', |
457 | 434 | { |
458 | 435 | opcode: 'currentObject', |
|
464 | 441 | { |
465 | 442 | opcode: 'builder', |
466 | 443 | text: 'object builder [CURRENT_OBJECT]', |
467 | | - ...dogeiscutObject.Block, |
| 444 | + branches: [{}], |
468 | 445 | arguments: { |
469 | 446 | CURRENT_OBJECT: { |
470 | 447 | fillIn: 'currentObject' |
471 | 448 | }, |
472 | 449 | }, |
473 | | - branches: [{ |
474 | | - //accepts: 'dogeiscutObjectBuilder' |
475 | | - }], |
| 450 | + ...dogeiscutObject.Block, |
476 | 451 | }, |
477 | 452 | { |
478 | 453 | opcode: 'builderAppend', |
479 | 454 | text: 'append key [KEY] value [VALUE] to builder', |
480 | 455 | blockType: Scratch.BlockType.COMMAND, |
481 | | - //notchAccepts: 'dogeiscutObjectBuilder', |
482 | 456 | arguments: { |
483 | 457 | KEY: { |
484 | 458 | type: Scratch.ArgumentType.STRING, |
|
496 | 470 | opcode: 'builderAppendEmpty', |
497 | 471 | text: 'append key [KEY] to builder', |
498 | 472 | blockType: Scratch.BlockType.COMMAND, |
499 | | - //notchAccepts: 'dogeiscutObjectBuilder', |
500 | 473 | arguments: { |
501 | 474 | KEY: { |
502 | 475 | type: Scratch.ArgumentType.STRING, |
|
509 | 482 | opcode: 'builderSet', |
510 | 483 | text: 'set builder to [OBJECT]', |
511 | 484 | blockType: Scratch.BlockType.COMMAND, |
512 | | - //notchAccepts: 'dogeiscutObjectBuilder', |
513 | 485 | arguments: { |
514 | 486 | OBJECT: dogeiscutObject.Argument |
515 | 487 | } |
|
603 | 575 | ...dogeiscutObject.Block, |
604 | 576 | }, |
605 | 577 | '---', |
| 578 | + { |
| 579 | + opcode: 'toString', |
| 580 | + text: 'stringify [OBJECT] [FORMAT]', |
| 581 | + blockType: Scratch.BlockType.REPORTER, |
| 582 | + arguments: { |
| 583 | + OBJECT: dogeiscutObject.Argument, |
| 584 | + FORMAT: { |
| 585 | + menu: "stringifyFormat", |
| 586 | + defaultValue: "compact" |
| 587 | + } |
| 588 | + } |
| 589 | + }, |
| 590 | + '---', |
606 | 591 | { |
607 | 592 | opcode: 'keys', |
608 | 593 | text: 'keys of [OBJECT]', |
|
670 | 655 | } |
671 | 656 | } |
672 | 657 | }, |
673 | | - ] |
| 658 | + ], |
| 659 | + menus: { |
| 660 | + list: { |
| 661 | + acceptReporters: false, |
| 662 | + items: "getLists", |
| 663 | + }, |
| 664 | + stringifyFormat: { |
| 665 | + acceptReporters: false, |
| 666 | + items: [ |
| 667 | + "compact", |
| 668 | + "pretty" |
| 669 | + ] |
| 670 | + } |
| 671 | + } |
674 | 672 | } |
675 | 673 | } |
676 | 674 |
|
677 | 675 | getCompileInfo() { |
678 | 676 | return { |
679 | 677 | ir: { |
680 | | - builder: (generator, block) => ({ |
681 | | - kind: 'input', |
682 | | - substack: generator.descendSubstack(block, 'SUBSTACK') |
683 | | - }), |
| 678 | + builder: (generator, block) => { |
| 679 | + generator.script.yields = true |
| 680 | + return { |
| 681 | + kind: 'input', |
| 682 | + substack: generator.descendSubstack(block, 'SUBSTACK') |
| 683 | + } |
| 684 | + } |
684 | 685 | }, |
685 | 686 | js: { |
686 | 687 | builder: (node, compiler, imports) => { |
687 | 688 | const originalSource = compiler.source; |
688 | 689 |
|
689 | | - compiler.source = '(yield* (function*() {'; |
690 | | - compiler.source += ' const __inner = (yield* (function*() {'; |
691 | | - compiler.source += ` thread._dogeiscutObjectBuilderIndex ??= [];`; |
692 | | - compiler.source += ` thread._dogeiscutObjectBuilderIndex.push(Object.create(null));`; |
| 690 | + compiler.source = 'vm.dogeiscutObject.Type.toObject(yield* (function*() {'; |
| 691 | + compiler.source += 'thread._dogeiscutObjectBuilderIndex ??= [];'; |
| 692 | + compiler.source += 'thread._dogeiscutObjectBuilderIndex.push(Object.create(null));'; |
693 | 693 | compiler.descendStack(node.substack, new imports.Frame(false, undefined, true)); |
694 | | - compiler.source += ` return new runtime.ext_dogeiscutObject.BuilderReturnValue(thread._dogeiscutObjectBuilderIndex.pop());`; |
695 | | - compiler.source += ' })());'; |
696 | | - compiler.source += ' const __result = __inner;'; |
697 | | - compiler.source += ' if (!(__result instanceof runtime.ext_dogeiscutObject.BuilderReturnValue)) {'; |
698 | | - compiler.source += ' throw "Return statements are not supported in builders.";'; |
699 | | - compiler.source += ' }'; |
700 | | - compiler.source += ' return new runtime.vm.dogeiscutObject.Type(__result.value);'; |
| 694 | + compiler.source += 'return thread._dogeiscutObjectBuilderIndex.pop();'; |
701 | 695 | compiler.source += '})())'; |
702 | 696 |
|
703 | 697 | const stackSource = compiler.source; |
|
708 | 702 | }; |
709 | 703 | } |
710 | 704 |
|
711 | | - BuilderReturnValue = class { |
712 | | - constructor(value) { |
713 | | - this.value = value |
714 | | - } |
715 | | - } |
716 | | - |
717 | 705 | /* Blocks */ |
718 | 706 |
|
719 | 707 | blank() { |
|
745 | 733 | if (util.thread._dogeiscutObjectBuilderIndex && util.thread._dogeiscutObjectBuilderIndex.length > 0) { |
746 | 734 | return dogeiscutObject.Type.toObject(util.thread._dogeiscutObjectBuilderIndex[util.thread._dogeiscutObjectBuilderIndex.length-1]) |
747 | 735 | } else { |
748 | | - throw 'This block must be inside of a "string builder" block.'; |
| 736 | + throw 'This block must be inside of a "object builder" block.'; |
749 | 737 | } |
750 | 738 | } |
751 | 739 |
|
752 | | - async builder({}, util) { |
| 740 | + builder() { |
753 | 741 | return 'noop' |
754 | 742 | } |
755 | 743 |
|
|
880 | 868 | return TWO; |
881 | 869 | } |
882 | 870 |
|
| 871 | + toString({OBJECT, FORMAT}) { |
| 872 | + OBJECT = dogeiscutObject.Type.toObject(OBJECT, false); |
| 873 | + |
| 874 | + return OBJECT.toString(FORMAT === "pretty") |
| 875 | + } |
| 876 | + |
883 | 877 | keys({ OBJECT }) { |
884 | 878 | OBJECT = dogeiscutObject.Type.toObject(OBJECT, false); |
885 | 879 |
|
|
0 commit comments