void ResolveVariable(ILExpression expr, ILExpression instance = null, ILExpression index = null) { Debug.Assert(expr != null); UnresolvedVar uv = expr.Operand as UnresolvedVar; Debug.Assert(uv != null); ILVariable v = null; if (uv.Extra != 0) { Debug.Assert(instance == null); instance = new ILExpression(GMCode.Constant, new ILValue(uv.Extra)); // create a fake instance value } instance = instance.MatchSingleArgument(); if (instance.Code == GMCode.Constant) { ILValue value = instance.Operand as ILValue; v = ILVariable.CreateVariable(uv.Name, (int)value, this.locals); } else if (instance.Code == GMCode.Var) { v = ILVariable.CreateVariable(uv.Name, 0, this.locals); (instance.Operand as ILVariable).Type = GM_Type.Instance; // make sure its an instance } else { throw new Exception("humm"); } if (uv.Operand >= 0) { Debug.Assert(index != null); index = index.MatchSingleArgument(); if (index.Code == GMCode.Var) { ILVariable ivar = index.Operand as ILVariable; // indexs can only be ints, but they can be negitive? ivar.Type = GM_Type.Int; } } else { index = null; } Debug.Assert(v != null); expr.Code = GMCode.Var; expr.Operand = v; expr.Arguments.Clear(); expr.Arguments.Add(instance); if (index != null) { expr.Arguments.Add(index); } }
// Changed the design on this, just emulated the dup by replacing dup and inserting the values needed for the two unresolved assigns, it SHOULD all resolve // though the pump void FixComplexPop(IList <ILNode> nodes, ILExpression var_expr, int start, UnresolvedVar uv) // uv is only used for debugging { UnresolvedVar popVar = null; // the pop var that we dupped for (int i = start; i < nodes.Count; i++) // need to find the matching pop, should be only a push up { if (nodes[i].Match(GMCode.Pop, out popVar)) { Debug.Assert(popVar.Name == uv.Name && uv.Operand == popVar.Operand && uv.Extra == popVar.Extra); // only thing we can compare ILExpression expr = nodes[i] as ILExpression; ILExpression assign = new ILExpression(GMCode.Assign, null, new ILExpression(var_expr)); assign.WithILRanges(expr); nodes[i] = assign; break; } } }
bool ComplexPopStack(IList <ILNode> nodes, ILExpression expr, int pos) { int dupType = 0; ILExpression instance; UnresolvedVar uv = null; // compiler warning if (nodes.ElementAtOrDefault(pos + 1).Match(GMCode.Dup, out dupType) && dupType == 0 && // stack var expr.Match(GMCode.Push, out instance) && nodes.ElementAtOrDefault(pos + 2).Match(GMCode.Push, out uv)) { expr = nodes[pos + 2] as ILExpression; Debug.Assert(expr.Operand is UnresolvedVar); expr.AddILRange(nodes[pos + 1]); // add the dup to the offsets nodes.RemoveRange(pos, 2); // dup and instance ResolveVariable(expr, instance); nodes[pos] = new ILExpression(GMCode.Push, null, expr); FixComplexPop(nodes, expr, pos + 1, uv); return(true); } return(false); }
// This is like assign add, ++, etc bool ComplexPopArray(IList <ILNode> nodes, ILExpression expr, int pos) { ILLabel l = nodes[0] as ILLabel; int dupType = 0; ILExpression instance = null; ILExpression index = null; UnresolvedVar uv = null; // compiler warning if (nodes.ElementAtOrDefault(pos + 2).Match(GMCode.Dup, out dupType) && dupType == 1 && // stack var expr.Match(GMCode.Push, out instance) && nodes.ElementAtOrDefault(pos + 1).Match(GMCode.Push, out index) && nodes.ElementAtOrDefault(pos + 3).Match(GMCode.Push, out uv)) { expr = nodes[pos + 3] as ILExpression; Debug.Assert(expr.Operand is UnresolvedVar); expr.AddILRange(nodes[pos + 2]); // add the dup to the offsets nodes.RemoveRange(pos, 3); ResolveVariable(expr, instance, index); // fix it this way so we keep all the ILRanges nodes[pos] = new ILExpression(GMCode.Push, null, expr); FixComplexPop(nodes, expr, pos + 1, uv); return(true); } return(false); }