//----------------------------------------------------------------------------------------------------------------------------------------------------- private bool TryBuildJumpTable(CaseBlock[] caseBlocks, out CaseBlock[] jumpTable, out long adjustment) { jumpTable = null; adjustment = 0; var jumpTableLength = caseBlocks[caseBlocks.Length - 1].Int64 - caseBlocks[0].Int64 + 1; if (jumpTableLength > caseBlocks.Length * 2 + 1 || jumpTableLength > UInt32.MaxValue) { return(false); } jumpTable = new CaseBlock[jumpTableLength]; adjustment = -caseBlocks[0].Int64; var caseIndex = 0; for (int jumpIndex = 0; jumpIndex < jumpTableLength; jumpIndex++) { if (jumpIndex == caseBlocks[caseIndex].Int64 + adjustment) { jumpTable[jumpIndex] = caseBlocks[caseIndex++]; } } return(true); }
public Dictionary <object, CodeBlock> ToDictionary(Executer exec, out CodeBlock _default) { Dictionary <object, CodeBlock> dict = new Dictionary <object, CodeBlock>(); _default = null; for (int index = 0; index < Body.Count; index++) { CaseBlock caseBlock; index = CaseBlock.ParseBlock(index, Body, out caseBlock) - 1; if (caseBlock.Header.Name.EqualsIgnoreCase("DEFAULT")) { _default = caseBlock; } else if (caseBlock.Header.Name.EqualsIgnoreCase("CASE")) { dict.Add( Evaluator.Evaluate(caseBlock.Condition, exec), caseBlock ); } else { throw ThrowHelper.InvalidTypeInExpression(Body[0].Text, "CASE"); } } return(dict); }
public void Equality_Default() { var a = new CaseBlock(); var b = new CaseBlock(); Assert.AreEqual(a, b); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
public void DefaultValues() { var sut = new CaseBlock(); Assert.AreEqual(new UnknownExpression(), sut.Label); Assert.AreEqual(Lists.NewList <IStatement>(), sut.Body); Assert.AreNotEqual(0, sut.GetHashCode()); Assert.AreNotEqual(1, sut.GetHashCode()); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public void Default(Action body) { if (m_Default != null) { throw new InvalidOperationException("Default case was already specified."); } m_Default = new CaseBlock(this, default(T)); m_Default.Do(body); }
public void Equality_DifferentBody() { var a = new CaseBlock { Body = { new ReturnStatement() } }; var b = new CaseBlock(); Assert.AreNotEqual(a, b); Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode()); }
public void Equality_DifferentLabel() { var a = new CaseBlock { Label = Label("a") }; var b = new CaseBlock(); Assert.AreNotEqual(a, b); Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode()); }
public void SettingValues() { var sut = new CaseBlock { Label = Label("a"), Body = { new ReturnStatement() } }; Assert.AreEqual(Label("a"), sut.Label); Assert.AreEqual(Lists.NewList(new ReturnStatement()), sut.Body); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- #region IHapilSwitchSyntax<T> Members public IHapilSwitchCaseSyntax <T> Case(T constantValue) { if (m_CasesByValue.ContainsKey(constantValue)) { throw new ArgumentException("There is already case for specified value", paramName: "constantValue"); } var block = new CaseBlock(this, constantValue); m_CasesByValue.Add(constantValue, block); return(block); }
public override void VisitCFGCaseBlock(CaseBlock x) { VisitCFGBlockInit(x); if (!x.CaseValue.IsOnlyBoundElement) { x.CaseValue.PreBoundStatements.ForEach(Accept); } if (!x.CaseValue.IsEmpty) { Accept(x.CaseValue.BoundElement); } VisitCFGBlockInternal(x); }
// Build a case block statement public static void BuildCaseBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var caseBlock = new CaseBlock(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(caseBlock); // Get the expression being tested against parser.ConsumeParseTree(root, caseBlock.Variable, currentNode.ChildNodes[1]); // Build the expressions in the body of the case block foreach (var e in currentNode.ChildNodes[2].ChildNodes) { parser.ConsumeParseTree(root, caseBlock, e); } }
public void Equality_ReallyTheSame() { var a = new CaseBlock { Label = Label("a"), Body = { new ReturnStatement() } }; var b = new CaseBlock { Label = Label("a"), Body = { new ReturnStatement() } }; Assert.AreEqual(a, b); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
public void AddBlock(CaseBlock <double> caseBlock) { if (caseBlock != null) { if (double.IsNaN(NumericValue)) { throw new SwitchBlockException("An expression was expected but provided in case."); } if (_numericBlocks.Any(cb => cb.Cases.Intersect(caseBlock.Cases).Any())) { var blockFound = _numericBlocks.First(cb => cb.Cases.Intersect(caseBlock.Cases).Any()); var dupCase = blockFound.Cases.Intersect(caseBlock.Cases); throw new SwitchBlockException($"Multiple instances of cases with comparison of values {string.Join(',', dupCase)}."); } _numericBlocks.Add(caseBlock); } }
public void AddBlock(CaseBlock <string> caseBlock) { if (caseBlock != null) { if (string.IsNullOrEmpty(StringValue)) { throw new SwitchBlockException("String literal was expected but not provided in case."); } if (_stringBlocks.Any(cb => cb.Cases.Intersect(caseBlock.Cases).Any())) { var blockFound = _stringBlocks.First(cb => cb.Cases.Intersect(caseBlock.Cases).Any()); var dupCase = blockFound.Cases.Intersect(caseBlock.Cases); throw new SwitchBlockException($"Multiple instances of cases with comparison of values \"{string.Join(',', dupCase)}\"."); } _stringBlocks.Add(caseBlock); } }
public static int ParseBlock(int index, LineCollection all, out CaseBlock caseBlock) { LineCollection blockLines = new LineCollection(); bool isBlock = false; for (; index < all.Count; index++) { if (isBlock) { if (all[index].Name.EqualsIgnoreCase("CASE") || all[index].Name.EqualsIgnoreCase("DEFAULT")) { break; } else { blockLines.Add(all[index]); } } else if (all[index].Name.EqualsIgnoreCase("CASE") || all[index].Name.EqualsIgnoreCase("DEFAULT")) { isBlock = true; blockLines.Add(all[index]); } } if (blockLines.Count > 0) { caseBlock = new CaseBlock(blockLines); } else { caseBlock = null; } return(index); }
private void ReadCase(Switch target) { var scb = new CaseBlock(); BlockBase p; NodeBase[] s; for (; ; ) { var t = Read(); switch (t) { case null: throw Abort("switch: }}}} が必要です。"); case "case": case "default": if (scb.Block != null) { target.Blocks.Add(scb); scb = new CaseBlock(); } if (scb.Case == null) scb.Case = Case.New(target); if (t == "case") { var v = ReadExpression() as NodeBase; if (v == null) throw Abort("case: 値が必要です。"); Check("case", ":"); scb.Case.Values.Add(v); } else Check("default", ":"); break; case "}": if (scb.Block != null) target.Blocks.Add(scb); return; default: Rewind(); if (scb.Case == null) throw Abort("switch: 条件が必要です。"); if (scb.Block == null) scb.Block = Block.New(target); p = parent; parent = target; s = Sentence(); if (s != null) scb.Block.AddSentences(s); parent = p; break; } } }
internal SwitchEdge(BoundBlock source, BoundExpression switchValue, CaseBlock[] caseBlocks, BoundBlock endBlock) : base(source) { Contract.ThrowIfNull(caseBlocks); _switchValue = switchValue; _caseBlocks = caseBlocks; _end = endBlock; Connect(source); }
public override void ExecuteDirective() { var line = Assembler.LineIterator.Current; if (!line.InstructionName.Equals(".switch")) { return; } SwitchContext context = null; CaseBlock <string> stringBlock = null; CaseBlock <double> numericBlock = null; if (Line.OperandHasToken) { if (!Assembler.SymbolManager.SymbolExists(Line.OperandExpression)) { if (Line.Operand.Children[0].Name.Equals("(")) { if (Line.Operand.Children[0].Children.Count > 0 && Line.Operand.Children[0].Children[0].ToString().EnclosedInDoubleQuotes()) { context = new SwitchContext(Line.Operand.Children[0].Children[0].ToString()); } else { context = new SwitchContext(Evaluator.Evaluate(Line.Operand)); } } } else { context = new SwitchContext(Evaluator.Evaluate(Line.Operand)); } } if (context == null) { Assembler.Log.LogEntry(Line, Line.Operand, "Expression must be a valid symbol or constant expression."); return; } Token lastInstruction = null; if (!(line.OperandHasToken && (Assembler.SymbolManager.SymbolExists(line.Operand.Children[0].Children[0].Name) || line.Operand.Children[0].Name.Equals("(")))) { string error; if (!line.OperandHasToken) { error = "Expression must follow \".switch\" directive."; } else { error = "Expression must be a valid symbol or an expression."; } Assembler.Log.LogEntry(line, line.Instruction.Position, error); return; } var defaultIndex = -1; if (!string.IsNullOrEmpty(context.StringValue)) { stringBlock = new CaseBlock <string>(); } else { numericBlock = new CaseBlock <double>(); } while ((line = Assembler.LineIterator.GetNext()) != null && !line.InstructionName.Equals(".endswitch")) { if (!string.IsNullOrEmpty(line.InstructionName)) { lastInstruction = line.Instruction; } if (line.InstructionName.Equals(".case")) { if (defaultIndex > -1) { Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" directive cannot follow a \".default\" directive."); } else if (stringBlock?.FallthroughIndex > -1 || numericBlock?.FallthroughIndex > -1) { Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" directive must follow a \".break\" directive."); } { stringBlock?.Cases.Add(line.Operand.Name); numericBlock?.Cases.Add(Evaluator.Evaluate(line.Operand)); } } else if (line.InstructionName.Equals(".break")) { if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0) { Assembler.Log.LogEntry(line, line.Instruction.Position, "\".break\" directive must follow a \".case\" or \".default\" directive."); } else { context.AddBlock(stringBlock); context.AddBlock(numericBlock); if (stringBlock != null) { stringBlock = new CaseBlock <string>(); } else { numericBlock = new CaseBlock <double>(); } } } else if (line.InstructionName.Equals(".default")) { if (defaultIndex > -1) { Assembler.Log.LogEntry(line, line.Instruction.Position, "There can only be one \".default\" directive in a switch block."); } else { defaultIndex = Assembler.LineIterator.Index; } } else { if (line.Label != null) { Assembler.Log.LogEntry(line, line.Label.Position, "Label cannot be defined inside a switch block."); } if (line.Instruction != null) { if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0) { Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" or \".default\" directive expected"); } else if (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0) { if (stringBlock != null) { stringBlock.FallthroughIndex = Assembler.LineIterator.Index; } if (numericBlock != null) { numericBlock.FallthroughIndex = Assembler.LineIterator.Index; } } } } } if (lastInstruction == null || (line != null && !string.IsNullOrEmpty(lastInstruction.Name) && !lastInstruction.Name.Equals(".break"))) { if (line == null) { line = Line; } Assembler.Log.LogEntry(line, "Switch statement must end with a \".break\" directive."); } else if (line != null) { if (defaultIndex < 0 || !context.AnyCaseDefined()) { if (defaultIndex >= 0) { Assembler.Log.LogEntry(line, line.Instruction, "Only a default case was specified.", false); } else if (!context.AnyCaseDefined()) { Assembler.Log.LogEntry(line, line.Instruction, "Switch statement did not encounter any cases to evaluate."); return; } else { Assembler.Log.LogEntry(line, line.Instruction, "Switch statement does not have a default case.", false); } } int fallthroughIndex = context.GetFallthroughIndex(); if (fallthroughIndex < 0) { fallthroughIndex = defaultIndex; } if (fallthroughIndex > -1) { Assembler.LineIterator.Rewind(fallthroughIndex - 1); } } }
public virtual void VisitCFGCaseBlock(CaseBlock x) { Accept(x.CaseValue); VisitCFGBlockInternal(x); }
public override void ExecuteDirective(RandomAccessIterator <SourceLine> lines) { var line = lines.Current; if (line.Instruction.Name.Equals(".endswitch", Services.StringComparison)) { return; } CaseBlock <string> stringBlock = null; CaseBlock <double> numericBlock = null; SwitchContext context = null; var it = line.Operands.GetIterator(); if (it.MoveNext()) { if (StringHelper.ExpressionIsAString(it, Services)) { context = new SwitchContext(StringHelper.GetString(it, Services)); } else { context = new SwitchContext(Services.Evaluator.Evaluate(it, false)); } if (it.Current != null) { throw new SyntaxException(it.Current, "Unexpected expression."); } } if (context == null) { string error; if (line.Operands.Count == 0) { error = "Expression must follow \".switch\" directive."; } else { error = "Expression must be a valid symbol or an expression."; } Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, error); return; } var defaultIndex = -1; if (!string.IsNullOrEmpty(context.StringValue)) { stringBlock = new CaseBlock <string>(); } else { numericBlock = new CaseBlock <double>(); } while ((line = lines.GetNext()) != null && (line.Instruction == null || !line.Instruction.Name.Equals(".endswitch", Services.StringComparison))) { if (line.Instruction != null) { if (line.Instruction.Name.Equals(".case", Services.StringComparison)) { if (defaultIndex > -1) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "\".case\" directive cannot follow a \".default\" directive."); } else if (stringBlock?.FallthroughIndex > -1 || numericBlock?.FallthroughIndex > -1) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "\".case\" does not fall through."); } else if (line.Operands.Count == 0) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "Expression expected."); } else { var iterator = line.Operands.GetIterator(); if (stringBlock != null) { if (!StringHelper.ExpressionIsAString(iterator, Services)) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Operands[0].Position, "String expression expected."); } else { stringBlock.Cases.Add(StringHelper.GetString(iterator, Services)); } } else { numericBlock?.Cases.Add(Services.Evaluator.Evaluate(iterator)); } if (iterator.Current != null) { throw new SyntaxException(iterator.Current, "Unexpected expression."); } } } else if (Reserved.IsOneOf("BreakContReturn", line.Instruction.Name)) { if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, $"\"{line.Instruction}\" directive must follow a \".case\" or \".default\" directive."); } else { if (line.Instruction.Name.Equals(".return", Services.StringComparison) && (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0)) { if (stringBlock != null) { stringBlock.FallthroughIndex = lines.Index; } if (numericBlock != null) { numericBlock.FallthroughIndex = lines.Index; } } else if (!line.Instruction.Name.Equals(".return", Services.StringComparison) && line.Operands.Count > 0) { throw new SyntaxException(line.Operands[0], "Unexpected expression."); } context.AddBlock(stringBlock); context.AddBlock(numericBlock); Services.SymbolManager.PopScope(); if (stringBlock != null) { stringBlock = new CaseBlock <string>(); } else { numericBlock = new CaseBlock <double>(); } } } else if (line.Instruction.Name.Equals(".default", Services.StringComparison)) { if (line.Operands.Count > 0) { throw new SyntaxException(line.Operands[0], "Unexpected expression."); } if (defaultIndex > -1) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "There can only be one \".default\" directive in a switch block."); } else { defaultIndex = lines.Index + 1; } } else if (line.Label != null) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Label.Position, "Label cannot be defined inside a switch block."); } else { if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "\".case\" or \".default\" directive expected"); } else if (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0) { if (stringBlock != null) { stringBlock.FallthroughIndex = lines.Index; } if (numericBlock != null) { numericBlock.FallthroughIndex = lines.Index; } } } } } if (line != null) { if (defaultIndex < 0 || !context.AnyCaseDefined()) { if (defaultIndex >= 0) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "Only a default case was specified.", false); } else if (!context.AnyCaseDefined()) { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "Switch statement did not encounter any cases to evaluate."); return; } else { Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "Switch statement does not have a default case.", false); } } var fallthroughIndex = context.GetFallthroughIndex(); if (fallthroughIndex < 0) { fallthroughIndex = defaultIndex; } if (fallthroughIndex > -1) { lines.Rewind(fallthroughIndex - 1); } Services.SymbolManager.PushScope(lines.Index.ToString()); } }
public override void VisitCFGCaseBlock(CaseBlock x) { VisitCFGBlockInit(x); Accept(x.CaseValue); VisitCFGBlockInternal(x); }
public SyntaxList <SwitchSectionSyntax> Convert(CaseBlock node) { return(SyntaxFactory.List(node.Clauses.ToCsNodes <SwitchSectionSyntax>())); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public SwitchStatement(IOperand <T> value) { m_Value = value; m_CasesByValue = new SortedDictionary <T, CaseBlock>(); m_Default = null; }