public static ControlFlowGraph Create(AMethodDecl method) { ControlFlowGraph graph = new ControlFlowGraph(method); CFGGenerator generator = new CFGGenerator(); method.GetBlock().Apply(generator); graph.Nodes = new List<Node>(generator.Nodes.Count); graph.Nodes.AddRange(generator.Nodes); return graph; }
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); }
private void Analyze(AMethodDecl method) { MethodAnalyzer analyzer = new MethodAnalyzer(method, Methods, data); method.GetBlock().Apply(this); Methods[method] = analyzer.SafeData; /* List of safe variables after each statement * While statements need a list for first statement in the while, and a list for first statement after the while * Also need to account for break and continue statments * If statements need a list for then then branch, and one for the else branch. * * CFG: * Join(v): * First, set safeList = intersection(pred(stm)) * Parse through expression, do the folloing in the order you get out of nodes * pointerLvalue: If unsafe, make a test, and restart check ///NO, its an iterative build. do this after * delete: clear safeList, safeIfTrue and safeIfFalse * p == null: if p is a pointer, add p to a safeIfTrue list * p != null: if p is a pointer, add p to a safeIfFalse list * !<exp>: swap safeIfTrue and safeIfFalse lists * <exp> || <exp>: intersection between left and right safeIfTrue list * <exp> && <exp>: intersection between left and right safeIfFalse list * * if stm: thenList = safeList U safeIfTrue * afterList = safeList U safeIfFalse * if-else stm: thenList = safeList U safeIfTrue * elseList = safeList U safeIfFalse * while stm: thenList = safeList U safeIfTrue * * * Problem: if something is safe before a while, it currently can't become safe in the while, since it will not initially be safe at the end of the while. * * * * ------------------------------- * * List of unsafe variables after each CFG node. * * Preprocess step: List of all used variables (Base: Field/Local, Others:Pointer/StructField) * * All those variables are unsafe before first statment * * * Join(v): * * */ }
public override void CaseAMethodDecl(AMethodDecl node) { InAMethodDecl(node); if (node.GetBlock() != null) { node.GetBlock().Apply(this); } { Object[] temp = new Object[node.GetFormals().Count]; node.GetFormals().CopyTo(temp, 0); for (int i = temp.Length - 1; i >= 0; i--) { ((PLocalDecl)temp[i]).Apply(this); } } if (node.GetName() != null) { node.GetName().Apply(this); } if (node.GetReturnType() != null) { node.GetReturnType().Apply(this); } if (node.GetDelegate() != null) { node.GetDelegate().Apply(this); } if (node.GetInline() != null) { node.GetInline().Apply(this); } if (node.GetNative() != null) { node.GetNative().Apply(this); } if (node.GetStatic() != null) { node.GetStatic().Apply(this); } if (node.GetTrigger() != null) { node.GetTrigger().Apply(this); } if (node.GetVisibilityModifier() != null) { node.GetVisibilityModifier().Apply(this); } OutAMethodDecl(node); }
public override void OutAMethodDecl(AMethodDecl node) { //If void return is missing, insert it. if (node.GetReturnType() is AVoidType && node.GetBlock() != null) { AABlock block = (AABlock)node.GetBlock(); bool insertReturn = false; while (true) { if (block.GetStatements().Count == 0) { insertReturn = true; break; } PStm lastStm = (PStm)block.GetStatements()[block.GetStatements().Count - 1]; if (lastStm is AVoidReturnStm) break; if (lastStm is ABlockStm) { block = (AABlock)((ABlockStm)block.GetStatements()[block.GetStatements().Count - 1]).GetBlock(); continue; } insertReturn = true; break; } if (insertReturn) { block.GetStatements().Add(new AVoidReturnStm(new TReturn("return", block.GetToken().Line, block.GetToken().Pos))); } } //Check if delegate is valid if (node.GetDelegate() != null) { if (node.GetBlock() != null) errors.Add(new ErrorCollection.Error(node.GetDelegate(), currentSourceFile, LocRM.GetString("ErrorText195"))); if (node.GetInline() != null) errors.Add(new ErrorCollection.Error(node.GetDelegate(), currentSourceFile, LocRM.GetString("ErrorText196"))); if (node.GetTrigger() != null) errors.Add(new ErrorCollection.Error(node.GetDelegate(), currentSourceFile, LocRM.GetString("ErrorText197"))); if (node.GetStatic() != null) errors.Add(new ErrorCollection.Error(node.GetDelegate(), currentSourceFile, LocRM.GetString("ErrorText198"))); if (node.GetNative() != null) errors.Add(new ErrorCollection.Error(node.GetDelegate(), currentSourceFile, LocRM.GetString("ErrorText199"))); } //If it's protected, it must be in a struct if (!Util.HasAncestor<AStructDecl>(node)) { if (node.GetVisibilityModifier() is AProtectedVisibilityModifier) errors.Add(new ErrorCollection.Error(node.GetName(), LocRM.GetString("ErrorText200"))); } base.OutAMethodDecl(node); }
public override void OutAMethodDecl(AMethodDecl node) { if (node.GetTrigger() != null) { bool validSignature = IsBoolType(node.GetReturnType()); validSignature &= node.GetFormals().Count == 2; foreach (AALocalDecl formal in node.GetFormals()) { validSignature &= IsBoolType(formal.GetType()); validSignature &= formal.GetRef() == null && formal.GetOut() == null; } if (!validSignature) { errors.Add(new ErrorCollection.Error(node.GetName(), currentSourceFile, LocRM.GetString("ErrorText156"))); } } //Check that all code paths return a value if (!(node.GetReturnType() is AVoidType)) { CheckReturns returnChecker = new CheckReturns(); node.GetBlock().Apply(returnChecker); if (!returnChecker.Returned) { errors.Add(new ErrorCollection.Error(node.GetName(), currentSourceFile, LocRM.GetString("ErrorText157"))); } } //If the return type or the type of any formals is a private struct, and the method is a public context, give an error { AStructDecl pStruct = Util.GetAncestor<AStructDecl>(node); //Is public context if (pStruct == null && node.GetVisibilityModifier() is APublicVisibilityModifier || pStruct != null && pStruct.GetVisibilityModifier() is APublicVisibilityModifier && !(node.GetVisibilityModifier() is APrivateVisibilityModifier)) { PType type = node.GetReturnType(); int i = 0; FindPrivateTypes finder = new FindPrivateTypes(data); while (true) { type.Apply(finder); if (i == node.GetFormals().Count) break; AALocalDecl formal = (AALocalDecl) node.GetFormals()[i]; type = formal.GetType(); i++; } if (finder.PrivateTypes.Count > 0) { List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>(); List<PDecl> usedDecls = new List<PDecl>(); foreach (ANamedType namedType in finder.PrivateTypes) { if (data.StructTypeLinks.ContainsKey(namedType)) { AStructDecl decl = data.StructTypeLinks[namedType]; if (usedDecls.Contains(decl)) continue; usedDecls.Add(decl); subErrors.Add(new ErrorCollection.Error(decl.GetName(), LocRM.GetString("ErrorText64"))); } else if (data.DelegateTypeLinks.ContainsKey(namedType)) { AMethodDecl decl = data.DelegateTypeLinks[namedType]; if (usedDecls.Contains(decl)) continue; usedDecls.Add(decl); subErrors.Add(new ErrorCollection.Error(decl.GetName(), LocRM.GetString("ErrorText154"))); } } errors.Add(new ErrorCollection.Error(node.GetName(), LocRM.GetString("ErrorText155"), false, subErrors.ToArray())); } } } base.OutAMethodDecl(node); }
/*public override void InAMethodDecl(AMethodDecl node) { AABlock block = (AABlock) node.GetBlock(); if (block != null) { if (!data.Locals.ContainsKey(block)) data.Locals.Add(block, new List<AALocalDecl>()); foreach (AALocalDecl formal in node.GetFormals()) { data.Locals[block].Add(formal); } } } public override void InAConstructorDecl(AConstructorDecl node) { AABlock block = (AABlock)node.GetBlock(); if (block != null) { if (!data.Locals.ContainsKey(block)) data.Locals.Add(block, new List<AALocalDecl>()); foreach (AALocalDecl formal in node.GetFormals()) { data.Locals[block].Add(formal); } } }*/ public override void OutAMethodDecl(AMethodDecl node) { AStructDecl parentStruct = Util.GetAncestor<AStructDecl>(node); AEnrichmentDecl parentEnrichment = Util.GetAncestor<AEnrichmentDecl>(node); if (parentStruct != null) { //Struct method data.StructMethods[parentStruct].Add(node); } else if (parentEnrichment == null) {//Global method //Dont care about abstract methods - will add them later if (node.GetBlock() != null || node.GetNative() != null) { data.Methods.Add(new SharedData.DeclItem<AMethodDecl>(currentSourceFile, node)); data.UserMethods.Add(node); } else if (node.GetDelegate() != null) data.Delegates.Add(new SharedData.DeclItem<AMethodDecl>(currentSourceFile, node)); else { node.Parent().RemoveChild(node); return; } } base.OutAMethodDecl(node); }
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 CaseAMethodDecl(AMethodDecl node) { if (firstMethodCall) StatementRemover.Parse(node); firstMethodCall = false; before.Clear(); after.Clear(); uses.Clear(); intersectingLocals.Clear(); definedLocals.Clear(); renamedLocals.Clear(); assigns.Clear(); changes = false; //Make uses setUses = true; base.CaseAMethodDecl(node); setUses = false; //Build a list of what's visible do { changes = false; base.CaseAMethodDecl(node); } while (changes); setSpans = true; base.CaseAMethodDecl(node); setSpans = false; //Join locals of same type, unless they are both parameters or they are listed as intersecting for (int i = 0; i < definedLocals.Count; i++) { for (int j = i + 1; j < definedLocals.Count; j++) { AALocalDecl decl1 = definedLocals[i]; AALocalDecl decl2 = definedLocals[j]; if (Util.TypeToString(decl1.GetType()) == Util.TypeToString(decl2.GetType()) && !intersectingLocals.Contains(new Pair(decl1, decl2))) { if (Util.GetAncestor<AABlock>(decl1) == null && Util.GetAncestor<AABlock>(decl2) == null) continue; AALocalDecl replacement = decl1; AALocalDecl replaced = decl2; //Dont replace the parameter if (Util.GetAncestor<AABlock>(replaced) == null) { replacement = decl2; replaced = decl1; i--; } j--; renamedLocals.Add(replaced, replacement); definedLocals.Remove(replaced); foreach (Pair pair in intersectingLocals) { if (pair.Local1 == replaced) pair.Local1 = replacement; if (pair.Local2 == replaced) pair.Local2 = replacement; } //Assign defaults if (replaced.GetInit() == null) { ALocalLvalue lvalue = new ALocalLvalue(new TIdentifier(replaced.GetName().Text)); finalTrans.data.LocalLinks[lvalue] = replaced; finalTrans.data.LvalueTypes[lvalue] = replaced.GetType(); List<PStm> statements = AssignDefault(lvalue); PStm pStm = Util.GetAncestor<PStm>(replaced); AABlock pBlock = (AABlock) pStm.Parent(); foreach (PStm statement in statements) { pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), statement); } pBlock.RemoveChild(pStm); } else { //Make an assignment expression instead ALocalDeclStm declStm = (ALocalDeclStm)replaced.Parent(); ALocalLvalue lvalue = new ALocalLvalue((TIdentifier)replaced.GetName().Clone()); finalTrans.data.LvalueTypes[lvalue] = replaced.GetType(); AAssignmentExp exp = new AAssignmentExp(new TAssign("=", lvalue.GetName().Line, lvalue.GetName().Pos), lvalue, replaced.GetInit()); AExpStm expStm = new AExpStm(declStm.GetToken(), exp); declStm.ReplaceBy(expStm); finalTrans.data.LvalueTypes[lvalue] = replacement.GetType(); finalTrans.data.ExpTypes[exp] = replacement.GetType(); finalTrans.data.LocalLinks[lvalue] = replacement; } } } } //Unique names List<string> names = new List<string>(); //Avoid clash with methods/fields/structs names.AddRange(finalTrans.data.Methods.Select(declItem => declItem.Decl.GetName().Text)); names.AddRange(finalTrans.data.Fields.Select(declItem => declItem.Decl.GetName().Text)); names.AddRange(finalTrans.data.Structs.Select(declItem => declItem.Decl.GetName().Text)); foreach (AALocalDecl local in definedLocals) { string name = local.GetName().Text; int version = 1; while (names.Contains(name)) { version++; name = local.GetName().Text + version; } local.GetName().Text = name; names.Add(name); } //Move defined locals to the start of the method foreach (AALocalDecl formal in node.GetFormals()) { definedLocals.Remove(formal); } AABlock block = (AABlock)node.GetBlock(); for (int i = 0; i < block.GetStatements().Count; i++) { ALocalDeclStm stm; if (block.GetStatements()[i] is ALocalDeclStm) { stm = (ALocalDeclStm)block.GetStatements()[i]; definedLocals.Remove((AALocalDecl)stm.GetLocalDecl()); continue; } //Add the rest at i if (definedLocals.Count == 0) break; AALocalDecl decl = definedLocals[0]; definedLocals.RemoveAt(0); if (decl.GetInit() == null) { ALocalLvalue lvalue = new ALocalLvalue(new TIdentifier(decl.GetName().Text)); finalTrans.data.LocalLinks[lvalue] = decl; finalTrans.data.LvalueTypes[lvalue] = decl.GetType(); List<PStm> statements = AssignDefault(lvalue); PStm pStm = Util.GetAncestor<PStm>(decl); AABlock pBlock = (AABlock) pStm.Parent(); foreach (PStm statement in statements) { pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), statement); } pBlock.RemoveChild(pStm); } else { //Make an assignment expression before moving stm = (ALocalDeclStm)decl.Parent(); ALocalLvalue lvalue = new ALocalLvalue(new TIdentifier(decl.GetName().Text)); finalTrans.data.LvalueTypes[lvalue] = decl.GetType(); AAssignmentExp exp = new AAssignmentExp(new TAssign("="), lvalue, decl.GetInit()); AExpStm expStm = new AExpStm(new TSemicolon(";"), exp); stm.ReplaceBy(expStm); finalTrans.data.LvalueTypes[lvalue] = decl.GetType(); finalTrans.data.ExpTypes[exp] = decl.GetType(); finalTrans.data.LocalLinks[lvalue] = decl; } stm = new ALocalDeclStm(new TSemicolon(";"), decl); block.GetStatements().Insert(i, stm); } fixRefferences = true; base.CaseAMethodDecl(node); fixRefferences = false; //If we have an assignment to a local where the stored result is never used, remove the assignment //Since we changed some statements, rebuild stuff before.Clear(); after.Clear(); uses.Clear(); intersectingLocals.Clear(); definedLocals.Clear(); renamedLocals.Clear(); assigns.Clear(); changes = false; //Make uses setUses = true; base.CaseAMethodDecl(node); setUses = false; //Build a list of what's visible do { changes = false; base.CaseAMethodDecl(node); } while (changes); PStm[] stms = new PStm[before.Keys.Count]; before.Keys.CopyTo(stms, 0); foreach (PStm stm in stms) { if (assigns[stm] != null && //Assignment exp !after[stm].Contains(assigns[stm]) && //Assignment unused Util.GetAncestor<AMethodDecl>(assigns[stm]) != null && !(stm is ALocalDeclStm))//It is to a local { stm.Apply(new MoveMethodDeclsOut(finalTrans.data)); stm.Parent().RemoveChild(stm); } } //Remove foo = foo; RemoveStupidAssignments assignmentRemover = new RemoveStupidAssignments(finalTrans.data); node.Apply(assignmentRemover); //Remove unused local variables foreach (AALocalDecl local in definedLocals) { if (Util.GetAncestor<AAProgram>(local) != null && Util.GetAncestor<AABlock>(local) != null && !finalTrans.data.LocalLinks.Where(p => p.Value == local).Any(p => Util.GetAncestor<AAProgram>(p.Key) != null)) local.Parent().Parent().RemoveChild(local.Parent()); } if (assignmentRemover.RemovedOne) { CaseAMethodDecl(node); return; } //If an assignment to a variable is completely local, and that assignment is only used once, put the assignment where it is used //Since we changed some statements, rebuild stuff before.Clear(); after.Clear(); uses.Clear(); intersectingLocals.Clear(); definedLocals.Clear(); renamedLocals.Clear(); assigns.Clear(); changes = false; //Make uses setUses = true; base.CaseAMethodDecl(node); setUses = false; //Build a list of what's visible do { changes = false; base.CaseAMethodDecl(node); } while (changes); foreach (KeyValuePair<PStm, AALocalDecl> pair in assigns) { PStm assignStm = pair.Key; AALocalDecl assignVar = pair.Value; bool isLocal = Util.IsLocal(assignStm, finalTrans.data); bool containsInvokeInPrevStm = false; if (assignVar != null && after[assignStm].Contains(assignVar)) { bool dontMove = false; //First, if there are any conditional parrent statement, where the variable is in live before the stm, then we can't move it PStm condParent = (PStm) Util.GetNearestAncestor(assignStm, typeof (AIfThenStm), typeof (AIfThenElseStm), typeof (AWhileStm)); while (condParent != null) { if (before[condParent].Contains(assignVar)) { dontMove = true; break; } condParent = (PStm)Util.GetNearestAncestor(condParent.Parent(), typeof(AIfThenStm), typeof(AIfThenElseStm), typeof(AWhileStm)); } PStm useStm = null; List<PStm> successors = GetSuccessor(assignStm); bool containsConditionalAssignments = false; while (successors.Count > 0) { if (successors.Count > 500) useStm = useStm; PStm successor = successors[0]; successors.RemoveAt(0); if (uses[successor].Contains(assignVar)) { if (useStm == null && !containsConditionalAssignments && !(successor is AWhileStm)) useStm = successor; else { dontMove = true; break; } } if (after[successor].Contains(assignVar) && !(assigns.ContainsKey(successor) && assigns[successor] == assignVar)) { List<PStm> newSuccessors = GetSuccessor(successor); foreach (PStm stm in newSuccessors) { if (!successors.Contains(stm)) successors.Add(stm); } } if (assigns.ContainsKey(successor) && uses[assignStm].Contains(assigns[successor])) { dontMove = true; break; } if (assigns.ContainsKey(successor) && assigns[successor] == assignVar) { condParent = (PStm)Util.GetNearestAncestor(successor, typeof(AIfThenStm), typeof(AIfThenElseStm), typeof(AWhileStm)); while (condParent != null) { if (!Util.IsAncestor(assignStm, condParent)) { containsConditionalAssignments = true; break; } condParent = (PStm)Util.GetNearestAncestor(condParent.Parent(), typeof(AIfThenStm), typeof(AIfThenElseStm), typeof(AWhileStm)); } //If we found a usage, and it is inside a while that the assignStm is not inside, but we are inside, don't move if (useStm != null) { AWhileStm whileParant = Util.GetAncestor<AWhileStm>(successor); while (whileParant != null) { if (Util.IsAncestor(useStm, whileParant) && !Util.IsAncestor(assignStm, whileParant)) { dontMove = true; break; } whileParant = Util.GetAncestor<AWhileStm>(whileParant.Parent()); } } } FindInvoke finder = new FindInvoke(); successor.Apply(finder); if (finder.ContainsInvoke && useStm == null) containsInvokeInPrevStm = true; } if (useStm != null && !dontMove) { //If assignStm is inside an if, and the use stm is not, and there is another assignment //to the same variable in an else block, then don't join AIfThenElseStm ifThenElse = Util.GetAncestor<AIfThenElseStm>(assignStm); while (ifThenElse != null) { if (!Util.IsAncestor(useStm, ifThenElse)) { ABlockStm otherBlock; if (Util.IsAncestor(assignStm, ifThenElse.GetThenBody())) otherBlock = (ABlockStm) ifThenElse.GetElseBody(); else otherBlock = (ABlockStm)ifThenElse.GetThenBody(); StmEnum enumerator = new StmEnum(otherBlock); while (enumerator.MoveNext()) { PStm stm = (PStm) enumerator.Current; if (assigns.ContainsKey(stm) && assigns[stm] == assignVar) { dontMove = true; break; } } if (dontMove) break; } ifThenElse = Util.GetAncestor<AIfThenElseStm>(ifThenElse.Parent()); } //If the assignStm or useStm is inside a while, it could get complicated //if (Util.HasAncestor<AWhileStm>(assignStm) || Util.HasAncestor<AWhileStm>(useStm)) // dontMove = true; } if (useStm != null && dontMove == false && (isLocal || !containsInvokeInPrevStm)) { //Ensure that it is not used twice in this stm FindLvalue finder = new FindLvalue(assignVar, finalTrans.data); useStm.Apply(finder); if (!finder.IsUsedTwice && (isLocal || !finder.HasPrevInvoke)) { PExp rightside; if (assignStm is ALocalDeclStm) { rightside = ((AALocalDecl)((ALocalDeclStm)assignStm).GetLocalDecl()).GetInit(); } else { rightside = ((AAssignmentExp)((AExpStm)assignStm).GetExp()).GetExp(); assignStm.Parent().RemoveChild(assignStm); } if (rightside != null) { finder.Lvalue.Parent().ReplaceBy(rightside); CaseAMethodDecl(node); return; } } } } } if (StatementRemover.Parse(node)) { CaseAMethodDecl(node); return; } firstMethodCall = true; }
public override void OutAMethodDecl(AMethodDecl node) { //If void return is missing, insert it. if (node.GetReturnType() is AVoidType && node.GetBlock() != null) { AABlock block = (AABlock)node.GetBlock(); bool insertReturn = false; while (true) { if (block.GetStatements().Count == 0) { insertReturn = true; break; } PStm lastStm = (PStm)block.GetStatements()[block.GetStatements().Count - 1]; if (lastStm is AVoidReturnStm) break; if (lastStm is ABlockStm) { block = (AABlock)((ABlockStm)block.GetStatements()[block.GetStatements().Count - 1]).GetBlock(); continue; } insertReturn = true; break; } if (insertReturn) { block.GetStatements().Add(new AVoidReturnStm(new TReturn("return", block.GetToken().Line, block.GetToken().Pos))); } } base.OutAMethodDecl(node); }
/* * 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); } } }
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 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); }
public static bool Parse(AMethodDecl method, SharedData data) { RemoveSelfAssignments remover = new RemoveSelfAssignments(data); method.GetBlock().Apply(remover); return remover.changedSomething; }