11using System ;
2+ using System . Collections . Generic ;
23using Underanalyzer ;
34using Underanalyzer . Compiler ;
45using Underanalyzer . Compiler . Bytecode ;
@@ -16,9 +17,34 @@ internal class CodeBuilder : ICodeBuilder
1617 // Data being used with this code builder.
1718 private readonly GlobalDecompileContext _globalContext ;
1819
20+ // Lookups for variables and functions.
21+ private readonly Dictionary < ( UndertaleString , UndertaleInstruction . InstanceType ) , UndertaleVariable > _variableLookup ;
22+ private readonly Dictionary < string , UndertaleFunction > _functionLookup ;
23+
1924 public CodeBuilder ( GlobalDecompileContext globalContext )
2025 {
2126 _globalContext = globalContext ;
27+
28+ // Make variable and function lookups (to not rely on O(n) searches)
29+ IList < UndertaleVariable > variables = _globalContext . Data . Variables ;
30+ _variableLookup = new ( variables . Count ) ;
31+ foreach ( UndertaleVariable v in variables )
32+ {
33+ if ( v is null )
34+ {
35+ continue ;
36+ }
37+ _variableLookup . TryAdd ( ( v . Name , v . InstanceType ) , v ) ;
38+ }
39+ IList < UndertaleFunction > functions = _globalContext . Data . Functions ;
40+ _functionLookup = new ( functions . Count ) ;
41+ foreach ( UndertaleFunction f in functions )
42+ {
43+ if ( f ? . Name ? . Content is string name )
44+ {
45+ _functionLookup . TryAdd ( name , f ) ;
46+ }
47+ }
2248 }
2349
2450 /// <summary>
@@ -262,8 +288,18 @@ public void PatchInstruction(IGMInstruction instruction, string variableName, In
262288 // Register/define non-local variable, and update variable on instruction immediately
263289 _globalContext . CurrentCompileGroup . RegisterNonLocalVariable ( variableName ) ;
264290 UndertaleString nameString = _globalContext . CurrentCompileGroup . MakeString ( variableName , out int nameStringId ) ;
265- utInstruction . ValueVariable = _globalContext . Data . Variables . EnsureDefined (
266- nameString , nameStringId , ( UndertaleInstruction . InstanceType ) variableInstanceType , isBuiltin , _globalContext . Data ) ;
291+ UndertaleInstruction . InstanceType actualInstType =
292+ _globalContext . Data . Variables . CalculateInstType ( ( UndertaleInstruction . InstanceType ) variableInstanceType , isBuiltin , _globalContext . Data ) ;
293+ if ( _variableLookup . TryGetValue ( ( nameString , actualInstType ) , out UndertaleVariable existingVariable ) )
294+ {
295+ utInstruction . ValueVariable = existingVariable ;
296+ }
297+ else
298+ {
299+ UndertaleVariable newVariable = _globalContext . Data . Variables . Define ( nameString , nameStringId , actualInstType , isBuiltin , _globalContext . Data ) ;
300+ _variableLookup . Add ( ( nameString , actualInstType ) , newVariable ) ;
301+ utInstruction . ValueVariable = newVariable ;
302+ }
267303 }
268304
269305 // Update other parts of instruction
@@ -288,15 +324,31 @@ public void PatchInstruction(IGMInstruction instruction, FunctionScope scope, st
288324 }
289325 else if ( _globalContext . Builtins . LookupBuiltinFunction ( functionName ) is not null )
290326 {
291- reference = _globalContext . Data . Functions . EnsureDefined ( functionName , _globalContext . Data . Strings ) ;
327+ if ( _functionLookup . TryGetValue ( functionName , out UndertaleFunction existingFunction ) )
328+ {
329+ reference = existingFunction ;
330+ }
331+ else
332+ {
333+ reference = _globalContext . Data . Functions . Define ( functionName , _globalContext . Data . Strings ) ;
334+ _functionLookup . Add ( functionName , reference ) ;
335+ }
292336 }
293337 else if ( _globalContext . GlobalFunctions . TryGetFunction ( functionName , out IGMFunction function ) )
294338 {
295339 reference = ( UndertaleFunction ) function ;
296340 }
297341 else if ( _globalContext . GetScriptId ( functionName , out int _ ) )
298342 {
299- reference = _globalContext . Data . Functions . EnsureDefined ( functionName , _globalContext . Data . Strings ) ;
343+ if ( _functionLookup . TryGetValue ( functionName , out UndertaleFunction existingFunction ) )
344+ {
345+ reference = existingFunction ;
346+ }
347+ else
348+ {
349+ reference = _globalContext . Data . Functions . Define ( functionName , _globalContext . Data . Strings ) ;
350+ _functionLookup . Add ( functionName , reference ) ;
351+ }
300352 }
301353 else
302354 {
0 commit comments