ribrdb / desynced-tools

Tools for working with behaviors and blueprints from Desynced.
MIT License
4 stars 3 forks source link

TypeScript source outdated? #37

Closed bigbellyburger closed 6 months ago

bigbellyburger commented 6 months ago

I'd like to run this tool locally but am experiencing issues with the assembling. After some debugging and comparing against the web based editor it seems that the typescript files might be outdated?

For example the convertArg function is defined in assembler.ts but is never called anywhere, however in the app/bundle.out.js I am seeing it used in ways that will likely resolve my issue.

ribrdb commented 6 months ago

The source code in the repo is more up to date than the web app. There was some recent refactoring around convertArg. What's the issue you're seeing?

bigbellyburger commented 6 months ago

When I go to https://desynced-behavior-editor.web.app/ and compile the behavior:

export function foo(v:Value) {
    if (self.fullBattery()) {
        return;
    }
    const missing = v.solve();
    if (missing) {
        notify("no solution");
    } else {
        notify("solved");
    }
    let a:number;
    switch (missing?.type) {
        case "Item": {
            a = 1;
            break;
        }
        case "Entity": {
            a = 2;
            break;
        }
        case "Component": {
            a = 3;
            break;
        }
        default:
            a = 4;
    }
    for (const e of entitiesInRange(20, "v_construction")) {
        const l = self.getDistance(e);
    }
}

Things work as expected. This is the behavior string that I get:

DSCCx1TQNY00tMgl11WMD6u1DRGSw4YuZPY1Qixrm3g8NcW1IYqwI0MZcXg2jJszy3fDm110qjSHn4LuT8C4KsCVC2OlORy44ARys1h7P3T35MC8h0Cwnfw1ddHT63QrqVn2r7zag1Cd0Mp1jeGfQ1gX9vZ1EoL8k1UPO9y19dl5z4ceTZG0t3Mct13WjIf1SKCTj0X13Sw2jNm6U02LaBE0V6tIe3YwDkI46ovT11QeOTV4U2Gov48b3H50R7VyJ3VrAn73yapWv1BkHHG2VuiJM3CCAJ22BWIZQ0YIr7a2QusaE0nBSXC1QdiPf2v7YOg3Uz5G51x1xpN47d6qd2Ip5Q83h9GCC2FiwYP4IUjKy2vIWeR4bnCfH2zHWwT0R6Lcl

When I compile the same behavior locally, placed in test.ts using:

npm run build
node dist/js2ds.js test.ts
node dist/as.js test.ts.asm

I get this behavior string instead (from test.ts.asm.txt):

DSCDZ2e5gqW0tMgiz3czAmm1Zn5nQ1vbVRw1qDj39154KVm3QgGtm48VvIZ2dpNP60D7cVO0WAYRY1nLIMz3TgpgV24FFJR0E4xwH07qQx40pay2d1g63k90wZcg73I781Y3B15SF1wCuHB3o0NcC3C2sgk1VQzi00dP4R42jKCFc16gR0m41m2DJ0fRI4Q2sDayc0vGxNZ1kMZtX1C6aeP1AhRcZ4Bl1Qm3sHaKj49fOHV28aBoe00Z0Pk4GPPv21S7C751AyYei0D9ZML2GtkvX3zk09c3Fgs6500R8D11toW8u1PiEfi2x3dyE33ymfM1sdTUu2fx8MT362cbA2n4sN92S6YOA1DFgBg2otcXj3kQE7G3bMsmP3YWMQq2dTJUf1av

The game produces this error when loading the behavior:

[2024.02.13-20.48.47:343][659]Error: Critical error while executing Main/ui/Program.lua:873: attempt to index a nil value (local 'regsrc')
[2024.02.13-20.48.47:343][659]Error: stack traceback:
[2024.02.13-20.48.47:344][659]Error:    Main/ui/Program.lua:873: in upvalue 'BuildNode'
[2024.02.13-20.48.47:347][659]Error:    Main/ui/Program.lua:849: in upvalue 'BuildNode'
[2024.02.13-20.48.47:347][659]Error:    Main/ui/Program.lua:849: in upvalue 'BuildNode'
[2024.02.13-20.48.47:347][659]Error:    Main/ui/Program.lua:849: in upvalue 'BuildNode'
[2024.02.13-20.48.47:347][659]Error:    Main/ui/Program.lua:849: in upvalue 'BuildNode'
[2024.02.13-20.48.47:348][659]Error:    Main/ui/Program.lua:849: in upvalue 'BuildNode'
[2024.02.13-20.48.47:348][659]Error:    Main/ui/Program.lua:849: in local 'BuildNode'
[2024.02.13-20.48.47:348][659]Error:    Main/ui/Program.lua:938: in upvalue 'OldRefresh'
[2024.02.13-20.48.47:349][659]Error:    BehaviorVariablesDebug/Program.lua:87: in method 'Refresh'
[2024.02.13-20.48.47:349][659]Error:    Main/ui/Program.lua:486: in upvalue 'do_load'
[2024.02.13-20.48.47:349][659]Error:    Main/ui/Program.lua:493: in upvalue 'on_ok'
[2024.02.13-20.48.47:350][659]Error:    Main/ui/utilities.lua:4: in function <Main/ui/utilities.lua:4>

When comparing the behaviors in https://stagegames.github.io/DesyncedJavaScriptUtils/ I see these differences:

diff --git a/compare.txt b/compare.txt
index 68aed41..d5c33f8 100644
--- a/compare.txt
+++ b/compare.txt
@@ -32,6 +32,7 @@
         "0": {
             "num": 1
         },
+        "1": 0,
         "op": "set_reg",
         "next": 10
     },
@@ -39,6 +40,7 @@
         "0": {
             "num": 2
         },
+        "1": 0,
         "op": "set_reg",
         "next": 10
     },
@@ -46,6 +48,7 @@
         "0": {
             "num": 3
         },
+        "1": 0,
         "op": "set_reg",
         "next": 10
     },
@@ -53,6 +56,7 @@
         "0": {
             "num": 4
         },
+        "1": 0,
         "op": "set_reg"
     },
     "9": {
@@ -62,12 +66,15 @@
         "1": {
             "id": "v_construction"
         },
-        "4": "A",
+        "2": 0,
+        "3": 0,
+        "4": "B",
         "5": false,
         "op": "for_entities_in_range"
     },
     "10": {
-        "0": "A",
+        "0": "B",
+        "1": 0,
         "op": "get_distance",
         "next": false
     },
bigbellyburger commented 6 months ago

The files that were generated: test-ts.zip

bigbellyburger commented 6 months ago

After comparing with https://desynced-behavior-editor.web.app/bundle.out.js and https://desynced-behavior-editor.web.app/compiler.js I do believe the files in this repository are different. The compile.js is minified so this isn't complete, but I've seen these changes which do help with the nil handling:

diff --git a/decompile/disasm.ts b/decompile/disasm.ts
index 117043c..f56b86d 100644
--- a/decompile/disasm.ts
+++ b/decompile/disasm.ts
@@ -46,7 +46,8 @@ export class Disassembler {

   code() {
     if (this.output.length == 0) {
-      this.output = generateAsm(this.program);
+      buildLabels(this.program);
+      this.program.apply(RenderAssembly(this.output));
     }
     return this.output.join("\n");
   }
@@ -373,11 +374,4 @@ function buildLabels(prog: Program) {
       inst.labels.push(labels.get(i)!);
     }
   });
-}
-
-export function generateAsm(prog: Program): string[] {
-  buildLabels(prog);
-  const output: string[] = [];
-  prog.apply(RenderAssembly(output));
-  return output;
 }
\ No newline at end of file
diff --git a/ir/instruction.ts b/ir/instruction.ts
index 85eaad3..0cb1aa6 100644
--- a/ir/instruction.ts
+++ b/ir/instruction.ts
@@ -31,20 +31,19 @@ export class NodeRef {
 }

 const regNums = {
-  nil: 0,
   goto: -1,
   store: -2,
   visual: -3,
   signal: -4,
 };
-const regNames = ["nil", "goto", "store", "visual", "signal"];
+const regNames = [, "goto", "store", "visual", "signal"];

 export class RegRef {
   readonly type = "regRef";

   constructor(readonly reg: number | string) {
     if (typeof reg === "number") {
-      if (reg < -4) {
+      if (reg == 0 || reg < -4) {
         throw new Error(`Invalid register: ${reg}`);
       }
     } else {
@@ -57,7 +56,7 @@ export class RegRef {
   name(): string {
     if (typeof this.reg == "string") {
       return this.reg;
-    } else if (this.reg <= 0) {
+    } else if (this.reg < 0) {
       return regNames[-this.reg]!;
     } else {
       return `p${this.reg}`;

This seems related to a recent commit, but I'm a bit lost 😅

ribrdb commented 6 months ago

Can you see if that fixes your issue?

bigbellyburger commented 6 months ago

It does, thank you!

I am still noticing a difference with https://desynced-behavior-editor.web.app/ where the hosted version re-uses the A variable instead of introducing a second B variable.

@@ -62,12 +62,12 @@
         "1": {
             "id": "v_construction"
         },
-        "4": "A",
+        "4": "B",
         "5": false,
         "op": "for_entities_in_range"
     },
     "10": {
-        "0": "A",
+        "0": "B",
         "op": "get_distance",
         "next": false
     },
ribrdb commented 6 months ago

Yes there was a bug where it was re-using variables too aggressively. The register allocater could be improved, but the current version is safer.