public override void CaseADelegateInvokeExp(ADelegateInvokeExp node) { //Build a list of the possible methods AASourceFile currentFile = Util.GetAncestor <AASourceFile>(node); List <AMethodDecl> methods = new List <AMethodDecl>(); ANamedType type = (ANamedType)finalTrans.data.ExpTypes[node.GetReceiver()]; AMethodDecl delegateMethod = finalTrans.data.DelegateTypeLinks[type]; foreach (KeyValuePair <ADelegateExp, AMethodDecl> delegateCreationPair in finalTrans.data.DelegateCreationMethod) { if (TypeChecking.Assignable(delegateCreationPair.Key.GetType(), type)) { if (!methods.Contains(delegateCreationPair.Value)) { methods.Add(delegateCreationPair.Value); } } } MoveMethodDeclsOut mover; if (methods.Count == 0) { //Can only remove it if the return value is unused if (!(node.Parent() is AExpStm)) { finalTrans.errors.Add(new ErrorCollection.Error(node.GetToken(), currentFile, "No possible methods found for delegate invoke.")); throw new ParserException(node.GetToken(), "Delegates.OutADelegateInvokeExp"); } mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data); foreach (Node arg in node.GetArgs()) { arg.Apply(mover); } node.Parent().Parent().RemoveChild(node.Parent()); foreach (PStm stm in mover.NewStatements) { stm.Apply(this); } return; } if (methods.Count == 1) { ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList()); while (node.GetArgs().Count > 0) { invoke.GetArgs().Add(node.GetArgs()[0]); } //If we have a struct method, add the pointer from the delegate if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(methods[0]))) { AStructDecl targetStr = finalTrans.data.StructMethods.First(str => str.Value.Contains(methods[0])).Key; AMethodDecl getPointerDecl = GetPointerMethod(targetStr.GetDimention() != null); ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList() { node.GetReceiver() }); invoke.GetArgs().Add(getPointerInvoke); finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl; finalTrans.data.ExpTypes[getPointerInvoke] = getPointerDecl.GetReturnType(); } finalTrans.data.SimpleMethodLinks[invoke] = methods[0]; finalTrans.data.ExpTypes[invoke] = methods[0].GetReturnType(); node.ReplaceBy(invoke); return; } //Multiple methods. Make /* * <Methods moved out from reciever> * string delegate = GetMethodPart(<reciever>); * if (delegate == "...") * { * Foo(...); * } * else if (delegate == "...") * { * Bar(..., GetPointerPart(<reciever>); * } * else if(...) * ... * else * { * UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("[<file>:<line>]: No methods matched delegate.")); * int i = 1/0; * return; * } * */ AABlock block = new AABlock(new ArrayList(), new TRBrace("}")); mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data); node.GetReceiver().Apply(mover); AMethodDecl methodPartMethod = GetMethodMethod(); ASimpleInvokeExp methodPartInvoke = new ASimpleInvokeExp(new TIdentifier("GetMethodPart"), new ArrayList() { Util.MakeClone(node.GetReceiver(), finalTrans.data) }); finalTrans.data.SimpleMethodLinks[methodPartInvoke] = methodPartMethod; finalTrans.data.ExpTypes[methodPartInvoke] = methodPartMethod.GetReturnType(); AALocalDecl methodPartDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("string"), null), new TIdentifier("methodPart"), methodPartInvoke); block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), methodPartDecl)); //If the invoke's return value is used, get the lvalue PLvalue leftSide; if (node.Parent() is AALocalDecl) { leftSide = new ALocalLvalue(new TIdentifier("renameMe")); finalTrans.data.LocalLinks[(ALocalLvalue)leftSide] = (AALocalDecl)node.Parent(); finalTrans.data.LvalueTypes[leftSide] = new ANamedType(new TIdentifier("string"), null); PStm pStm = Util.GetAncestor <PStm>(node); AABlock pBlock = (AABlock)pStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + 1, new ABlockStm(new TLBrace("{"), block)); node.Parent().RemoveChild(node); } else if (node.Parent() is AAssignmentExp) { AAssignmentExp assignExp = (AAssignmentExp)node.Parent(); leftSide = assignExp.GetLvalue(); leftSide.Apply(mover); PStm pStm = Util.GetAncestor <PStm>(node); pStm.ReplaceBy(new ABlockStm(new TLBrace("{"), block)); } else if (node.Parent() is AExpStm) { //No assignments needed leftSide = null; node.Parent().ReplaceBy(new ABlockStm(new TLBrace("{"), block)); } else { //Create a new local AALocalDecl leftSideDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(delegateMethod.GetReturnType(), finalTrans.data), new TIdentifier("delegateVar"), null); ALocalLvalue leftSideLink = new ALocalLvalue(new TIdentifier("delegateVar")); ALvalueExp leftSideLinkExp = new ALvalueExp(leftSideLink); PStm pStm = Util.GetAncestor <PStm>(node); AABlock pBlock = (AABlock)pStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), new ABlockStm(new TLBrace("{"), block)); node.ReplaceBy(leftSideLinkExp); finalTrans.data.LocalLinks[leftSideLink] = leftSideDecl; finalTrans.data.LvalueTypes[leftSideLink] = finalTrans.data.ExpTypes[leftSideLinkExp] = leftSideDecl.GetType(); leftSide = leftSideLink; block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), leftSideDecl)); } ABlockStm elseBranch; //Make final else branch /* { * UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("<file>[<line>, <pos>]: No methods matched delegate.")); * IntToString(1/0); * return; * } */ { AABlock innerBlock = new AABlock(new ArrayList(), new TRBrace("}")); ASimpleInvokeExp playerGroupInvoke = new ASimpleInvokeExp(new TIdentifier("PlayerGroupAll"), new ArrayList()); AFieldLvalue messageAreaLink = new AFieldLvalue(new TIdentifier("c_messageAreaDebug")); ALvalueExp messageAreaLinkExp = new ALvalueExp(messageAreaLink); AStringConstExp stringConst = new AStringConstExp( new TStringLiteral("\"" + currentFile.GetName().Text.Replace('\\', '/') + "[" + node.GetToken().Line + ", " + node.GetToken().Pos + "]: Got a null delegate.\"")); ASimpleInvokeExp stringToTextInvoke = new ASimpleInvokeExp(new TIdentifier("StringToText"), new ArrayList() { stringConst }); ASimpleInvokeExp displayMessageInvoke = new ASimpleInvokeExp(new TIdentifier("UIDisplayMessage"), new ArrayList() { playerGroupInvoke, messageAreaLinkExp, stringToTextInvoke }); AIntConstExp intConst1 = new AIntConstExp(new TIntegerLiteral("1")); AIntConstExp intConst2 = new AIntConstExp(new TIntegerLiteral("0")); ABinopExp binop = new ABinopExp(intConst1, new ADivideBinop(new TDiv("/")), intConst2); ASimpleInvokeExp intToStringInvoke = new ASimpleInvokeExp(new TIdentifier("IntToString"), new ArrayList() { binop }); innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), displayMessageInvoke)); innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), intToStringInvoke)); //innerBlock.GetStatements().Add(new AVoidReturnStm(new TReturn("return"))); elseBranch = new ABlockStm(new TLBrace("{"), innerBlock); finalTrans.data.SimpleMethodLinks[playerGroupInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == playerGroupInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[stringToTextInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == stringToTextInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[displayMessageInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == displayMessageInvoke.GetName().Text); finalTrans.data.SimpleMethodLinks[intToStringInvoke] = finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == intToStringInvoke.GetName().Text); finalTrans.data.FieldLinks[messageAreaLink] = finalTrans.data.Libraries.Fields.First(m => m.GetName().Text == messageAreaLink.GetName().Text); finalTrans.data.ExpTypes[playerGroupInvoke] = finalTrans.data.SimpleMethodLinks[playerGroupInvoke].GetReturnType(); finalTrans.data.LvalueTypes[messageAreaLink] = finalTrans.data.ExpTypes[messageAreaLinkExp] = finalTrans.data.FieldLinks[messageAreaLink].GetType(); finalTrans.data.ExpTypes[stringToTextInvoke] = finalTrans.data.SimpleMethodLinks[stringToTextInvoke].GetReturnType(); finalTrans.data.ExpTypes[stringConst] = finalTrans.data.ExpTypes[intToStringInvoke] = new ANamedType(new TIdentifier("string"), null); finalTrans.data.ExpTypes[displayMessageInvoke] = new AVoidType(); finalTrans.data.ExpTypes[intConst1] = finalTrans.data.ExpTypes[intConst2] = finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("int"), null); } foreach (AMethodDecl method in methods) { /* * if (delegate == "...") * { * Foo(...); * } * else if (delegate == "...") * { * Bar(..., GetPointerPart(<reciever>); * } * else if(...) * ... */ AABlock innerBlock = new AABlock(new ArrayList(), new TRBrace("}")); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier(method.GetName().Text), new ArrayList()); for (int i = 0; i < node.GetArgs().Count; i++) { PExp arg = (PExp)node.GetArgs()[i]; invoke.GetArgs().Add(Util.MakeClone(arg, finalTrans.data)); } //If we have a struct method, add the pointer from the delegate if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(method))) { AStructDecl targetStr = finalTrans.data.StructMethods.First(str => str.Value.Contains(method)).Key; AMethodDecl getPointerDecl = GetPointerMethod(targetStr.GetDimention() != null); ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList() { Util.MakeClone(node.GetReceiver(), data) }); invoke.GetArgs().Add(getPointerInvoke); finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl; finalTrans.data.ExpTypes[getPointerInvoke] = getPointerDecl.GetReturnType(); } finalTrans.data.SimpleMethodLinks[invoke] = method; finalTrans.data.ExpTypes[invoke] = method.GetReturnType(); if (leftSide == null) { innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), invoke)); } else { AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), Util.MakeClone(leftSide, finalTrans.data), invoke); finalTrans.data.ExpTypes[assignment] = finalTrans.data.ExpTypes[invoke]; innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), assignment)); } ALocalLvalue methodPartLink = new ALocalLvalue(new TIdentifier("methodPart")); ALvalueExp methodPartLinkExp = new ALvalueExp(methodPartLink); AStringConstExp stringConst = new AStringConstExp(new TStringLiteral("\"" + GetName(method) + "\"")); finalTrans.data.LocalLinks[methodPartLink] = methodPartDecl; finalTrans.data.LvalueTypes[methodPartLink] = finalTrans.data.ExpTypes[methodPartLinkExp] = finalTrans.data.ExpTypes[stringConst] = new ANamedType(new TIdentifier("string"), null); ABinopExp binop = new ABinopExp(methodPartLinkExp, new AEqBinop(new TEq("==")), stringConst); finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("bool"), null); AIfThenElseStm ifThenElse = new AIfThenElseStm(new TLParen("("), binop, new ABlockStm(new TLBrace("{"), innerBlock), elseBranch); elseBranch = new ABlockStm(new TLBrace("{"), new AABlock(new ArrayList() { ifThenElse }, new TRBrace("}"))); } block.GetStatements().Add(elseBranch); }
private static void MakeCloneRefferences(PExp clone, PExp exp, SharedData data) { data.ExpTypes[clone] = data.ExpTypes[exp]; if (exp is AIntConstExp || exp is AHexConstExp || exp is AOctalConstExp || exp is AFixedConstExp || exp is AStringConstExp || exp is ACharConstExp || exp is ABooleanConstExp || exp is ANullExp) { //No more required } else if (exp is AIncDecExp) { AIncDecExp aExp = (AIncDecExp)exp; AIncDecExp aClone = (AIncDecExp)clone; MakeCloneRefferences(aClone.GetLvalue(), aExp.GetLvalue(), data); } else if (exp is ABinopExp) { ABinopExp aExp = (ABinopExp)exp; ABinopExp aClone = (ABinopExp)clone; MakeCloneRefferences(aClone.GetLeft(), aExp.GetLeft(), data); MakeCloneRefferences(aClone.GetRight(), aExp.GetRight(), data); } else if (exp is AUnopExp) { AUnopExp aExp = (AUnopExp)exp; AUnopExp aClone = (AUnopExp)clone; MakeCloneRefferences(aClone.GetExp(), aExp.GetExp(), data); } else if (exp is ASimpleInvokeExp) { ASimpleInvokeExp aExp = (ASimpleInvokeExp)exp; ASimpleInvokeExp aClone = (ASimpleInvokeExp)clone; data.SimpleMethodLinks[aClone] = data.SimpleMethodLinks[aExp]; for (int i = 0; i < aExp.GetArgs().Count; i++) { MakeCloneRefferences((PExp)aClone.GetArgs()[i], (PExp)aExp.GetArgs()[i], data); } } else if (exp is ANonstaticInvokeExp) { ANonstaticInvokeExp aExp = (ANonstaticInvokeExp)exp; ANonstaticInvokeExp aClone = (ANonstaticInvokeExp)clone; data.StructMethodLinks[aClone] = data.StructMethodLinks[aExp]; for (int i = 0; i < aExp.GetArgs().Count; i++) { MakeCloneRefferences((PExp)aClone.GetArgs()[i], (PExp)aExp.GetArgs()[i], data); } MakeCloneRefferences(aClone.GetReceiver(), aExp.GetReceiver(), data); } else if (exp is ALvalueExp) { ALvalueExp aExp = (ALvalueExp)exp; ALvalueExp aClone = (ALvalueExp)clone; MakeCloneRefferences(aClone.GetLvalue(), aExp.GetLvalue(), data); } else if (exp is AAssignmentExp) { AAssignmentExp aExp = (AAssignmentExp)exp; AAssignmentExp aClone = (AAssignmentExp)clone; MakeCloneRefferences(aClone.GetLvalue(), aExp.GetLvalue(), data); MakeCloneRefferences(aClone.GetExp(), aExp.GetExp(), data); } else if (exp is AParenExp) { AParenExp aExp = (AParenExp)exp; AParenExp aClone = (AParenExp)clone; MakeCloneRefferences(aClone.GetExp(), aExp.GetExp(), data); } else if (exp is AStringConstExp) { AStringConstExp aExp = (AStringConstExp)exp; AStringConstExp aClone = (AStringConstExp)clone; if (data.ObfuscatedStrings.ContainsKey(aExp)) { data.ObfuscatedStrings[aClone] = data.ObfuscatedStrings[aExp]; } if (data.StringsDontJoinRight.Contains(aExp)) { data.StringsDontJoinRight.Add(aClone); } } else if (exp is ANewExp) { ANewExp aExp = (ANewExp)exp; ANewExp aClone = (ANewExp)clone; if (data.ConstructorLinks.ContainsKey(aExp)) { data.ConstructorLinks[aClone] = data.ConstructorLinks[aExp]; } MakeCloneRefferences(aClone.GetType(), aExp.GetType(), data); for (int i = 0; i < aExp.GetArgs().Count; i++) { MakeCloneRefferences((PExp)aClone.GetArgs()[i], (PExp)aExp.GetArgs()[i], data); } } else if (exp is ACastExp) { ACastExp aExp = (ACastExp)exp; ACastExp aClone = (ACastExp)clone; MakeCloneRefferences(aClone.GetType(), aExp.GetType(), data); MakeCloneRefferences(aClone.GetExp(), aExp.GetExp(), data); } else if (exp is ADelegateExp) { ADelegateExp aExp = (ADelegateExp)exp; ADelegateExp aClone = (ADelegateExp)clone; if (data.DelegateCreationMethod.ContainsKey(aExp)) { data.DelegateCreationMethod[aClone] = data.DelegateCreationMethod[aExp]; } MakeCloneRefferences(aClone.GetType(), aExp.GetType(), data); MakeCloneRefferences(aClone.GetLvalue(), aExp.GetLvalue(), data); } else if (exp is ADelegateInvokeExp) { ADelegateInvokeExp aExp = (ADelegateInvokeExp)exp; ADelegateInvokeExp aClone = (ADelegateInvokeExp)clone; MakeCloneRefferences(aClone.GetReceiver(), aExp.GetReceiver(), data); for (int i = 0; i < aExp.GetArgs().Count; i++) { MakeCloneRefferences((PExp)aClone.GetArgs()[i], (PExp)aExp.GetArgs()[i], data); } } else if (exp is AIfExp) { AIfExp aExp = (AIfExp)exp; AIfExp aClone = (AIfExp)clone; MakeCloneRefferences(aClone.GetCond(), aExp.GetCond(), data); MakeCloneRefferences(aClone.GetThen(), aExp.GetThen(), data); MakeCloneRefferences(aClone.GetElse(), aExp.GetElse(), data); } else { throw new Exception("Unexpect exp. Got " + exp.GetType()); } }