public override void CaseAMethodDecl(AMethodDecl node) { if (node.GetInline() == null) { return; } //Variables marked as out can be made into ref foreach (AALocalDecl formal in node.GetFormals()) { if (formal.GetOut() != null) { formal.SetRef(new TRef("ref")); formal.SetOut(null); } } assignedToLocals.Clear(); base.CaseAMethodDecl(node); foreach (AALocalDecl formal in node.GetFormals()) { if (!assignedToLocals.Contains(formal)) { formal.SetRef(new TRef("ref")); } } }
public override void CaseAMethodDecl(AMethodDecl node) { Write("\n"); if (node.GetStatic() != null) { Write("static "); } if (node.GetNative() != null) { Write("native "); } node.GetReturnType().Apply(this); Write(" " + node.GetName().Text + "("); bool first = true; foreach (AALocalDecl formal in node.GetFormals()) { if (!first) { Write(", "); } formal.Apply(this); first = false; } if (node.GetBlock() != null) { Write(")\n"); node.GetBlock().Apply(this); } else { Write(");\n\n"); } }
public override void CaseALocalLvalue(ALocalLvalue node) { if (Util.HasAncestor <AMethodDecl>(node) && //Is in a method data.LocalLinks[node].Parent() == Util.GetAncestor <AMethodDecl>(node)) //Is a link to a formal in that method { if (Util.HasAncestor <AAssignmentExp>(node) && //Is in an assignement Util.IsAncestor(node, Util.GetAncestor <AAssignmentExp>(node).GetLvalue())) //Is left side of the assignment { AssignedFormals.Add(data.LocalLinks[node]); } else if (Util.HasAncestor <ASimpleInvokeExp>(node)) { ASimpleInvokeExp invoke = Util.GetAncestor <ASimpleInvokeExp>(node); AMethodDecl method = data.SimpleMethodLinks[invoke]; for (int i = 0; i < invoke.GetArgs().Count; i++) { AALocalDecl formal = (AALocalDecl)method.GetFormals()[i]; if ((formal.GetRef() != null || formal.GetOut() != null) && Util.IsAncestor(node, (Node)invoke.GetArgs()[i])) { AssignedFormals.Add(data.LocalLinks[node]); return; } } } } }
public override void CaseASimpleInvokeExp(ASimpleInvokeExp node) { AMethodDecl target = data.SimpleMethodLinks[node]; for (int i = 0; i < node.GetArgs().Count; i++) { PExp arg = (PExp)node.GetArgs()[i]; currentLocal = null; arg.Apply(this); if (currentLocal != null && target.GetFormals().Cast <AALocalDecl>().ToList()[i].GetRef() != null) { ALocalLvalue local = currentLocal; target.Apply(this); if (target.GetFormals().Cast <AALocalDecl>().ToList()[i].GetRef() != null) { AALocalDecl decl = data.LocalLinks[local]; NeededRefs[Util.GetAncestor <AMethodDecl>(node)].Add(decl); } } } }
public override void CaseAMethodDecl(AMethodDecl node) { if (node.GetNative() == null && node.GetBlock() == null) { return; } if (node.GetStatic() != null) { return; } string inputStr = "native " + TypeToString(node.GetReturnType()) + " " + node.GetName().Text + "("; bool first = true; foreach (AALocalDecl formal in node.GetFormals()) { if (!first) { inputStr += ", "; } inputStr += TypeToString(formal.GetType()) + " " + formal.GetName().Text; first = false; } inputStr += ");"; writer.WriteLine(inputStr); AStructDecl str = Util.GetAncestor <AStructDecl>(node); List <AMethodDecl> methodList; if (str != null) { methodList = StructMethods[str]; } else { methodList = Methods; } string sig = Util.GetMethodSignature(node); if (methodList.Any(otherMethod => Util.GetMethodSignature(otherMethod) == sig)) { return; } methodList.Add(node); node.SetBlock(null); node.Parent().RemoveChild(node); }
public override void CaseAOperatorDecl(AOperatorDecl node) { AMethodDecl replacer = new AMethodDecl(node.GetVisibilityModifier(), null, node.GetStatic(), null, null, null, node.GetReturnType(), new TIdentifier(""), new ArrayList(), node.GetBlock()); while (node.GetFormals().Count > 0) { replacer.GetFormals().Add(node.GetFormals()[0]); } node.ReplaceBy(replacer); replacer.Apply(this); }
public static string ToString(AMethodDecl methodDecl) { string str = TypeToString(methodDecl.GetReturnType()) + " " + methodDecl.GetName().Text + "("; foreach (AALocalDecl formal in methodDecl.GetFormals()) { if (str.EndsWith("(")) { str += TypeToString(formal.GetType()) + " " + formal.GetName().Text; } else { str += ", " + TypeToString(formal.GetType()) + " " + formal.GetName().Text; } } str += ")"; return(str); }
/// <summary> /// Crawls the StarCraft 2 MPQs to grab the *.galaxy files inside. These files are parsed for (native) functions and constants. /// </summary> /// <returns>The functions and constants of StarCraft 2 in form of a LibraryData</returns> LibraryData loadLibraries() { // parse the files for functions and constants CrawlAndParseMpqs(); // convert the functions and constants to a LibraryData format LibraryData lib = new LibraryData(); // create the methods with from crawled info foreach (ParsedFunction function in functions) { AMethodDecl method = new AMethodDecl(); if (function.IsNative) { method.SetNative(new TNative("native")); } method.SetName(new TIdentifier(function.Name)); method.SetReturnType(new ANamedType(new TIdentifier(function.ReturnType), null)); // add function parameter foreach (var parameter in function.Parameters) { method.GetFormals().Add(new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier(parameter.Item1), null), new TIdentifier(parameter.Item2), null)); } lib.Methods.Add(method); } // create the constants from the crawled info foreach (ParsedConstant constant in constants) { AFieldDecl field = new AFieldDecl(new APublicVisibilityModifier(), null, new TConst("const"), new ANamedType(new TIdentifier(constant.Type), null), new TIdentifier(constant.Name), new AStringConstExp(new TStringLiteral(constant.Value))); lib.Fields.Add(field); } functions.Clear(); constants.Clear(); return(lib); }
public static string GetMethodSignature(AMethodDecl method) { StringBuilder str = new StringBuilder(method.GetName().Text); str.Append("("); bool first = true; foreach (AALocalDecl localDecl in method.GetFormals()) { if (!first) { str.Append(","); } str.Append(Util.TypeToStringBuilder(localDecl.GetType())); first = false; } str.Append(")"); return(str.ToString()); }
public override void CaseAMethodDecl(AMethodDecl node) { if (parsedMethods.Contains(node) || methodChain.Contains(node)) { return; } methodChain.Add(node); NeededRefs.Add(node, new List <AALocalDecl>()); base.CaseAMethodDecl(node); methodChain.Remove(node); parsedMethods.Add(node); foreach (AALocalDecl formal in node.GetFormals()) { if (formal.GetRef() != null && !NeededRefs[node].Contains(formal) && !Util.IsBulkCopy(formal.GetType())) { formal.SetRef(null); } } }
public override void CaseAMethodDecl(AMethodDecl node) { if (node.GetName().Text == "InitMap" && node.GetFormals().Count == 0) { if (finalTrans.multipleMainEntries) { multipleEntryCandidates.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor <AASourceFile>(node.GetName()), "Candidate")); } else if (finalTrans.mainEntry != null) { multipleEntryCandidates.Add(new ErrorCollection.Error(finalTrans.mainEntry.GetName(), Util.GetAncestor <AASourceFile>(finalTrans.mainEntry.GetName()), "Candidate")); multipleEntryCandidates.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor <AASourceFile>(node.GetName()), "Candidate")); //finalTrans.errors.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor<AASourceFile>(node), "Found multiple candidates for a main entry", true)); finalTrans.multipleMainEntries = true; finalTrans.mainEntry = null; } else { finalTrans.mainEntry = node; } } base.CaseAMethodDecl(node); }
public MethodDescription(AConstructorDecl method, string type) { Parser parser = new Parser(method); Start = parser.Start; End = parser.End; ReturnType = type; Name = parser.Name; Formals = parser.Formals; Locals = parser.Locals; if (method.Parent() != null) { method.Parent().RemoveChild(method); } Decl = new AMethodDecl(new APublicVisibilityModifier(), null, null, null, null, null, new ANamedType(new TIdentifier(type), null), new TIdentifier(""), new ArrayList(), method.GetBlock()); while (method.GetFormals().Count > 0) { Decl.GetFormals().Add(method.GetFormals()[0]); } Visibility = method.GetVisibilityModifier(); Position = TextPoint.FromCompilerCoords(method.GetName()); }
/* * Apply before Transform method decls, and remove dead code * * Convert properties to methods */ public static void Parse(FinalTransformations finalTrans) { OldEnrichmentParents.Clear(); OldStructParents.Clear(); SharedData data = finalTrans.data; foreach (APropertyDecl property in data.Properties.Select(p => p.Decl)) { AASourceFile parent = (AASourceFile)property.Parent(); if (property.GetGetter() != null) { AMethodDecl getter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier("Get" + property.GetName().Text, property.GetName().Line, 0), new ArrayList(), property.GetGetter()); data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(parent, getter)); parent.GetDecl().Insert(parent.GetDecl().IndexOf(property), getter); data.Getters[property] = getter; } if (property.GetSetter() != null) { AALocalDecl valueLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier("value"), null); AMethodDecl setter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, new AVoidType(new TVoid("void")), new TIdentifier("Set" + property.GetName().Text, property.GetName().Line, 0), new ArrayList() { valueLocal }, property.GetSetter()); data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(parent, setter)); parent.GetDecl().Insert(parent.GetDecl().IndexOf(property), setter); setter.GetBlock().Apply(new FixValue(valueLocal, data)); data.Setters[property] = setter; } property.Parent().RemoveChild(property); } foreach (AStructDecl structDecl in data.Structs.Select(s => s.Decl)) { foreach (APropertyDecl property in data.StructProperties[structDecl]) { //Due to enheritance, they might not be in same struct if (structDecl != Util.GetAncestor <AStructDecl>(property)) { continue; } OldStructParents[property] = structDecl; if (property.GetGetter() != null) { AALocalDecl indexLocal = null; string methodName = "Get" + property.GetName().Text; if (property.GetName().Text == "") { methodName = "GetThis"; indexLocal = data.ArrayPropertyLocals[property][0]; } AMethodDecl getter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier(methodName, property.GetName().Line, 0), new ArrayList(), property.GetGetter()); if (indexLocal != null) { indexLocal.Parent().Parent().RemoveChild(indexLocal.Parent()); //data.Locals[(AABlock) getter.GetBlock()].Remove(indexLocal); getter.GetFormals().Insert(0, indexLocal); } data.StructMethods[structDecl].Add(getter); structDecl.GetLocals().Insert(structDecl.GetLocals().IndexOf(property.Parent()), new ADeclLocalDecl(getter)); data.Getters[property] = getter; } if (property.GetSetter() != null) { AALocalDecl indexLocal = null; string methodName = "Set" + property.GetName().Text; if (property.GetName().Text == "") { methodName = "SetThis"; indexLocal = data.ArrayPropertyLocals[property][data.ArrayPropertyLocals[property].Length - 1]; } AALocalDecl valueLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier("value"), null); AMethodDecl setter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, new AVoidType(new TVoid("void")), new TIdentifier(methodName, property.GetName().Line, 0), new ArrayList() { valueLocal }, property.GetSetter()); if (indexLocal != null) { indexLocal.Parent().Parent().RemoveChild(indexLocal.Parent()); //data.Locals[(AABlock)setter.GetBlock()].Remove(indexLocal); setter.GetFormals().Insert(0, indexLocal); } data.StructMethods[structDecl].Add(setter); structDecl.GetLocals().Insert(structDecl.GetLocals().IndexOf(property.Parent()), new ADeclLocalDecl(setter)); setter.GetBlock().Apply(new FixValue(valueLocal, data)); data.Setters[property] = setter; } structDecl.RemoveChild(property.Parent()); } } foreach (AEnrichmentDecl enrichment in data.Enrichments) { for (int i = 0; i < enrichment.GetDecl().Count; i++) { if (!(enrichment.GetDecl()[i] is APropertyDecl)) { continue; } APropertyDecl property = (APropertyDecl)enrichment.GetDecl()[i]; OldEnrichmentParents[property] = enrichment; if (property.GetGetter() != null) { AALocalDecl indexLocal = null; string methodName = "Get" + property.GetName().Text; if (property.GetName().Text == "") { methodName = "GetThis"; indexLocal = data.ArrayPropertyLocals[property][0]; } AMethodDecl getter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier(methodName, property.GetName().Line, 0), new ArrayList(), property.GetGetter()); if (indexLocal != null) { indexLocal.Parent().Parent().RemoveChild(indexLocal.Parent()); //data.Locals[(AABlock)getter.GetBlock()].Remove(indexLocal); getter.GetFormals().Insert(0, indexLocal); } enrichment.GetDecl().Insert(enrichment.GetDecl().IndexOf(property), getter); data.Getters[property] = getter; } if (property.GetSetter() != null) { AALocalDecl indexLocal = null; string methodName = "Set" + property.GetName().Text; if (property.GetName().Text == "") { methodName = "SetThis"; indexLocal = data.ArrayPropertyLocals[property][data.ArrayPropertyLocals[property].Length - 1]; } AALocalDecl valueLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(property.GetType(), data), new TIdentifier("value"), null); AMethodDecl setter = new AMethodDecl(new APublicVisibilityModifier(), null, property.GetStatic() == null ? null : (TStatic)property.GetStatic().Clone(), null, null, null, new AVoidType(new TVoid("void")), new TIdentifier(methodName, property.GetName().Line, 0), new ArrayList() { valueLocal }, property.GetSetter()); if (indexLocal != null) { indexLocal.Parent().Parent().RemoveChild(indexLocal.Parent()); data.Locals[(AABlock)setter.GetBlock()].Remove(indexLocal); setter.GetFormals().Insert(0, indexLocal); } enrichment.GetDecl().Insert(enrichment.GetDecl().IndexOf(property), setter); setter.GetBlock().Apply(new FixValue(valueLocal, data)); data.Setters[property] = setter; } enrichment.RemoveChild(property); } } }
/*private class IsThisOnLeftSide : DepthFirstAdapter * { * private PType type; * private SharedData data; * public bool IsAssignedTo; * private List<AMethodDecl> investigatedMethods = new List<AMethodDecl>(); * * public IsThisOnLeftSide(PType type, SharedData data) * { * this.type = type; * this.data = data; * } * * //Check assignments, method invocations and nonstatic method invocations. * * public override void CaseAMethodDecl(AMethodDecl node) * { * investigatedMethods.Add(node); * } * * public override void CaseAThisLvalue(AThisLvalue node) * { * if (IsAssignedTo) * return; * * Node iParent = GetClosestNodeOfType(node, typeof (AAssignmentExp), * typeof (ASimpleInvokeExp), * typeof (ANonstaticInvokeExp), * typeof (AAsyncInvokeStm), * typeof (ASyncInvokeExp), * typeof(AArrayLvalue), * typeof(APointerLvalue), * typeof(APropertyLvalue), * typeof(AStructLvalue)); * if (iParent == null) * return; * * if (iParent is AAssignmentExp) * { * AAssignmentExp aParent = (AAssignmentExp) iParent; * if (Util.IsAncestor(node, aParent.GetLvalue())) * { * IsAssignedTo = true; * } * return; * } * if (iParent is ASimpleInvokeExp) * { * ASimpleInvokeExp aParent = (ASimpleInvokeExp) iParent; * AMethodDecl method = data.SimpleMethodLinks[aParent]; * if (investigatedMethods.Contains(method)) * return; * * if (Util.IsAncestor(node, aParent.GetLvalue())) * { * IsAssignedTo = true; * } * return; * } * } * * private Node GetClosestNodeOfType(Node node, params Type[] types) * { * if (node == null) * return null; * if (types.Contains(node.GetType())) * return node; * return GetClosestNodeOfType(node.Parent(), types); * } * }*/ public override void CaseADeconstructorDecl(ADeconstructorDecl node) { AStructDecl str = Util.GetAncestor <AStructDecl>(node); AEnrichmentDecl enrichment = Util.GetAncestor <AEnrichmentDecl>(node); AMethodDecl replacer = new AMethodDecl(new APublicVisibilityModifier(), null, null, null, null, null, new AVoidType(new TVoid("void")), node.GetName(), new ArrayList(), node.GetBlock()); replacer.GetName().Text += "_Deconstructor"; //Move the method outside the struct AASourceFile file = Util.GetAncestor <AASourceFile>(node); if (str != null) { str.RemoveChild(node.Parent()); } /*else * enrichment.RemoveChild(node);*/ int i = file.GetDecl().IndexOf(str ?? (PDecl)enrichment); file.GetDecl().Insert(i /* + 1*/, replacer); //Add the struct as a parameter PType type; if (str != null) { ANamedType structType = new ANamedType(new TIdentifier(str.GetName().Text), null); finalTrans.data.StructTypeLinks[structType] = str; type = structType; } else { type = Util.MakeClone(enrichment.GetType(), finalTrans.data); } finalTrans.data.DeconstructorMap[node] = replacer; AALocalDecl structFormal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new APointerType(new TStar("*"), type), new TIdentifier("currentStruct", replacer.GetName().Line, replacer.GetName().Pos), null); replacer.GetFormals().Add(structFormal); finalTrans.data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(file, replacer)); //Call base deconstructor before each return if (str != null && str.GetBase() != null) { AStructDecl baseStruct = data.StructTypeLinks[(ANamedType)str.GetBase()]; if (data.StructDeconstructor.ContainsKey(baseStruct)) { baseStruct.Apply(this); replacer.Apply(new CallDeconstructors(baseStruct, structFormal, data)); /*AMethodDecl baseDeconstructor = data.DeconstructorMap[data.StructDeconstructor[baseStruct]]; * * * ALocalLvalue structFormalRef = new ALocalLvalue(new TIdentifier("currentStruct")); * ALvalueExp structFormalRefExp = new ALvalueExp(structFormalRef); * ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("baseDeconstructor"), * new ArrayList() {structFormalRefExp}); * AABlock block = (AABlock) replacer.GetBlock(); * block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), invoke)); * * data.LocalLinks[structFormalRef] = structFormal; * data.SimpleMethodLinks[invoke] = baseDeconstructor; * data.LvalueTypes[structFormalRef] = data.ExpTypes[structFormalRefExp] = structFormal.GetType(); * data.ExpTypes[invoke] = baseDeconstructor.GetReturnType();*/ } } this.structFormal = structFormal; base.CaseAMethodDecl(replacer); }
public static List <AABlock> Inline(ASimpleInvokeExp node, FinalTransformations finalTrans) { /*if (Util.GetAncestor<AMethodDecl>(node) != null && Util.GetAncestor<AMethodDecl>(node).GetName().Text == "UIChatFrame_LeaveChannel") * node = node;*/ SharedData data = finalTrans.data; //If this node is inside the condition of a while, replace it with a new local var, //make a clone before the while, one before each continue in the while, and one at the end of the while //(unless the end is a return or break) AABlock pBlock; if (Util.HasAncestor <AWhileStm>(node)) { AWhileStm whileStm = Util.GetAncestor <AWhileStm>(node); if (Util.IsAncestor(node, whileStm.GetCondition())) { List <ASimpleInvokeExp> toInline = new List <ASimpleInvokeExp>(); //Above while AALocalDecl replaceVarDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(data.ExpTypes[node], data), new TIdentifier("whileVar"), null); ALocalLvalue replaceVarRef = new ALocalLvalue(new TIdentifier("whileVar")); ALvalueExp replaceVarRefExp = new ALvalueExp(replaceVarRef); data.LocalLinks[replaceVarRef] = replaceVarDecl; data.ExpTypes[replaceVarRefExp] = data.LvalueTypes[replaceVarRef] = replaceVarDecl.GetType(); node.ReplaceBy(replaceVarRefExp); replaceVarDecl.SetInit(node); pBlock = (AABlock)whileStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(whileStm), new ALocalDeclStm(new TSemicolon(";"), replaceVarDecl)); toInline.Add(node); //In the end of the while PStm lastStm = whileStm.GetBody(); while (lastStm is ABlockStm) { AABlock block = (AABlock)((ABlockStm)lastStm).GetBlock(); if (block.GetStatements().Count == 0) { lastStm = null; break; } lastStm = (PStm)block.GetStatements()[block.GetStatements().Count - 1]; } if (lastStm == null || !(lastStm is AValueReturnStm || lastStm is AVoidReturnStm || lastStm is ABreakStm)) { lastStm = whileStm.GetBody(); AABlock block; if (lastStm is ABlockStm) { block = (AABlock)((ABlockStm)lastStm).GetBlock(); } else { block = new AABlock(new ArrayList(), new TRBrace("}")); block.GetStatements().Add(lastStm); whileStm.SetBody(new ABlockStm(new TLBrace("{"), block)); } replaceVarRef = new ALocalLvalue(new TIdentifier("whileVar")); ASimpleInvokeExp clone = (ASimpleInvokeExp)Util.MakeClone(node, data); toInline.Add(clone); AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), replaceVarRef, clone); data.LocalLinks[replaceVarRef] = replaceVarDecl; data.ExpTypes[assignment] = data.LvalueTypes[replaceVarRef] = replaceVarDecl.GetType(); block.GetStatements().Add(new AExpStm(new TSemicolon(";"), assignment)); } //After each continue CloneBeforeContinue cloner = new CloneBeforeContinue(node, replaceVarDecl, data); whileStm.GetBody().Apply(cloner); toInline.AddRange(cloner.replacementExpressions); List <AABlock> visitBlocks = new List <AABlock>(); foreach (ASimpleInvokeExp invoke in toInline) { visitBlocks.AddRange(Inline(invoke, finalTrans)); } return(visitBlocks); } } AMethodDecl decl = finalTrans.data.SimpleMethodLinks[node]; FindAssignedToFormals assignedToFormalsFinder = new FindAssignedToFormals(finalTrans.data); decl.Apply(assignedToFormalsFinder); List <AALocalDecl> assignedToFormals = assignedToFormalsFinder.AssignedFormals; /* * inline int foo(int a) * { * int b = 2; * int c; * ... * while(...) * { * ... * break; * ... * return c; * } * ... * return 2; * } * * bar(foo(<arg for a>)); * -> * * { * bool inlineMethodReturned = false; * int inlineReturner; * int a = <arg for a>; * while (!inlineMethodReturned) * { * int b = 2; * int c; * ... * while(...) * { * ... * break * ... * inlineReturner = c; * inlineMethodReturned = true; * break; * } * if (inlineMethodReturned) * { * break; * } * ... * inlineReturner = 2; * inlineMethodReturned = true; * break; * break; * } * bar(inlineReturner); * } * * */ AABlock outerBlock = new AABlock(); PExp exp = new ABooleanConstExp(new AFalseBool()); finalTrans.data.ExpTypes[exp] = new ANamedType(new TIdentifier("bool"), null); AALocalDecl hasMethodReturnedVar = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("bool"), null), new TIdentifier("hasInlineReturned"), exp); finalTrans.data.GeneratedVariables.Add(hasMethodReturnedVar); PStm stm = new ALocalDeclStm(new TSemicolon(";"), hasMethodReturnedVar); outerBlock.GetStatements().Add(stm); AALocalDecl methodReturnerVar = null; if (!(decl.GetReturnType() is AVoidType)) { methodReturnerVar = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(decl.GetReturnType(), finalTrans.data), new TIdentifier("inlineReturner"), null); stm = new ALocalDeclStm(new TSemicolon(";"), methodReturnerVar); outerBlock.GetStatements().Add(stm); } AABlock afterBlock = new AABlock(); //A dictionary from the formals of the inline method to a cloneable replacement lvalue Dictionary <AALocalDecl, PLvalue> Parameters = new Dictionary <AALocalDecl, PLvalue>(); Dictionary <AALocalDecl, PExp> ParameterExps = new Dictionary <AALocalDecl, PExp>(); for (int i = 0; i < decl.GetFormals().Count; i++) { AALocalDecl formal = (AALocalDecl)decl.GetFormals()[i]; PExp arg = (PExp)node.GetArgs()[0]; PLvalue lvalue; //if ref, dont make a new var if (formal.GetRef() != null && arg is ALvalueExp) { arg.Apply(new MoveMethodDeclsOut("inlineVar", finalTrans.data)); arg.Parent().RemoveChild(arg); lvalue = ((ALvalueExp)arg).GetLvalue(); } else if (!assignedToFormals.Contains(formal) && Util.IsLocal(arg, finalTrans.data)) { lvalue = new ALocalLvalue(new TIdentifier("I hope I dont make it")); finalTrans.data.LvalueTypes[lvalue] = formal.GetType(); finalTrans.data.LocalLinks[(ALocalLvalue)lvalue] = formal; ParameterExps[formal] = arg; arg.Parent().RemoveChild(arg); } else { AAssignmentExp assExp = null; if (formal.GetOut() != null) { //Dont initialize with arg, but assign arg after arg.Apply(new MoveMethodDeclsOut("inlineVar", finalTrans.data)); lvalue = ((ALvalueExp)arg).GetLvalue(); assExp = new AAssignmentExp(new TAssign("="), lvalue, null); finalTrans.data.ExpTypes[assExp] = finalTrans.data.LvalueTypes[lvalue]; arg.Parent().RemoveChild(arg); arg = null; } AALocalDecl parameter = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(formal.GetType(), finalTrans.data), new TIdentifier(formal.GetName().Text), arg); stm = new ALocalDeclStm(new TSemicolon(";"), parameter); outerBlock.GetStatements().Add(stm); lvalue = new ALocalLvalue(new TIdentifier(parameter.GetName().Text)); finalTrans.data.LvalueTypes[lvalue] = parameter.GetType(); finalTrans.data.LocalLinks[(ALocalLvalue)lvalue] = parameter; if (formal.GetOut() != null) { //Dont initialize with arg, but assign arg after ALvalueExp lvalueExp = new ALvalueExp(Util.MakeClone(lvalue, finalTrans.data)); finalTrans.data.ExpTypes[lvalueExp] = finalTrans.data.LvalueTypes[lvalue]; assExp.SetExp(lvalueExp); afterBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), assExp)); } } Parameters.Add(formal, lvalue); } AABlock innerBlock = (AABlock)decl.GetBlock().Clone(); exp = new ABooleanConstExp(new ATrueBool()); finalTrans.data.ExpTypes[exp] = new ANamedType(new TIdentifier("bool"), null); ABlockStm innerBlockStm = new ABlockStm(new TLBrace("{"), innerBlock); bool needWhile = CheckIfWhilesIsNeeded.IsWhileNeeded(decl.GetBlock()); if (needWhile) { stm = new AWhileStm(new TLParen("("), exp, innerBlockStm); } else { stm = innerBlockStm; } outerBlock.GetStatements().Add(stm); outerBlock.GetStatements().Add(new ABlockStm(new TLBrace("{"), afterBlock)); //Clone method contents to inner block. CloneMethod cloneFixer = new CloneMethod(finalTrans, Parameters, ParameterExps, innerBlockStm); decl.GetBlock().Apply(cloneFixer); foreach (KeyValuePair <PLvalue, PExp> pair in cloneFixer.ReplaceUsAfter) { PLvalue lvalue = pair.Key; PExp replacement = Util.MakeClone(pair.Value, finalTrans.data); ALvalueExp lvalueParent = (ALvalueExp)lvalue.Parent(); lvalueParent.ReplaceBy(replacement); } innerBlockStm.Apply(new FixTypes(finalTrans.data)); innerBlock.Apply(new FixReturnsAndWhiles(hasMethodReturnedVar, methodReturnerVar, finalTrans.data, needWhile)); GetNonBlockStm stmFinder = new GetNonBlockStm(false); innerBlock.Apply(stmFinder); if (needWhile && (stmFinder.Stm == null || !(stmFinder.Stm is ABreakStm))) { innerBlock.GetStatements().Add(new ABreakStm(new TBreak("break"))); } //Insert before current statement ABlockStm outerBlockStm = new ABlockStm(new TLBrace("{"), outerBlock); PStm pStm = Util.GetAncestor <PStm>(node); pBlock = (AABlock)pStm.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), outerBlockStm); if (node.Parent() == pStm && pStm is AExpStm) { pBlock.RemoveChild(pStm); } else { PLvalue lvalue = new ALocalLvalue(new TIdentifier(methodReturnerVar.GetName().Text)); finalTrans.data.LvalueTypes[lvalue] = methodReturnerVar.GetType(); finalTrans.data.LocalLinks[(ALocalLvalue)lvalue] = methodReturnerVar; exp = new ALvalueExp(lvalue); finalTrans.data.ExpTypes[exp] = methodReturnerVar.GetType(); node.ReplaceBy(exp); } return(new List <AABlock>() { outerBlock }); }
public override void CaseAConstructorDecl(AConstructorDecl node) { AStructDecl str = Util.GetAncestor <AStructDecl>(node); AEnrichmentDecl enrichment = Util.GetAncestor <AEnrichmentDecl>(node); AMethodDecl replacer = new AMethodDecl(new APublicVisibilityModifier(), null, null, null, null, null, new AVoidType(new TVoid("void")), node.GetName(), new ArrayList(), node.GetBlock()); replacer.GetName().Text += "_Constructor"; while (node.GetFormals().Count > 0) { replacer.GetFormals().Add(node.GetFormals()[0]); } //Move the method outside the struct AASourceFile file = Util.GetAncestor <AASourceFile>(node); if (str != null) { str.RemoveChild(node.Parent()); } else { enrichment.RemoveChild(node); } int i = file.GetDecl().IndexOf(str ?? (PDecl)enrichment); file.GetDecl().Insert(i /* + 1*/, replacer); //Add the struct as a parameter PType type; if (str != null) { ANamedType structType = new ANamedType(new TIdentifier(str.GetName().Text), null); finalTrans.data.StructTypeLinks[structType] = str; type = structType; } else { type = Util.MakeClone(enrichment.GetType(), finalTrans.data); } finalTrans.data.ConstructorMap[node] = replacer; structFormal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new APointerType(new TStar("*"), type), new TIdentifier("currentStruct", replacer.GetName().Line, replacer.GetName().Pos), null); replacer.GetFormals().Add(structFormal); finalTrans.data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(file, replacer)); //Add return stm replacer.SetReturnType(new APointerType(new TStar("*"), Util.MakeClone(type, data))); replacer.Apply(new TransformConstructorReturns(structFormal, data)); //Insert call to base constructor);); if (finalTrans.data.ConstructorBaseLinks.ContainsKey(node)) { AMethodDecl baseConstructor = finalTrans.data.ConstructorMap[finalTrans.data.ConstructorBaseLinks[node]]; ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier(baseConstructor.GetName().Text), new ArrayList()); while (node.GetBaseArgs().Count > 0) { invoke.GetArgs().Add(node.GetBaseArgs()[0]); } AThisLvalue thisLvalue1 = new AThisLvalue(new TThis("this")); ALvalueExp thisExp1 = new ALvalueExp(thisLvalue1); invoke.GetArgs().Add(thisExp1); AThisLvalue thisLvalue2 = new AThisLvalue(new TThis("this")); AAssignmentExp assignExp = new AAssignmentExp(new TAssign("="), thisLvalue2, invoke); ANamedType structType = new ANamedType(new TIdentifier(str.GetName().Text), null); finalTrans.data.StructTypeLinks[structType] = str; finalTrans.data.LvalueTypes[thisLvalue1] = finalTrans.data.LvalueTypes[thisLvalue2] = finalTrans.data.ExpTypes[thisExp1] = finalTrans.data.ExpTypes[assignExp] = finalTrans.data.ExpTypes[invoke] = new APointerType(new TStar("*"), structType); //finalTrans.data.ExpTypes[invoke] = new AVoidType(new TVoid("void")); finalTrans.data.SimpleMethodLinks[invoke] = baseConstructor; ((AABlock)replacer.GetBlock()).GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), assignExp)); //Inline if base and current are two different kinds of pointer types (int/string) AStructDecl baseStruct = null; AConstructorDecl baseC = finalTrans.data.ConstructorBaseLinks[node]; foreach (KeyValuePair <AStructDecl, List <AConstructorDecl> > pair in finalTrans.data.StructConstructors) { bool found = false; foreach (AConstructorDecl decl in pair.Value) { if (baseC == decl) { found = true; break; } } if (found) { baseStruct = pair.Key; break; } } if ((str.GetIntDim() == null) != (baseStruct.GetIntDim() == null)) { //For the inilining, change the type to the type of the caller AALocalDecl lastFormal = baseConstructor.GetFormals().OfType <AALocalDecl>().Last(); lastFormal.SetRef(new TRef("ref")); APointerType oldType = (APointerType)lastFormal.GetType(); structType = new ANamedType(new TIdentifier(str.GetName().Text), null); finalTrans.data.StructTypeLinks[structType] = str; APointerType newType = new APointerType(new TStar("*"), structType); lastFormal.SetType(newType); foreach ( ALocalLvalue lvalue in data.LocalLinks.Where(pair => pair.Value == lastFormal).Select(pair => pair.Key)) { data.LvalueTypes[lvalue] = newType; if (lvalue.Parent() is ALvalueExp) { data.ExpTypes[(PExp)lvalue.Parent()] = newType; if (lvalue.Parent().Parent() is APointerLvalue) { data.LvalueTypes[(PLvalue)lvalue.Parent().Parent()] = newType.GetType(); } } } FixInlineMethods.Inline(invoke, finalTrans); lastFormal.SetRef(null); foreach ( ALocalLvalue lvalue in data.LocalLinks.Where(pair => pair.Value == lastFormal).Select(pair => pair.Key)) { data.LvalueTypes[lvalue] = oldType; if (lvalue.Parent() is ALvalueExp) { data.ExpTypes[(PExp)lvalue.Parent()] = oldType; if (lvalue.Parent().Parent() is APointerLvalue) { data.LvalueTypes[(PLvalue)lvalue.Parent().Parent()] = oldType.GetType(); } } } lastFormal.SetType(oldType); } //Inline it instead, Since the pointer implementations might not be the same (int vs string) /*AMethodDecl baseConstructor = finalTrans.data.ConstructorMap[finalTrans.data.ConstructorBaseLinks[node]]; * * AABlock localsBlock = new AABlock(new ArrayList(), new TRBrace("}")); * ABlockStm cloneBlock = new ABlockStm(new TLBrace("{"), (PBlock) baseConstructor.GetBlock().Clone()); * Dictionary<AALocalDecl, PLvalue> localMap = new Dictionary<AALocalDecl, PLvalue>(); * for (int argNr = 0; argNr < baseConstructor.GetFormals().Count; argNr++) * { * AALocalDecl formal = (AALocalDecl) baseConstructor.GetFormals()[i]; * PExp arg; * if (i < baseConstructor.GetFormals().Count - 1) * arg = (PExp)node.GetBaseArgs()[i]; * else * { * AThisLvalue thisLvalue = new AThisLvalue(new TThis("this")); * ALvalueExp thisExp = new ALvalueExp(thisLvalue); * * ANamedType structType = new ANamedType(new TIdentifier(str.GetName().Text), null); * finalTrans.data.StructTypeLinks[structType] = str; * * finalTrans.data.LvalueTypes[thisLvalue] = * finalTrans.data.ExpTypes[thisExp] = new APointerType(new TStar("*"), structType); * * arg = thisExp; * } * * if (formal.GetRef() != null || formal.GetOut() != null) * { * //Use same variable * localMap[formal] = ((ALvalueExp) arg).GetLvalue(); * } * else * { * //Make a new variable * AALocalDecl newLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, * Util.MakeClone(formal.GetType(), finalTrans.data), * new TIdentifier(formal.GetName().Text), * Util.MakeClone(arg, data)); * * ALocalLvalue newLocalRef = new ALocalLvalue(new TIdentifier(newLocal.GetName().Text)); * * localMap[formal] = newLocalRef; * data.LvalueTypes[newLocalRef] = newLocal.GetType(); * data.LocalLinks[newLocalRef] = newLocal; * * localsBlock.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), newLocal)); * } * * } * * CloneMethod cloner = new CloneMethod(finalTrans.data, localMap, cloneBlock); * baseConstructor.GetBlock().Apply(cloner); * * ((AABlock)cloneBlock.GetBlock()).GetStatements().Insert(0, new ABlockStm(new TLBrace("{"), localsBlock)); * ((AABlock)node.GetBlock()).GetStatements().Insert(0, cloneBlock);*/ } //Fix refferences to other struct stuff); base.CaseAMethodDecl(replacer); //Add functionality to refference the current struct in a constructor //Want to do it as a pointer type, since the constructer can only be called for pointer types }
private void MakeInitializerInvokes() { AABlock block = (AABlock)mainEntry.GetBlock(); AASourceFile file = Util.GetAncestor <AASourceFile>(mainEntry); AMethodDecl invokeMethod; /* Add * void Invoke(string methodName) * { * trigger initTrigger = TriggerCreate(methodName); * TriggerExecute(initTrigger, false, true); * TriggerDestroy(initTrigger); * } */ { //void Invoke(string methodName) AALocalDecl parameter = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("string"), null), new TIdentifier("methodName"), null); AABlock methodBody = new AABlock(); invokeMethod = new AMethodDecl(new APublicVisibilityModifier(), null, null, null, null, null, new AVoidType(new TVoid("void")), new TIdentifier("Invoke"), new ArrayList() { parameter }, methodBody); //trigger initTrigger = TriggerCreate(methodName); ALocalLvalue parameterLvalue = new ALocalLvalue(new TIdentifier("methodName")); data.LocalLinks[parameterLvalue] = parameter; ALvalueExp parameterLvalueExp = new ALvalueExp(parameterLvalue); data.LvalueTypes[parameterLvalue] = data.ExpTypes[parameterLvalueExp] = parameter.GetType(); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("TriggerCreate"), new ArrayList() { parameterLvalueExp }); data.ExpTypes[invoke] = new ANamedType(new TIdentifier("trigger"), null); foreach (AMethodDecl methodDecl in data.Libraries.Methods) { if (methodDecl.GetName().Text == "TriggerCreate") { data.SimpleMethodLinks[invoke] = methodDecl; break; } } AALocalDecl initTriggerDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("trigger"), null), new TIdentifier("initTrigger"), invoke); methodBody.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), initTriggerDecl)); //TriggerExecute(initTrigger, false, true); ALocalLvalue initTriggerLvalue = new ALocalLvalue(new TIdentifier("initTrigger")); data.LocalLinks[initTriggerLvalue] = initTriggerDecl; ALvalueExp initTriggerLvalueExp = new ALvalueExp(initTriggerLvalue); data.LvalueTypes[initTriggerLvalue] = data.ExpTypes[initTriggerLvalueExp] = initTriggerDecl.GetType(); ABooleanConstExp falseBool = new ABooleanConstExp(new AFalseBool()); ABooleanConstExp trueBool = new ABooleanConstExp(new ATrueBool()); data.ExpTypes[falseBool] = data.ExpTypes[trueBool] = new ANamedType(new TIdentifier("bool"), null); invoke = new ASimpleInvokeExp(new TIdentifier("TriggerExecute"), new ArrayList() { initTriggerLvalueExp, falseBool, trueBool }); data.ExpTypes[invoke] = new AVoidType(new TVoid("void")); foreach (AMethodDecl methodDecl in data.Libraries.Methods) { if (methodDecl.GetName().Text == "TriggerExecute") { data.SimpleMethodLinks[invoke] = methodDecl; break; } } methodBody.GetStatements().Add(new AExpStm(new TSemicolon(";"), invoke)); //TriggerDestroy(initTrigger); initTriggerLvalue = new ALocalLvalue(new TIdentifier("initTrigger")); data.LocalLinks[initTriggerLvalue] = initTriggerDecl; initTriggerLvalueExp = new ALvalueExp(initTriggerLvalue); data.LvalueTypes[initTriggerLvalue] = data.ExpTypes[initTriggerLvalueExp] = initTriggerDecl.GetType(); invoke = new ASimpleInvokeExp(new TIdentifier("TriggerDestroy"), new ArrayList() { initTriggerLvalueExp }); data.ExpTypes[invoke] = new AVoidType(new TVoid("void")); foreach (AMethodDecl methodDecl in data.Libraries.Methods) { if (methodDecl.GetName().Text == "TriggerDestroy") { data.SimpleMethodLinks[invoke] = methodDecl; break; } } methodBody.GetStatements().Add(new AExpStm(new TSemicolon(";"), invoke)); file.GetDecl().Add(invokeMethod); } for (int i = data.InitializerMethods.Count - 1; i >= 0; i--) { AMethodDecl method = data.InitializerMethods[i]; //Turn method into a trigger method.SetReturnType(new ANamedType(new TIdentifier("bool"), null)); method.GetFormals().Add(new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("bool"), null), new TIdentifier("testConds"), null)); method.GetFormals().Add(new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("bool"), null), new TIdentifier("runActions"), null)); method.SetTrigger(new TTrigger("trigger")); ((AABlock)method.GetBlock()).GetStatements().Add(new AVoidReturnStm(new TReturn("return"))); TriggerConvertReturn returnConverter = new TriggerConvertReturn(data); method.Apply(returnConverter); data.TriggerDeclarations[method] = new List <TStringLiteral>(); //Add Invoke(<name>); to main entry TStringLiteral literal = new TStringLiteral(method.GetName().Text); data.TriggerDeclarations[method].Add(literal); AStringConstExp stringConst = new AStringConstExp(literal); data.ExpTypes[stringConst] = new ANamedType(new TIdentifier("string"), null); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("Invoke"), new ArrayList() { stringConst }); data.SimpleMethodLinks[invoke] = invokeMethod; data.ExpTypes[invoke] = invokeMethod.GetReturnType(); block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), invoke)); //ASyncInvokeExp syncInvokeExp = new ASyncInvokeExp(new TSyncInvoke("Invoke"), new AAmbiguousNameLvalue(new ASimpleName(new TIdentifier(method.GetName().Text))), new ArrayList()); //data.Invokes.Add(method, new List<InvokeStm>(){new InvokeStm(syncInvokeExp)}); //data.ExpTypes[syncInvokeExp] = new AVoidType(new TVoid("void")); //block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), syncInvokeExp)); } for (int i = data.InvokeOnIniti.Count - 1; i >= 0; i--) { AMethodDecl method = data.InvokeOnIniti[i]; //Turn method into a trigger method.SetReturnType(new ANamedType(new TIdentifier("bool"), null)); method.GetFormals().Add(new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("bool"), null), new TIdentifier("testConds"), null)); method.GetFormals().Add(new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("bool"), null), new TIdentifier("runActions"), null)); method.SetTrigger(new TTrigger("trigger")); ((AABlock)method.GetBlock()).GetStatements().Add(new AVoidReturnStm(new TReturn("return"))); TriggerConvertReturn returnConverter = new TriggerConvertReturn(data); method.Apply(returnConverter); data.TriggerDeclarations[method] = new List <TStringLiteral>(); //Add Invoke(<name>); to main entry TStringLiteral literal = new TStringLiteral(method.GetName().Text); data.TriggerDeclarations[method].Add(literal); AStringConstExp stringConst = new AStringConstExp(literal); data.ExpTypes[stringConst] = new ANamedType(new TIdentifier("string"), null); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("Invoke"), new ArrayList() { stringConst }); data.SimpleMethodLinks[invoke] = invokeMethod; data.ExpTypes[invoke] = invokeMethod.GetReturnType(); block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), invoke)); /* * ASyncInvokeExp syncInvokeExp = new ASyncInvokeExp(new TSyncInvoke("Invoke"), new AAmbiguousNameLvalue(new ASimpleName(new TIdentifier(method.GetName().Text))), new ArrayList()); * data.Invokes.Add(method, new List<InvokeStm>() { new InvokeStm(syncInvokeExp) }); * data.ExpTypes[syncInvokeExp] = new AVoidType(new TVoid("void")); * * block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), syncInvokeExp));*/ } for (int i = data.FieldsToInitInMapInit.Count - 1; i >= 0; i--) { AFieldDecl field = data.FieldsToInitInMapInit[i]; if (field.GetInit() == null) { continue; } AFieldLvalue lvalue = new AFieldLvalue(new TIdentifier(field.GetName().Text)); AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), lvalue, field.GetInit()); data.ExpTypes[assignment] = data.LvalueTypes[lvalue] = field.GetType(); data.FieldLinks[lvalue] = field; block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), assignment)); } block.RemoveChild(mainEntryFieldInitBlock); block.GetStatements().Insert(0, mainEntryFieldInitBlock); }
public override void CaseASimpleInvokeExp(ASimpleInvokeExp node) { AMethodDecl decl = finalTrans.data.SimpleMethodLinks[node]; if (structMethods.Contains(decl)) { //The target is a struct method that has been moved out if (node.GetArgs().Count < decl.GetFormals().Count&& Util.HasAncestor <AStructDecl>(node)) { //If this is the case, we Must be inside the same struct as the target. - Not with enheritance ALocalLvalue local = new ALocalLvalue(new TIdentifier("tempName")); ALvalueExp exp = new ALvalueExp(local); finalTrans.data.LvalueTypes[local] = finalTrans.data.ExpTypes[exp] = structFormal.GetType(); finalTrans.data.LocalLinks[local] = structFormal; //If we're calling from class to struct, we must depointer it AStructDecl currentStruct = finalTrans.data.StructMethods.First( pair => pair.Value.Contains(Util.GetAncestor <AMethodDecl>(node))).Key; AStructDecl baseStruct = finalTrans.data.StructMethods.First( pair => pair.Value.Contains(decl)).Key; if (currentStruct.GetClassToken() != baseStruct.GetClassToken()) //It's not possible to call from struct to class { APointerLvalue pointerLvalue = new APointerLvalue(new TStar("*"), exp); exp = new ALvalueExp(pointerLvalue); finalTrans.data.LvalueTypes[pointerLvalue] = finalTrans.data.ExpTypes[exp] = ((APointerType)structFormal.GetType()).GetType(); } node.GetArgs().Add(exp); } } else if (Util.GetAncestor <AStructDecl>(decl) != null && OldParentStruct.ContainsKey(Util.GetAncestor <AMethodDecl>(node))) { //The target is a struct method that hasn't been moved out if (Util.GetAncestor <AStructDecl>(decl) == OldParentStruct[Util.GetAncestor <AMethodDecl>(node)] && decl.GetStatic() == null) { //We have an internal struct call. Expect to have one too many args if (node.GetArgs().Count == decl.GetFormals().Count) { ALocalLvalue local = new ALocalLvalue(new TIdentifier("tempName")); ALvalueExp exp = new ALvalueExp(local); finalTrans.data.LvalueTypes[local] = finalTrans.data.ExpTypes[exp] = structFormal.GetType(); finalTrans.data.LocalLinks[local] = structFormal; //If we're calling from class to struct, we must depointer it AStructDecl currentStruct = finalTrans.data.StructMethods.First( pair => pair.Value.Contains(Util.GetAncestor <AMethodDecl>(node))).Key; AStructDecl baseStruct = finalTrans.data.StructMethods.First( pair => pair.Value.Contains(decl)).Key; if (currentStruct.GetClassToken() != baseStruct.GetClassToken()) //It's not possible to call from struct to class { APointerLvalue pointerLvalue = new APointerLvalue(new TStar("*"), exp); exp = new ALvalueExp(pointerLvalue); finalTrans.data.LvalueTypes[pointerLvalue] = finalTrans.data.ExpTypes[exp] = ((APointerType)structFormal.GetType()).GetType(); } node.GetArgs().Add(exp); } } } base.CaseASimpleInvokeExp(node); }
public static void Apply(AAProgram ast, FinalTransformations finalTrans) { //Build list of file dependacies Phase1 phase1 = new Phase1(finalTrans); ast.Apply(phase1); var dependancies = phase1.dependancies; if (dependancies.Keys.Count == 0) { return; } AASourceFile root = Util.GetAncestor <AASourceFile>(finalTrans.mainEntry) ?? dependancies.Keys.FirstOrDefault(file => !file.GetName().Text.Contains("\\")) ?? dependancies.Keys.First(file => true); //Remove files unreachable from root //On second thought, dont. there might be static refferences the other way which needs to be included /*{ * List<AASourceFile> reachable = GetReachable(root, dependancies); * AASourceFile[] keys = new AASourceFile[dependancies.Count]; * dependancies.Keys.CopyTo(keys, 0); * foreach (AASourceFile key in keys) * { * if (!reachable.Contains(key)) * dependancies.Remove(key); * } * }*/ //Push common depancies up /* * root -> (item1 -> (item3), item2 -> (item4 -> (item3))) * * root -> (item3, item1, item2 -> (item4)) */ //Add unreachable to the root while (true) { List <AASourceFile> reachable = new List <AASourceFile>(); GetReachable(root, dependancies, ref reachable); if (reachable.Count == dependancies.Count + (reachable.Contains(null) ? 1 : 0)) { break; } AASourceFile[] keys = new AASourceFile[dependancies.Count]; dependancies.Keys.CopyTo(keys, 0); foreach (AASourceFile key in keys) { if (!reachable.Contains(key)) { AASourceFile k = key; //See if you can find another unreachable file which need this file Dictionary <AASourceFile, int> decendantCounts = new Dictionary <AASourceFile, int>(); decendantCounts.Add(k, CountDecendants(k, dependancies, new List <AASourceFile>())); while (true) { AASourceFile file = null; foreach (KeyValuePair <AASourceFile, List <AASourceFile> > dependancy in dependancies) { if (decendantCounts.ContainsKey(dependancy.Key)) { continue; } if (!dependancy.Value.Contains(k)) { continue; } file = dependancy.Key; break; } //AASourceFile file = dependancies.FirstOrDefault(item => item.Value.Contains(k)).Key; if (file == null) { break; } decendantCounts.Add(file, CountDecendants(file, dependancies, new List <AASourceFile>())); k = file; } foreach (KeyValuePair <AASourceFile, int> decendantItem in decendantCounts) { if (decendantItem.Value > decendantCounts[k]) { k = decendantItem.Key; } } dependancies[root].Add(k); break; } } } //It is moved down here because cycles are not removed in unreachable RemoveCycles(root, dependancies, new List <AASourceFile> { root }); //Convert to tree to make it easier List <Item> allItems = new List <Item>(); IncludeItem rootIncludeItem = MakeTree(root, dependancies, allItems, null); bool[] removed = new bool[allItems.Count]; for (int i = 0; i < removed.Length; i++) { removed[i] = false; } int removedCount = 0; //Ensure that each include is only included one place for (int i = 0; i < allItems.Count; i++) { if (removed[i]) { continue; } IncludeItem item1 = (IncludeItem)allItems[i]; for (int j = i + 1; j < allItems.Count; j++) { if (removed[j]) { continue; } IncludeItem item2 = (IncludeItem)allItems[j]; if (item1.Current == item2.Current) { List <Item> path1 = item1.Path; List <Item> path2 = item2.Path; for (int k = 0; k < Math.Min(path1.Count, path2.Count); k++) { if (path1[k] != path2[k]) { int insertAt = Math.Min(path1[k - 1].Children.IndexOf(path1[k]), path2[k - 1].Children.IndexOf(path2[k])); item1.Parent.Children.Remove(item1); LinkedList <IncludeItem> toRemove = new LinkedList <IncludeItem>(); toRemove.AddLast(item2); while (toRemove.Count > 0) { IncludeItem item = toRemove.First.Value; toRemove.RemoveFirst(); item.Parent.Children.Remove(item); //allItems.Remove(item); removedCount++; removed[item.ListIndex] = true; foreach (IncludeItem child in item.Children) { toRemove.AddLast(child); } } //j--; path1[k - 1].Children.Insert(insertAt, item1); item1.Parent = path1[k - 1]; break; } } } } } List <Item> newAllItems = new List <Item>(allItems.Count - removedCount); for (int i = 0; i < allItems.Count; i++) { if (!removed[i]) { newAllItems.Add(allItems[i]); } } allItems = newAllItems; //Move the null node to nr [0] foreach (IncludeItem item in allItems) { if (item.Current == null) { int itemIndex = item.Parent.Children.IndexOf(item); Item item0 = item.Parent.Children[0]; item.Parent.Children[0] = item; item.Parent.Children[itemIndex] = item0; break; } } //Insert method decls and move structs & fields up as needed ast.Apply(new Phase2(finalTrans, allItems)); //Insert the headers in the files if (Options.Compiler.OneOutputFile) { //for (int i = 0; i < allItems.Count; i++) int i = 0; while (allItems.Count > 0) { if (allItems[i] is IncludeItem) { IncludeItem includeItem = (IncludeItem)allItems[i]; //Dont want the standard lib if (includeItem.Current == null) { i++; continue; } //If it has children with children, then pick another first if (includeItem.Children.Any(child => child.Children.Count > 0)) { i++; continue; } if (includeItem.Children.Count == 0) { if (includeItem.Parent == null) { break; } i++; continue; } i = 0; //Put all children into this while (includeItem.Children.Count > 0) { int childNr = includeItem.Children.Count - 1; allItems.Remove(includeItem.Children[childNr]); if (includeItem.Children[childNr] is FieldItem) { FieldItem aItem = (FieldItem)includeItem.Children[childNr]; Node node = aItem.FieldDecl; node.Parent().RemoveChild(node); includeItem.Current.GetDecl().Insert(0, node); } else if (includeItem.Children[childNr] is StructItem) { StructItem aItem = (StructItem)includeItem.Children[childNr]; Node node = aItem.StructDecl; node.Parent().RemoveChild(node); includeItem.Current.GetDecl().Insert(0, node); } else if (includeItem.Children[childNr] is MethodDeclItem) { MethodDeclItem aItem = (MethodDeclItem)includeItem.Children[childNr]; AMethodDecl aNode = new AMethodDecl(); if (aItem.RealDecl.GetStatic() != null) { aNode.SetStatic(new TStatic("static")); } aNode.SetReturnType(Util.MakeClone(aItem.RealDecl.GetReturnType(), finalTrans.data)); aNode.SetName(new TIdentifier(aItem.RealDecl.GetName().Text)); foreach (AALocalDecl formal in aItem.RealDecl.GetFormals()) { AALocalDecl clone = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(formal.GetType(), finalTrans.data), new TIdentifier(formal.GetName().Text), null); aNode.GetFormals().Add(clone); } includeItem.Current.GetDecl().Insert(0, aNode); } else if (includeItem.Children[childNr] is IncludeItem) { IncludeItem aChild = (IncludeItem)includeItem.Children[childNr]; if (aChild.Current == null) { AIncludeDecl node = new AIncludeDecl(new TInclude("include"), new TStringLiteral("\"TriggerLibs/NativeLib\"")); includeItem.Current.GetDecl().Insert(0, node); } else { PDecl[] decls = new PDecl[aChild.Current.GetDecl().Count]; aChild.Current.GetDecl().CopyTo(decls, 0); for (int k = decls.Length - 1; k >= 0; k--) { includeItem.Current.GetDecl().Insert(0, decls[k]); } aChild.Current.Parent().RemoveChild(aChild.Current); //i = -1; } } includeItem.Children.RemoveAt(childNr); } } } } else { foreach (IncludeItem includeItem in allItems.OfType <IncludeItem>()) { for (int i = includeItem.Children.Count - 1; i >= 0; i--) { Node node; if (includeItem.Children[i] is IncludeItem) { IncludeItem aItem = (IncludeItem)includeItem.Children[i]; node = new AIncludeDecl(new TInclude("include"), new TStringLiteral("\"" + (aItem.Current == null ? "TriggerLibs/NativeLib" : aItem.Current.GetName().Text.Replace("\\", "/")) + "\"")); if (aItem.Current == null && finalTrans.mainEntry != null) { //Search for user defined initlib bool foundInvoke = false; foreach (ASimpleInvokeExp invokeExp in finalTrans.data.SimpleMethodLinks.Keys) { if (invokeExp.GetName().Text == "libNtve_InitLib" && invokeExp.GetArgs().Count == 0) { /*finalTrans.errors.Add(new ErrorCollection.Error(invokeExp.GetName(), * Util.GetAncestor<AASourceFile>( * invokeExp), * "You are invoking libNtve_InitLib() yourself somewhere. It will not be auto inserted.", * true));*/ foundInvoke = true; break; } } if (!foundInvoke) { //Init the lib ASimpleInvokeExp initExp = new ASimpleInvokeExp(); initExp.SetName(new TIdentifier("libNtve_InitLib")); finalTrans.data.ExpTypes[initExp] = new AVoidType(new TVoid("void")); foreach (AMethodDecl method in finalTrans.data.Libraries.Methods) { if (method.GetName().Text == "libNtve_InitLib" && method.GetFormals().Count == 0) { finalTrans.data.SimpleMethodLinks[initExp] = method; } } AABlock block = (AABlock)finalTrans.mainEntry.GetBlock(); block.GetStatements().Insert(0, new AExpStm(new TSemicolon(";"), initExp)); } } } else if (includeItem.Children[i] is FieldItem) { FieldItem aItem = (FieldItem)includeItem.Children[i]; node = aItem.FieldDecl; node.Parent().RemoveChild(node); } else if (includeItem.Children[i] is StructItem) { StructItem aItem = (StructItem)includeItem.Children[i]; node = aItem.StructDecl; node.Parent().RemoveChild(node); } else if (includeItem.Children[i] is MethodDeclItem) { MethodDeclItem aItem = (MethodDeclItem)includeItem.Children[i]; AMethodDecl aNode = new AMethodDecl(); if (aItem.RealDecl.GetStatic() != null) { aNode.SetStatic(new TStatic("static")); } aNode.SetReturnType(Util.MakeClone(aItem.RealDecl.GetReturnType(), finalTrans.data)); aNode.SetName(new TIdentifier(aItem.RealDecl.GetName().Text)); foreach (AALocalDecl formal in aItem.RealDecl.GetFormals()) { AALocalDecl clone = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(formal.GetType(), finalTrans.data), new TIdentifier(formal.GetName().Text), null); aNode.GetFormals().Add(clone); } node = aNode; } else { throw new Exception("FixIncludes.Apply: Unexpected item type"); } includeItem.Current.GetDecl().Insert(0, node); } } } }
//private List<ErrorCollection.Error> multipleEntryCandidates = new List<ErrorCollection.Error>(); public override void CaseAMethodDecl(AMethodDecl node) { //Done in a previous iteration /*if (node.GetName().Text == "InitMap" && node.GetFormals().Count == 0) * { * if (finalTrans.multipleMainEntries) * { * multipleEntryCandidates.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor<AASourceFile>(node.GetName()), "Candidate")); * } * else if (finalTrans.mainEntry != null) * { * multipleEntryCandidates.Add(new ErrorCollection.Error(finalTrans.mainEntry.GetName(), Util.GetAncestor<AASourceFile>(finalTrans.mainEntry.GetName()), "Candidate")); * multipleEntryCandidates.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor<AASourceFile>(node.GetName()), "Candidate")); * //finalTrans.errors.Add(new ErrorCollection.Error(node.GetName(), Util.GetAncestor<AASourceFile>(node), "Found multiple candidates for a main entry", true)); * finalTrans.multipleMainEntries = true; * finalTrans.mainEntry = null; * } * else * finalTrans.mainEntry = node; * }*/ AStructDecl str = Util.GetAncestor <AStructDecl>(node); if (str != null) { if (node.GetStatic() == null) { structMethods.Add(node); } //Move the method outside the struct str.RemoveChild(node.Parent()); AASourceFile file = (AASourceFile)str.Parent(); int i = file.GetDecl().IndexOf(str); file.GetDecl().Insert(i /* + 1*/, node); node.GetName().Text = GetUniqueStructMethodName(str.GetName().Text + "_" + node.GetName().Text); if (node.GetStatic() == null) { //Add the struct as a parameter PType structType = new ANamedType(new TIdentifier(str.GetName().Text), null); finalTrans.data.StructTypeLinks[(ANamedType)structType] = str; if (str.GetClassToken() != null) { structType = new APointerType(new TStar("*"), structType); } structFormal = new AALocalDecl(new APublicVisibilityModifier(), null, str.GetClassToken() == null ? new TRef("ref") : null, null, null, structType, new TIdentifier("currentStruct", node.GetName().Line, node.GetName().Pos), null); node.GetFormals().Add(structFormal); data.Locals[(AABlock)node.GetBlock()].Add(structFormal); } else { node.SetStatic(null); } finalTrans.data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(file, node)); if (node.GetStatic() == null) { OldParentStruct[node] = str; } //Fix refferences to other struct stuff); base.CaseAMethodDecl(node); //Will visit later, since it's added after the struct //base.CaseAMethodDecl(node); //if (str.GetLocals().Count == 0) // str.Parent().RemoveChild(str); return; } AEnrichmentDecl enrichment = Util.GetAncestor <AEnrichmentDecl>(node); if (enrichment != null) { if (node.GetStatic() == null) { structMethods.Add(node); } //Move the method outside the struct enrichment.RemoveChild(node); AASourceFile file = (AASourceFile)enrichment.Parent(); int i = file.GetDecl().IndexOf(enrichment); file.GetDecl().Insert(i /* + 1*/, node); node.GetName().Text = GetUniqueStructMethodName(Util.TypeToIdentifierString(enrichment.GetType()) + "_" + node.GetName().Text); if (node.GetStatic() == null) { //Add the struct as a parameter PType structType = Util.MakeClone(enrichment.GetType(), finalTrans.data); structFormal = new AALocalDecl(new APublicVisibilityModifier(), null, new TRef("ref"), null, null, structType, new TIdentifier("currentEnrichment", node.GetName().Line, node.GetName().Pos), null); node.GetFormals().Add(structFormal); } finalTrans.data.Methods.Add(new SharedData.DeclItem <AMethodDecl>(file, node)); //Fix refferences to other struct stuff); base.CaseAMethodDecl(node); //Will visit later, since it's added after the struct //base.CaseAMethodDecl(node); //if (str.GetLocals().Count == 0) // str.Parent().RemoveChild(str); return; } //Build a list of overloads List <AMethodDecl> overloads = new List <AMethodDecl>(); List <string> prefixMatches = new List <string>(); foreach (SharedData.DeclItem <AMethodDecl> declItem in finalTrans.data.Methods) { if (!Util.IsSameNamespace(declItem.Decl, node)) { continue; } if (declItem.Decl.GetName().Text == node.GetName().Text) { overloads.Add(declItem.Decl); } if (declItem.Decl.GetName().Text.StartsWith(node.GetName().Text + "O")) { prefixMatches.Add(declItem.Decl.GetName().Text); } } foreach (AMethodDecl method in finalTrans.data.Libraries.Methods) { if (method.GetBlock() != null || method.GetNative() != null) { if (method.GetName().Text == node.GetName().Text) { overloads.Add(method); } if (method.GetName().Text.StartsWith(node.GetName().Text + "O")) { prefixMatches.Add(method.GetName().Text); } } } //Add fields foreach (SharedData.DeclItem <AFieldDecl> declItem in finalTrans.data.Fields) { if (declItem.Decl.GetName().Text.StartsWith(node.GetName().Text + "O")) { prefixMatches.Add(declItem.Decl.GetName().Text); } } foreach (AFieldDecl field in finalTrans.data.Libraries.Fields) { if (field.GetName().Text.StartsWith(node.GetName().Text + "O")) { prefixMatches.Add(field.GetName().Text); } } //Dont want to hit another method by appending O# string postfix = ""; while (true) { postfix += "O"; if (prefixMatches.Any(text => text.StartsWith(node.GetName().Text + postfix))) { continue; } break; } if (overloads.Count > 1) { int i = 0; foreach (AMethodDecl method in overloads) { if (node == finalTrans.mainEntry || (node.GetTrigger() != null && finalTrans.data.HasUnknownTrigger)) { continue; } i++; method.GetName().Text += postfix + i; } } if (node != finalTrans.mainEntry && (node.GetTrigger() == null || !finalTrans.data.HasUnknownTrigger)) { node.GetName().Text = namespacePrefix + node.GetName().Text; } base.CaseAMethodDecl(node); }