private Shape DetectNewShapeDuringDrag(DragState state, MSet <LLShape> adorners, out bool potentialSelection) { potentialSelection = false; Shape newShape = null; adorners.Add(new LLPolyline(DiagramControl.MouseLineStyle, state.Points.Select(p => p.Point).AsList()) { ZOrder = 0x100 }); if (state.Points.Count == 1) { newShape = new Marker(Control.BoxStyle, state.FirstPoint, Control.MarkerRadius, Control.MarkerType); } else if (state.MousePoints.Count > 1) { #if DEBUG List <Section> ss = BreakIntoSections(state); EliminateTinySections(ss, 10 + (int)(ss.Sum(s => s.LengthPx) * 0.05)); foreach (Section s in ss) { adorners.Add(new LLMarker(new DrawStyle { LineColor = Color.Gainsboro, FillColor = Color.Gray }, s.StartSS, 5, MarkerPolygon.Circle)); } #endif newShape = RecognizeBoxOrLines(state, out potentialSelection); } return(newShape); }
protected LLShapeWidgetControl() { _widgets.Add(new ScrollThumb(this, 0, -1)); _widgets.Add(new ScrollThumb(this, -1, 0)); _widgets.Add(new ScrollThumb(this, 1, 0)); _widgets.Add(new ScrollThumb(this, 0, 1)); _toolButtonLayer = AddLayer(false); RefreshButtonsNonvirtual(); }
private void ShowEraseDuringDrag(DragState state, MSet <LLShape> adorners, IEnumerable <Shape> eraseSet, List <PointT> simplified, bool cancel) { DiagramControl.EraseLineStyle.LineColor = Color.FromArgb(128, Control.BackColor); var eraseLine = new LLPolyline(DiagramControl.EraseLineStyle, simplified); adorners.Add(eraseLine); if (cancel) { eraseLine.Style = Control.LineStyle; Control.BeginRemoveAnimation(adorners); adorners.Clear(); state.IsComplete = true; } else { // Show which shapes are erased by drawing them in the background color foreach (Shape s in eraseSet) { Shape s_ = s.Clone(); s_.Style = (DiagramDrawStyle)s.Style.Clone(); s_.Style.FillColor = s_.Style.LineColor = s_.Style.TextColor = Color.FromArgb(192, Control.BackColor); // avoid an outline artifact, in which color from the edges of the // original shape bleeds through by a variable amount that depends // on subpixel offsets. s_.Style.LineWidth++; s_.AddLLShapesTo(adorners); } } }
/// <summary>Decides whether to use a switch() and for which cases, using /// <see cref="BaseCostForSwitch"/> and <see cref="GetRelativeCostForSwitch"/>.</summary> public virtual bool ShouldGenerateSwitch(IPGTerminalSet[] sets, MSet <int> casesToInclude, bool hasErrorBranch) { // Compute scores IPGTerminalSet covered = EmptySet; int[] score = new int[sets.Length - 1]; // no error branch? then last set must be default for (int i = 0; i < score.Length; i++) { Debug.Assert(sets[i].Subtract(covered).Equals(sets[i])); score[i] = GetRelativeCostForSwitch(sets[i]); } // Consider highest scores first to figure out whether switch is // justified, and which branches should be expressed with "case"s. bool should = false; int switchScore = -BaseCostForSwitch; for (; ;) { int maxIndex = score.IndexOfMax(), maxScore = score[maxIndex]; switchScore += maxScore; if (switchScore > 0) { should = true; } else if (maxScore < 0) { break; } casesToInclude.Add(maxIndex); score[maxIndex] = -1000000; } return(should); }
void TrialAdds(T[] data, int start, int stop, bool randomOrder) { var indexes = GetIndexes(start, stop, randomOrder); int hCount = 0, oCount = 0, oldICount = _iSet.Count; _timer.Restart(); for (int i = 0; i < indexes.Count; i++) { if (_hSet.Add(data[indexes[i]])) { hCount++; } } _hTime += _timer.Restart(); for (int i = 0; i < indexes.Count; i++) { if (_mSet.Add(data[indexes[i]])) { oCount++; } } _mTime += _timer.Restart(); for (int i = 0; i < indexes.Count; i++) { _iSet = _iSet + data[indexes[i]]; } _iTime += _timer.Restart(); Debug.Assert(hCount == oCount); Debug.Assert(hCount == _iSet.Count - oldICount); TallyMemory(); }
public bool DeleteSelected(bool run = true) { if (_partialSelShape == null && _selectedShapes.Count == 0) { return(false); } if (run) { if (_partialSelShape != null) { _selectedShapes.Add(_partialSelShape); } DeleteShapes((Set <Shape>)_selectedShapes); } return(true); }
private void AutoAddBranchForAndPred(ref InternalList <PredictionBranch> children, AndPred andPred, List <KthSet> alts, Set <AndPred> matched, MSet <AndPred> falsified) { if (!falsified.Contains(andPred)) { var innerMatched = matched.With(andPred); var result = new PredictionBranch(new Set <AndPred>().With(andPred), ComputeAssertionTree2(alts, innerMatched)); falsified.Add(andPred); RemoveFalsifiedCases(alts, falsified); children.Add(result); } }
// GENERATED CODE EXAMPLE: The methods in this region generate // the for(;;) loop in this example and everything inside it, except // the calls to Match() which are generated by Visit(TerminalPred). // The generated code uses "goto" and "match" blocks in some cases // to avoid code duplication. This occurs when the matching code // requires multiple statements AND appears more than once in the // prediction tree. Otherwise, matching is done "inline" during // prediction. We generate a for(;;) loop for (...)*, and in certain // cases, we generates a do...while(false) loop for (...)?. // // rule Foo @{ (('a'|'A') 'A')* 'a'..'z' 'a'..'z' }; // public void Foo() // { // int la0, la1; // for (;;) { // la0 = LA(0); // if (la0 == 'a') { // la1 = LA(1); // if (la1 == 'A') // goto match1; // else // break; // } else if (la0 == 'A') // goto match1; // else // break; // match1: // { // Match('A', 'a'); // Match('A'); // } // } // MatchRange('a', 'z'); // MatchRange('a', 'z'); // } private void GenerateCodeForAlts(Alts alts, Dictionary<int, int> timesUsed, PredictionTree tree) { bool needError = LLPG.NeedsErrorBranch(tree, alts); if (!needError && alts.ErrorBranch != null) LLPG.Output(Warning, alts, "The error branch will not be used because the other alternatives are exhaustive (cover all cases)"); bool userDefinedError = needError && alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value; // Generate matching code for each arm. the "string" in each pair // becomes non-null if the matching code for that branch needs to be // split out (separated) from the prediction tree because it appears // multiple times in the tree. The string is the goto-label name. Pair<LNode, string>[] matchingCode = new Pair<LNode, string>[alts.Arms.Count + (userDefinedError ? 1 : 0)]; MSet<int> unreachable = new MSet<int>(); int separateCount = 0; for (int i = 0; i < alts.Arms.Count; i++) { if (!timesUsed.ContainsKey(i)) { unreachable.Add(i); continue; } var codeForThisArm = new WList<LNode>(); VisitWithNewTarget(alts.Arms[i], codeForThisArm); matchingCode[i].A = F.Braces(codeForThisArm.ToVList()); if (timesUsed[i] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) { separateCount++; matchingCode[i].B = alts.Arms[i].ChooseGotoLabel() ?? "match" + (i + 1).ToString(); } } // Add matching code for the error branch, if present. Note: the // default error branch, which is produced by IPGCodeGenHelper. // ErrorBranch() is handled differently: default error code can // differ at each error point in the prediction tree. Therefore // we generate it later, on-demand. if (userDefinedError) { int i = alts.Arms.Count; var errorHandler = new WList<LNode>(); VisitWithNewTarget(alts.ErrorBranch, errorHandler); matchingCode[i].A = F.Braces(errorHandler.ToVList()); if (timesUsed[ErrorAlt] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) { matchingCode[i].B = "error"; separateCount++; } } // Print unreachability warnings if (unreachable.Count == 1) LLPG.Output(Warning, alts, string.Format("Branch {{{0}}} is unreachable.", alts.AltName(unreachable.First()))); else if (unreachable.Count > 1) LLPG.Output(Warning, alts, string.Format("Branches {{{0}}} are unreachable.", unreachable.Select(i => alts.AltName(i)).Join(", "))); if (!timesUsed.ContainsKey(ExitAlt) && alts.Mode != LoopMode.None) LLPG.Output(Warning, alts, "Infinite loop. The exit branch is unreachable."); Symbol loopType = null; // Choose a loop type for (...)* or (...)?: if (alts.Mode == LoopMode.Star) loopType = S.For; else if (alts.Mode == LoopMode.Opt) { if (alts.HasErrorBranch(LLPG) || alts.NonExitDefaultArmRequested()) loopType = S.DoWhile; } // If the code for an arm is nontrivial and appears multiple times // in the prediction table, it will have to be split out into a // labeled block and reached via "goto". I'd rather just do a goto // from inside one "if" statement to inside another, but in C# // (unlike in CIL, and unlike in C) that is prohibited :( DeduplicateLabels(matchingCode); var extraMatching = GenerateExtraMatchingCode(matchingCode, separateCount, ref loopType); if (separateCount != 0) loopType = loopType ?? S.DoWhile; Symbol breakMode = loopType; // used to request a "goto" label in addition to the loop LNode code = GeneratePredictionTreeCode(tree, matchingCode, ref breakMode); // Add break/continue between prediction tree and extra matching code, // if necessary. if (extraMatching.Count != 0 && CodeGenHelperBase.EndMayBeReachable(code)) { loopType = loopType ?? S.DoWhile; extraMatching.Insert(0, GetContinueStmt(loopType)); } if (!extraMatching.IsEmpty) code = LNode.MergeLists(code, F.Braces(extraMatching), S.Braces); if (loopType == S.For) { // (...)* => for (;;) {} code = F.Call(S.For, F.List(), F.Missing, F.List(), code); } else if (loopType == S.DoWhile) { // (...)? becomes "do {...} while(false);" IF the exit branch is NOT the default. // If the exit branch is the default, then no loop and no "break" is needed. code = F.Call(S.DoWhile, code, F.@false); } if (breakMode != loopType && breakMode != null) { // Add "stop:" label (plus extra ";" for C# compatibility, in // case the label ends the block in which it is located.) var stopLabel = F.Call(S.Label, F.Id(breakMode)) .PlusTrailingTrivia(F.Trivia(S.TriviaRawText, ";")); code = LNode.MergeLists(code, stopLabel, S.Braces); } int oldCount = _target.Count; _target.SpliceAdd(code, S.Braces); // Add comment before code if (LLPG.AddComments) { var pos = alts.Basis.Range.Start; var comment = F.Trivia(S.TriviaSLComment, string.Format(" Line {0}: {1}", pos.Line, alts.ToString())); if (_target.Count > oldCount) _target[oldCount] = _target[oldCount].PlusAttr(comment); } }
/// <summary>Decides whether to use a switch() and for which cases, using /// <see cref="BaseCostForSwitch"/> and <see cref="GetRelativeCostForSwitch"/>.</summary> public virtual bool ShouldGenerateSwitch(IPGTerminalSet[] sets, MSet<int> casesToInclude, bool hasErrorBranch) { // Compute scores IPGTerminalSet covered = EmptySet; int[] score = new int[sets.Length - 1]; // no error branch? then last set must be default for (int i = 0; i < score.Length; i++) { Debug.Assert(sets[i].Subtract(covered).Equals(sets[i])); score[i] = GetRelativeCostForSwitch(sets[i]); } // Consider highest scores first to figure out whether switch is // justified, and which branches should be expressed with "case"s. bool should = false; int switchScore = -BaseCostForSwitch; for (; ; ) { int maxIndex = score.IndexOfMax(), maxScore = score[maxIndex]; switchScore += maxScore; if (switchScore > 0) should = true; else if (maxScore < 0) break; casesToInclude.Add(maxIndex); score[maxIndex] = -1000000; } return should; }
// GENERATED CODE EXAMPLE: The methods in this region generate // the for(;;) loop in this example and everything inside it, except // the calls to Match() which are generated by Visit(TerminalPred). // The generated code uses "goto" and "match" blocks in some cases // to avoid code duplication. This occurs when the matching code // requires multiple statements AND appears more than once in the // prediction tree. Otherwise, matching is done "inline" during // prediction. We generate a for(;;) loop for (...)*, and in certain // cases, we generates a do...while(false) loop for (...)?. // // rule Foo @{ (('a'|'A') 'A')* 'a'..'z' 'a'..'z' }; // public void Foo() // { // int la0, la1; // for (;;) { // la0 = LA(0); // if (la0 == 'a') { // la1 = LA(1); // if (la1 == 'A') // goto match1; // else // break; // } else if (la0 == 'A') // goto match1; // else // break; // match1: // { // Match('A', 'a'); // Match('A'); // } // } // MatchRange('a', 'z'); // MatchRange('a', 'z'); // } private void GenerateCodeForAlts(Alts alts, Dictionary <int, int> timesUsed, PredictionTree tree) { bool needError = LLPG.NeedsErrorBranch(tree, alts); if (!needError && alts.ErrorBranch != null) { LLPG.Output(Warning, alts, "The error branch will not be used because the other alternatives are exhaustive (cover all cases)"); } bool userDefinedError = needError && !_recognizerMode && alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value; // Generate matching code for each arm. the "string" in each pair // becomes non-null if the matching code for that branch needs to be // split out (separated) from the prediction tree because it appears // multiple times in the tree. The string is the goto-label name. Pair <LNode, string>[] matchingCode = new Pair <LNode, string> [alts.Arms.Count + (userDefinedError ? 1: 0)]; MSet <int> unreachable = new MSet <int>(); int separateCount = 0; for (int i = 0; i < alts.Arms.Count; i++) { if (!timesUsed.ContainsKey(i)) { unreachable.Add(i); continue; } var codeForThisArm = new WList <LNode>(); VisitWithNewTarget(alts.Arms[i], codeForThisArm); matchingCode[i].A = F.Braces(codeForThisArm.ToVList()); if (timesUsed[i] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) { separateCount++; matchingCode[i].B = alts.Arms[i].ChooseGotoLabel() ?? "match" + (i + 1).ToString(); } } // Add matching code for the error branch, if present. Note: the // default error branch, which is produced by IPGCodeGenHelper. // ErrorBranch() is handled differently: default error code can // differ at each error point in the prediction tree. Therefore // we generate it later, on-demand. if (userDefinedError) { int i = alts.Arms.Count; var errorHandler = new WList <LNode>(); VisitWithNewTarget(alts.ErrorBranch, errorHandler); matchingCode[i].A = F.Braces(errorHandler.ToVList()); if (timesUsed[ErrorAlt] > 1 && !SimpleEnoughToRepeat(matchingCode[i].A)) { matchingCode[i].B = "error"; separateCount++; } } // Print unreachability warnings if (unreachable.Count == 1) { LLPG.Output(Warning, alts, string.Format("Branch {{{0}}} is unreachable.", alts.AltName(unreachable.First()))); } else if (unreachable.Count > 1) { LLPG.Output(Warning, alts, string.Format("Branches {{{0}}} are unreachable.", unreachable.Select(i => alts.AltName(i)).Join(", "))); } if (!timesUsed.ContainsKey(ExitAlt) && alts.Mode != LoopMode.None) { LLPG.Output(Warning, alts, "Infinite loop. The exit branch is unreachable."); } Symbol loopType = null; // Choose a loop type for (...)* or (...)?: if (alts.Mode == LoopMode.Star) { loopType = S.For; } else if (alts.Mode == LoopMode.Opt) { if (alts.HasErrorBranch(LLPG) || alts.NonExitDefaultArmRequested()) { loopType = S.DoWhile; } } // If the code for an arm is nontrivial and appears multiple times // in the prediction table, it will have to be split out into a // labeled block and reached via "goto". I'd rather just do a goto // from inside one "if" statement to inside another, but in C# // (unlike in CIL, and unlike in C) that is prohibited :( DeduplicateLabels(matchingCode); var extraMatching = GenerateExtraMatchingCode(matchingCode, separateCount, ref loopType); if (separateCount != 0) { loopType = loopType ?? S.DoWhile; } Symbol breakMode = loopType; // used to request a "goto" label in addition to the loop LNode code = GeneratePredictionTreeCode(tree, matchingCode, ref breakMode); // Add break/continue between prediction tree and extra matching code, // if necessary. if (extraMatching.Count != 0 && CodeGenHelperBase.EndMayBeReachable(code)) { loopType = loopType ?? S.DoWhile; extraMatching.Insert(0, GetContinueStmt(loopType)); } if (!extraMatching.IsEmpty) { code = LNode.MergeLists(code, F.Braces(extraMatching), S.Braces); } if (loopType == S.For) { // (...)* => for (;;) {} code = F.Call(S.For, F.List(), F.Missing, F.List(), code); } else if (loopType == S.DoWhile) { // (...)? becomes "do {...} while(false);" IF the exit branch is NOT the default. // If the exit branch is the default, then no loop and no "break" is needed. code = F.Call(S.DoWhile, code, F.@false); } if (breakMode != loopType && breakMode != null) { // Add "stop:" label (plus extra ";" for C# compatibility, in // case the label ends the block in which it is located.) var stopLabel = F.Call(S.Label, F.Id(breakMode)) .PlusTrailingTrivia(F.Trivia(S.TriviaRawText, ";")); code = LNode.MergeLists(code, stopLabel, S.Braces); } int oldCount = _target.Count; _target.SpliceAdd(code, S.Braces); // Add comment before code if (LLPG.AddComments) { var pos = alts.Basis.Range.Start; var comment = F.Trivia(S.TriviaSLComment, string.Format(" Line {0}: {1}", pos.Line, alts.ToString())); if (_target.Count > oldCount) { _target[oldCount] = _target[oldCount].PlusAttr(comment); } } }
private void AutoAddBranchForAndPred(ref InternalList<PredictionBranch> children, AndPred andPred, List<KthSet> alts, Set<AndPred> matched, MSet<AndPred> falsified) { if (!falsified.Contains(andPred)) { var innerMatched = matched.With(andPred); var result = new PredictionBranch(new Set<AndPred>().With(andPred), ComputeAssertionTree2(alts, innerMatched)); falsified.Add(andPred); RemoveFalsifiedCases(alts, falsified); children.Add(result); } }
private Shape DetectNewShapeDuringDrag(DragState state, MSet<LLShape> adorners, out bool potentialSelection) { potentialSelection = false; Shape newShape = null; adorners.Add(new LLPolyline(DiagramControl.MouseLineStyle, state.Points.Select(p => p.Point).AsList()) { ZOrder = 0x100 }); if (state.Points.Count == 1) { newShape = new Marker(Control.BoxStyle, state.FirstPoint, Control.MarkerRadius, Control.MarkerType); } else if (state.MousePoints.Count > 1) { #if DEBUG List<Section> ss = BreakIntoSections(state); EliminateTinySections(ss, 10 + (int)(ss.Sum(s => s.LengthPx) * 0.05)); foreach (Section s in ss) adorners.Add(new LLMarker(new DrawStyle { LineColor = Color.Gainsboro, FillColor = Color.Gray }, s.StartSS, 5, MarkerPolygon.Circle)); #endif newShape = RecognizeBoxOrLines(state, out potentialSelection); } return newShape; }
private void ShowEraseDuringDrag(DragState state, MSet<LLShape> adorners, IEnumerable<Shape> eraseSet, List<PointT> simplified, bool cancel) { DiagramControl.EraseLineStyle.LineColor = Color.FromArgb(128, Control.BackColor); var eraseLine = new LLPolyline(DiagramControl.EraseLineStyle, simplified); adorners.Add(eraseLine); if (cancel) { eraseLine.Style = Control.LineStyle; Control.BeginRemoveAnimation(adorners); adorners.Clear(); state.IsComplete = true; } else { // Show which shapes are erased by drawing them in the background color foreach (Shape s in eraseSet) { Shape s_ = s.Clone(); s_.Style = (DiagramDrawStyle)s.Style.Clone(); s_.Style.FillColor = s_.Style.LineColor = s_.Style.TextColor = Color.FromArgb(192, Control.BackColor); // avoid an outline artifact, in which color from the edges of the // original shape bleeds through by a variable amount that depends // on subpixel offsets. s_.Style.LineWidth++; s_.AddLLShapesTo(adorners); } } }