summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Absy.ssc3244
-rw-r--r--Source/Core/AbsyCmd.ssc2472
-rw-r--r--Source/Core/AbsyExpr.ssc2430
-rw-r--r--Source/Core/AbsyQuant.ssc860
-rw-r--r--Source/Core/AbsyType.ssc2857
-rw-r--r--Source/Core/AssemblyInfo.ssc4
-rw-r--r--Source/Core/CommandLineOptions.ssc2109
-rw-r--r--Source/Core/Core.sscproj232
-rw-r--r--Source/Core/DeadVarElim.ssc1234
-rw-r--r--Source/Core/Duplicator.ssc408
-rw-r--r--Source/Core/GraphAlgorithms.ssc175
-rw-r--r--Source/Core/Inline.ssc689
-rw-r--r--Source/Core/LambdaHelper.ssc161
-rw-r--r--Source/Core/LoopUnroll.ssc224
-rw-r--r--Source/Core/OOLongUtil.ssc174
-rw-r--r--Source/Core/Parser.ssc2168
-rw-r--r--Source/Core/ParserHelper.ssc188
-rw-r--r--Source/Core/PureCollections.ssc785
-rw-r--r--Source/Core/ResolutionContext.ssc539
-rw-r--r--Source/Core/Scanner.ssc726
-rw-r--r--Source/Core/StandardVisitor.ssc503
-rw-r--r--Source/Core/TypeAmbiguitySeeker.ssc95
-rw-r--r--Source/Core/Util.ssc481
-rw-r--r--Source/Core/VCExp.ssc191
-rw-r--r--Source/Core/Xml.ssc291
25 files changed, 0 insertions, 23240 deletions
diff --git a/Source/Core/Absy.ssc b/Source/Core/Absy.ssc
deleted file mode 100644
index 4d0113ee..00000000
--- a/Source/Core/Absy.ssc
+++ /dev/null
@@ -1,3244 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-namespace Microsoft.Boogie.AbstractInterpretation
-{
- using System.Diagnostics;
- using CCI = System.Compiler;
- using System.Collections;
- using AI = Microsoft.AbstractInterpretationFramework;
-
- public class CallSite
- {
- public readonly Implementation! Impl;
- public readonly Block! Block;
- public readonly int Statement; // invariant: Block[Statement] is CallCmd
- public readonly AI.Lattice.Element! KnownBeforeCall;
- public readonly ProcedureSummaryEntry! SummaryEntry;
-
- public CallSite (Implementation! impl, Block! b, int stmt, AI.Lattice.Element! e, ProcedureSummaryEntry! summaryEntry)
- {
- this.Impl = impl;
- this.Block = b;
- this.Statement = stmt;
- this.KnownBeforeCall = e;
- this.SummaryEntry = summaryEntry;
- }
- }
-
- public class ProcedureSummaryEntry
- {
- public AI.Lattice! Lattice;
- public AI.Lattice.Element! OnEntry;
- public AI.Lattice.Element! OnExit;
- public CCI.IMutableSet/*<CallSite>*/! ReturnPoints; // whenever OnExit changes, we start analysis again at all the ReturnPoints
-
- public ProcedureSummaryEntry (AI.Lattice! lattice, AI.Lattice.Element! onEntry)
- {
- this.Lattice = lattice;
- this.OnEntry = onEntry;
- this.OnExit = lattice.Bottom;
- this.ReturnPoints = new CCI.HashSet();
- // base();
- }
-
- } // class
-
- public class ProcedureSummary : ArrayList/*<ProcedureSummaryEntry>*/
- {
- invariant !IsReadOnly && !IsFixedSize;
-
- public new ProcedureSummaryEntry! this [int i]
- {
- get
- requires 0 <= i && i < Count;
- { return (ProcedureSummaryEntry!) base[i]; }
- }
-
- } // class
-} // namespace
-
-
-namespace Microsoft.Boogie
-{
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.Contracts;
- using Graphing;
-
-
- public abstract class Absy
- {
- public IToken! tok;
- private int uniqueId;
-
- public int Line { get { return tok != null ? tok.line : -1; } }
- public int Col { get { return tok != null ? tok.col : -1; } }
-
- public Absy (IToken! tok)
- {
- this.tok = tok;
- this.uniqueId = AbsyNodeCount++;
- // base();
- }
-
- private static int AbsyNodeCount = 0;
-
- // We uniquely number every AST node to make them
- // suitable for our implementation of functional maps.
- //
- public int UniqueId { get { return this.uniqueId; } }
-
- private const int indent_size = 2;
- protected static string Indent (int level)
- {
- return new string(' ', (indent_size * level));
- }
-
- public abstract void Resolve (ResolutionContext! rc);
-
- /// <summary>
- /// Requires the object to have been successfully resolved.
- /// </summary>
- /// <param name="tc"></param>
- public abstract void Typecheck (TypecheckingContext! tc);
- /// <summary>
- /// Intorduced this so the uniqueId is not the same on a cloned object.
- /// </summary>
- /// <param name="tc"></param>
- public virtual Absy! Clone()
- {
- Absy! result = (Absy!) this.MemberwiseClone();
- result.uniqueId = AbsyNodeCount++; // BUGBUG??
- return result;
- }
-
- public virtual Absy! StdDispatch(StandardVisitor! visitor)
- {
- System.Diagnostics.Debug.Fail("Unknown Absy node type: " + this.GetType());
- throw new System.NotImplementedException();
- }
- }
-
- // TODO: Ideally, this would use generics.
- public interface IPotentialErrorNode
- {
- object ErrorData { get; set; }
- }
-
- public class Program : Absy
- {
- [Rep]
- public List<Declaration!>! TopLevelDeclarations;
-
- public Program()
- : base(Token.NoToken)
- {
- this.TopLevelDeclarations = new List<Declaration!>();
- // base(Token.NoToken);
- }
-
- public void Emit (TokenTextWriter! stream)
- {
- stream.SetToken(this);
- Emitter.Declarations(this.TopLevelDeclarations, stream);
- }
- /// <summary>
- /// Returns the number of name resolution errors.
- /// </summary>
- /// <returns></returns>
- public int Resolve ()
- {
- return Resolve((IErrorSink) null);
- }
-
- public int Resolve (IErrorSink errorSink)
- {
- ResolutionContext rc = new ResolutionContext(errorSink);
- Resolve(rc);
- return rc.ErrorCount;
- }
-
- public override void Resolve (ResolutionContext! rc)
- {
- Helpers.ExtraTraceInformation("Starting resolution");
-
- foreach (Declaration d in TopLevelDeclarations) {
- d.Register(rc);
- }
-
- ResolveTypes(rc);
-
- List<Declaration!> prunedTopLevelDecls = CommandLineOptions.Clo.OverlookBoogieTypeErrors ? new List<Declaration!>() : null;
-
- foreach (Declaration d in TopLevelDeclarations) {
- // resolve all the non-type-declarations
- if (d is TypeCtorDecl || d is TypeSynonymDecl) {
- if (prunedTopLevelDecls != null)
- prunedTopLevelDecls.Add(d);
- } else {
- int e = rc.ErrorCount;
- d.Resolve(rc);
- if (prunedTopLevelDecls != null) {
- if (rc.ErrorCount != e && d is Implementation) {
- // ignore this implementation
- System.Console.WriteLine("Warning: Ignoring implementation {0} because of translation resolution errors", ((Implementation)d).Name);
- rc.ErrorCount = e;
- } else {
- prunedTopLevelDecls.Add(d);
- }
- }
- }
- }
- if (prunedTopLevelDecls != null) {
- TopLevelDeclarations = prunedTopLevelDecls;
- }
-
- foreach (Declaration d in TopLevelDeclarations) {
- Variable v = d as Variable;
- if (v != null) {
- v.ResolveWhere(rc);
- }
- }
- }
-
-
- private void ResolveTypes (ResolutionContext! rc) {
- // first resolve type constructors
- foreach (Declaration d in TopLevelDeclarations) {
- if (d is TypeCtorDecl)
- d.Resolve(rc);
- }
-
- // collect type synonym declarations
- List<TypeSynonymDecl!>! synonymDecls = new List<TypeSynonymDecl!> ();
- foreach (Declaration d in TopLevelDeclarations) {
- if (d is TypeSynonymDecl)
- synonymDecls.Add((TypeSynonymDecl)d);
- }
-
- // then resolve the type synonyms by a simple
- // fixed-point iteration
- TypeSynonymDecl.ResolveTypeSynonyms(synonymDecls, rc);
- }
-
-
- public int Typecheck ()
- {
- return this.Typecheck((IErrorSink) null);
- }
-
- public int Typecheck (IErrorSink errorSink)
- {
- TypecheckingContext tc = new TypecheckingContext(errorSink);
- Typecheck(tc);
- return tc.ErrorCount;
- }
-
- public override void Typecheck (TypecheckingContext! tc)
- {
- Helpers.ExtraTraceInformation("Starting typechecking");
-
- int oldErrorCount = tc.ErrorCount;
- foreach (Declaration d in TopLevelDeclarations) {
- d.Typecheck(tc);
- }
-
- if (oldErrorCount == tc.ErrorCount) {
- // check whether any type proxies have remained uninstantiated
- TypeAmbiguitySeeker! seeker = new TypeAmbiguitySeeker (tc);
- foreach (Declaration d in TopLevelDeclarations) {
- seeker.Visit(d);
- }
- }
-
- AxiomExpander expander = new AxiomExpander(this, tc);
- expander.CollectExpansions();
- }
-
- public void ComputeStronglyConnectedComponents()
- {
- foreach(Declaration d in this.TopLevelDeclarations) {
- d.ComputeStronglyConnectedComponents();
- }
- }
-
- public void InstrumentWithInvariants ()
- {
- foreach (Declaration d in this.TopLevelDeclarations) {
- d.InstrumentWithInvariants();
- }
- }
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- public void ResetAbstractInterpretationState()
- {
- foreach(Declaration d in this.TopLevelDeclarations) {
- d.ResetAbstractInterpretationState();
- }
- }
-
- public void UnrollLoops(int n)
- requires 0 <= n;
- {
- foreach (Declaration d in this.TopLevelDeclarations) {
- Implementation impl = d as Implementation;
- if (impl != null && impl.Blocks != null && impl.Blocks.Count > 0) {
- expose (impl) {
- Block start = impl.Blocks[0];
- assume start != null;
- assume start.IsConsistent;
- impl.Blocks = LoopUnroll.UnrollLoops(start, n);
- }
- }
- }
- }
-
- void CreateProceduresForLoops(Implementation! impl, Graph<Block!>! g, List<Implementation!>! loopImpls)
- {
- // Enumerate the headers
- // for each header h:
- // create implementation p_h with
- // inputs = inputs, outputs, and locals of impl
- // outputs = outputs and locals of impl
- // locals = empty set
- // add call o := p_h(i) at the beginning of the header block
- // break the back edges whose target is h
- // Enumerate the headers again to create the bodies of p_h
- // for each header h:
- // compute the loop corresponding to h
- // make copies of all blocks in the loop for h
- // delete all target edges that do not go to a block in the loop
- // create a new entry block and a new return block
- // add edges from entry block to the loop header and the return block
- // add calls o := p_h(i) at the end of the blocks that are sources of back edges
- Dictionary<Block!, string!>! loopHeaderToName = new Dictionary<Block!, string!>();
- Dictionary<Block!, VariableSeq!>! loopHeaderToInputs = new Dictionary<Block!, VariableSeq!>();
- Dictionary<Block!, VariableSeq!>! loopHeaderToOutputs = new Dictionary<Block!, VariableSeq!>();
- Dictionary<Block!, Hashtable!>! loopHeaderToSubstMap = new Dictionary<Block!, Hashtable!>();
- Dictionary<Block!, Procedure!>! loopHeaderToLoopProc = new Dictionary<Block!, Procedure!>();
- Dictionary<Block!, CallCmd!>! loopHeaderToCallCmd = new Dictionary<Block!, CallCmd!>();
- foreach (Block! header in g.Headers)
- {
- Contract.Assert(header != null);
- string name = header.ToString();
- loopHeaderToName[header] = name;
- VariableSeq inputs = new VariableSeq();
- VariableSeq outputs = new VariableSeq();
- ExprSeq callInputs = new ExprSeq();
- IdentifierExprSeq callOutputs = new IdentifierExprSeq();
- Hashtable substMap = new Hashtable(); // Variable -> IdentifierExpr
-
- foreach (Variable! v in impl.InParams)
- {
- callInputs.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
- inputs.Add(f);
- substMap[v] = new IdentifierExpr(Token.NoToken, f);
- }
- foreach (Variable! v in impl.OutParams)
- {
- callInputs.Add(new IdentifierExpr(Token.NoToken, v));
- inputs.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true));
- callOutputs.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
- outputs.Add(f);
- substMap[v] = new IdentifierExpr(Token.NoToken, f);
- }
- foreach (Variable! v in impl.LocVars)
- {
- callInputs.Add(new IdentifierExpr(Token.NoToken, v));
- inputs.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true));
- callOutputs.Add(new IdentifierExpr(Token.NoToken, v));
- Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
- outputs.Add(f);
- substMap[v] = new IdentifierExpr(Token.NoToken, f);
- }
- VariableSeq! targets = new VariableSeq();
- foreach (Block! b in g.BackEdgeNodes(header))
- {
- foreach (Block! block in g.NaturalLoops(header, b))
- {
- foreach (Cmd! cmd in block.Cmds)
- {
- cmd.AddAssignedVariables(targets);
- }
- }
- }
- IdentifierExprSeq! globalMods = new IdentifierExprSeq();
- Set globalModsSet = new Set();
- foreach (Variable! v in targets)
- {
- if (!(v is GlobalVariable)) continue;
- if (globalModsSet.Contains(v)) continue;
- globalModsSet.Add(v);
- globalMods.Add(new IdentifierExpr(Token.NoToken, v));
- }
- loopHeaderToInputs[header] = inputs;
- loopHeaderToOutputs[header] = outputs;
- loopHeaderToSubstMap[header] = substMap;
- Procedure! proc =
- new Procedure(Token.NoToken, "loop_" + header.ToString(),
- new TypeVariableSeq(), inputs, outputs,
- new RequiresSeq(), globalMods, new EnsuresSeq());
- if (CommandLineOptions.Clo.LazyInlining > 0 || CommandLineOptions.Clo.StratifiedInlining > 0)
- {
- proc.AddAttribute("inline", Expr.Literal(1));
- }
- loopHeaderToLoopProc[header] = proc;
- CallCmd callCmd = new CallCmd(Token.NoToken, name, callInputs, callOutputs);
- callCmd.Proc = proc;
- loopHeaderToCallCmd[header] = callCmd;
- }
-
- foreach (Block! header in g.Headers)
- {
- Procedure loopProc = loopHeaderToLoopProc[header];
- Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
- CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me
- VariableSeq inputs = loopHeaderToInputs[header];
- VariableSeq outputs = loopHeaderToOutputs[header];
- foreach (Block! source in g.BackEdgeNodes(header))
- {
- foreach (Block! block in g.NaturalLoops(header, source))
- {
- if (blockMap.ContainsKey(block)) continue;
- Block newBlock = new Block();
- newBlock.Label = block.Label;
- newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
- blockMap[block] = newBlock;
- }
- string callee = loopHeaderToName[header];
- ExprSeq ins = new ExprSeq();
- IdentifierExprSeq outs = new IdentifierExprSeq();
- for (int i = 0; i < impl.InParams.Length; i++)
- {
- ins.Add(new IdentifierExpr(Token.NoToken, (!) inputs[i]));
- }
- foreach (Variable! v in outputs)
- {
- ins.Add(new IdentifierExpr(Token.NoToken, v));
- outs.Add(new IdentifierExpr(Token.NoToken, v));
- }
- CallCmd callCmd = new CallCmd(Token.NoToken, callee, ins, outs);
- callCmd.Proc = loopProc;
- Block! block1 = new Block(Token.NoToken, source.Label + "_dummy",
- new CmdSeq(new AssumeCmd(Token.NoToken, Expr.False)), new ReturnCmd(Token.NoToken));
- Block! block2 = new Block(Token.NoToken, block1.Label,
- new CmdSeq(callCmd), new ReturnCmd(Token.NoToken));
- impl.Blocks.Add(block1);
-
- GotoCmd gotoCmd = source.TransferCmd as GotoCmd;
- assert gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Length >= 1;
- StringSeq! newLabels = new StringSeq();
- BlockSeq! newTargets = new BlockSeq();
- for (int i = 0; i < gotoCmd.labelTargets.Length; i++)
- {
- if (gotoCmd.labelTargets[i] == header) continue;
- newTargets.Add(gotoCmd.labelTargets[i]);
- newLabels.Add(gotoCmd.labelNames[i]);
- }
- newTargets.Add(block1);
- newLabels.Add(block1.Label);
- gotoCmd.labelNames = newLabels;
- gotoCmd.labelTargets = newTargets;
-
- blockMap[block1] = block2;
- }
- List<Block!>! blocks = new List<Block!>();
- Block exit = new Block(Token.NoToken, "exit", new CmdSeq(), new ReturnCmd(Token.NoToken));
- GotoCmd cmd = new GotoCmd(Token.NoToken,
- new StringSeq(((!)blockMap[header]).Label, exit.Label),
- new BlockSeq(blockMap[header], exit));
-
- Debug.Assert(outputs.Length + impl.InParams.Length == inputs.Length);
- List<AssignLhs!>! lhss = new List<AssignLhs!>();
- List<Expr!>! rhss = new List<Expr!>();
- for (int i = impl.InParams.Length; i < inputs.Length; i++)
- {
- Variable! inv = (!)inputs[i];
- Variable! outv = (!)outputs[i - impl.InParams.Length];
- AssignLhs lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, outv));
- Expr rhs = new IdentifierExpr(Token.NoToken, inv);
- lhss.Add(lhs);
- rhss.Add(rhs);
- }
- AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss);
- Block entry = new Block(Token.NoToken, "entry", new CmdSeq(assignCmd), cmd);
- blocks.Add(entry);
- foreach (Block! block in blockMap.Keys)
- {
- Block! newBlock = (!) blockMap[block];
- GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
- if (gotoCmd == null)
- {
- newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- }
- else
- {
- assume gotoCmd.labelNames != null && gotoCmd.labelTargets != null;
- StringSeq newLabels = new StringSeq();
- BlockSeq newTargets = new BlockSeq();
- for (int i = 0; i < gotoCmd.labelTargets.Length; i++)
- {
- Block target = gotoCmd.labelTargets[i];
- if (blockMap.ContainsKey(target))
- {
- newLabels.Add(gotoCmd.labelNames[i]);
- newTargets.Add(blockMap[target]);
- }
- }
- if (newTargets.Length == 0)
- {
- newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
- newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- }
- else
- {
- newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets);
- }
- }
- blocks.Add(newBlock);
- }
- blocks.Add(exit);
- Implementation loopImpl =
- new Implementation(Token.NoToken, loopProc.Name,
- new TypeVariableSeq(), inputs, outputs, new VariableSeq(), blocks);
- loopImpl.Proc = loopProc;
- loopImpls.Add(loopImpl);
-
- // Finally, add call to the loop in the containing procedure
- CmdSeq cmdSeq = new CmdSeq();
- cmdSeq.Add(loopHeaderToCallCmd[header]);
- cmdSeq.AddRange(header.Cmds);
- header.Cmds = cmdSeq;
- }
- }
-
- public static Graph<Block!>! GraphFromImpl(Implementation! impl) {
- Contract.Ensures(Contract.Result<Graph<Block>>() != null);
-
- Graph<Block!> g = new Graph<Block!>();
- g.AddSource(impl.Blocks[0]); // there is always at least one node in the graph
- foreach (Block b in impl.Blocks) {
- Contract.Assert(b != null);
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null) {
- foreach (Block! dest in (!)gtc.labelTargets) {
- g.AddEdge(b, dest);
- }
- }
- }
- return g;
- }
-
- public void ExtractLoops()
- {
- List<Implementation!>! loopImpls = new List<Implementation!>();
- foreach (Declaration d in this.TopLevelDeclarations) {
- Implementation impl = d as Implementation;
- if (impl != null && impl.Blocks != null && impl.Blocks.Count > 0) {
- Graph<Block!>! g = GraphFromImpl(impl);
- g.ComputeLoops();
- if (!g.Reducible)
- {
- throw new Exception("Irreducible flow graphs are unsupported.");
- }
- CreateProceduresForLoops(impl, g, loopImpls);
- }
- }
- foreach (Implementation! loopImpl in loopImpls)
- {
- TopLevelDeclarations.Add(loopImpl);
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitProgram(this);
- }
-
- private List<GlobalVariable!> globals = null;
- public List<GlobalVariable!>! GlobalVariables()
- {
- if (globals != null) return globals;
- globals = new List<GlobalVariable!>();
- foreach (Declaration d in TopLevelDeclarations) {
- GlobalVariable gvar = d as GlobalVariable;
- if (gvar != null) globals.Add(gvar);
- }
- return globals;
- }
- }
-
- //---------------------------------------------------------------------
- // Declarations
-
- public abstract class Declaration : Absy
- {
- public QKeyValue Attributes;
-
- public Declaration(IToken! tok)
- : base(tok)
- {
- }
-
- protected void EmitAttributes(TokenTextWriter! stream)
- {
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- }
-
- protected void ResolveAttributes(ResolutionContext! rc)
- {
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- }
-
- protected void TypecheckAttributes(TypecheckingContext! rc)
- {
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(rc);
- }
- }
-
- // Look for {:name true} or {:name false} in list of attributes. Return result in 'result'
- // (which is not touched if there is no attribute specified).
- //
- // Returns false is there was an error processing the flag, true otherwise.
- public bool CheckBooleanAttribute(string! name, ref bool result)
- {
- Expr? expr = FindExprAttribute(name);
- if (expr != null) {
- if (expr is LiteralExpr && ((LiteralExpr)expr).isBool) {
- result = ((LiteralExpr)expr).asBool;
- } else {
- return false;
- }
- }
- return true;
- }
-
- // Look for {:name expr} in list of attributes.
- public Expr? FindExprAttribute(string! name)
- {
- Expr? res = null;
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
- res = (Expr)kv.Params[0];
- }
- }
- }
- return res;
- }
-
- // Look for {:name string} in list of attributes.
- public string? FindStringAttribute(string! name)
- {
- return QKeyValue.FindStringAttribute(this.Attributes, name);
- }
-
- // Look for {:name N} or {:name N} in list of attributes. Return result in 'result'
- // (which is not touched if there is no attribute specified).
- //
- // Returns false is there was an error processing the flag, true otherwise.
- public bool CheckIntAttribute(string! name, ref int result)
- {
- Expr? expr = FindExprAttribute(name);
- if (expr != null) {
- if (expr is LiteralExpr && ((LiteralExpr)expr).isBigNum) {
- result = ((LiteralExpr)expr).asBigNum.ToInt;
- } else {
- return false;
- }
- }
- return true;
- }
-
- public void AddAttribute(string! name, object! val)
- {
- QKeyValue kv;
- for (kv = this.Attributes; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- kv.Params.Add(val);
- break;
- }
- }
- if (kv == null) {
- Attributes = new QKeyValue(tok, name, new List<object!>(new object![] { val }), Attributes);
- }
- }
-
- public abstract void Emit(TokenTextWriter! stream, int level);
- public abstract void Register(ResolutionContext! rc);
-
- /// <summary>
- /// Compute the strongly connected components of the declaration.
- /// By default, it does nothing
- /// </summary>
- public virtual void ComputeStronglyConnectedComponents() { /* Does nothing */}
-
- /// <summary>
- /// This method inserts the abstract-interpretation-inferred invariants
- /// as assume (or possibly assert) statements in the statement sequences of
- /// each block.
- /// </summary>
- public virtual void InstrumentWithInvariants () {}
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- public virtual void ResetAbstractInterpretationState() { /* does nothing */ }
- }
-
- public class Axiom : Declaration
- {
- public Expr! Expr;
- public string? Comment;
-
- public Axiom(IToken! tok, Expr! expr)
- {
- this(tok, expr, null);
- }
-
- public Axiom(IToken! tok, Expr! expr, string? comment)
- : base(tok)
- {
- Expr = expr;
- Comment = comment;
- // base(tok);
- }
-
- public Axiom(IToken! tok, Expr! expr, string? comment, QKeyValue kv)
- {
- this(tok, expr, comment);
- this.Attributes = kv;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "axiom ");
- EmitAttributes(stream);
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext! rc)
- {
- // nothing to register
- }
- public override void Resolve(ResolutionContext! rc)
- {
- ResolveAttributes(rc);
- rc.StateMode = ResolutionContext.State.StateLess;
- Expr.Resolve(rc);
- rc.StateMode = ResolutionContext.State.Single;
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(tc);
- Expr.Typecheck(tc);
- assert Expr.Type != null; // follows from postcondition of Expr.Typecheck
- if (! Expr.Type.Unify(Type.Bool))
- {
- tc.Error(this, "axioms must be of type bool");
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAxiom(this);
- }
- }
-
- public abstract class NamedDeclaration : Declaration
- {
- private string! name;
- public string! Name
- {
- get
- {
- return this.name;
- }
- set
- {
- this.name = value;
- }
- }
-
-
- public NamedDeclaration(IToken! tok, string! name)
- : base(tok)
- {
- this.name = name;
- // base(tok);
- }
- [Pure]
- public override string! ToString()
- {
- return (!) Name;
- }
- }
-
- public class TypeCtorDecl : NamedDeclaration
- {
- public readonly int Arity;
-
- public TypeCtorDecl(IToken! tok, string! name, int Arity)
- : base(tok, name)
- {
- this.Arity = Arity;
- }
- public TypeCtorDecl(IToken! tok, string! name, int Arity, QKeyValue kv)
- : base(tok, name)
- {
- this.Arity = Arity;
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "type ");
- EmitAttributes(stream);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
- for (int i = 0; i < Arity; ++i)
- stream.Write(" _");
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddType(this);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- ResolveAttributes(rc);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(tc);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypeCtorDecl(this);
- }
- }
-
-
- public class TypeSynonymDecl : NamedDeclaration
- {
- public TypeVariableSeq! TypeParameters;
- public Type! Body;
-
- public TypeSynonymDecl(IToken! tok, string! name,
- TypeVariableSeq! typeParams, Type! body)
- : base(tok, name)
- {
- this.TypeParameters = typeParams;
- this.Body = body;
- }
- public TypeSynonymDecl(IToken! tok, string! name,
- TypeVariableSeq! typeParams, Type! body, QKeyValue kv)
- : base(tok, name)
- {
- this.TypeParameters = typeParams;
- this.Body = body;
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "type ");
- EmitAttributes(stream);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(Name));
- if (TypeParameters.Length > 0)
- stream.Write(" ");
- TypeParameters.Emit(stream, " ");
- stream.Write(" = ");
- Body.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddType(this);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- ResolveAttributes(rc);
-
- int previousState = rc.TypeBinderState;
- try {
- foreach (TypeVariable! v in TypeParameters)
- rc.AddTypeBinder(v);
- Body = Body.ResolveType(rc);
- } finally {
- rc.TypeBinderState = previousState;
- }
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(tc);
- }
-
- public static void ResolveTypeSynonyms(List<TypeSynonymDecl!>! synonymDecls,
- ResolutionContext! rc) {
- // then discover all dependencies between type synonyms
- IDictionary<TypeSynonymDecl!, List<TypeSynonymDecl!>!>! deps =
- new Dictionary<TypeSynonymDecl!, List<TypeSynonymDecl!>!> ();
- foreach (TypeSynonymDecl! decl in synonymDecls) {
- List<TypeSynonymDecl!>! declDeps = new List<TypeSynonymDecl!> ();
- FindDependencies(decl.Body, declDeps, rc);
- deps.Add(decl, declDeps);
- }
-
- List<TypeSynonymDecl!>! resolved = new List<TypeSynonymDecl!> ();
-
- int unresolved = synonymDecls.Count - resolved.Count;
- while (unresolved > 0) {
- foreach (TypeSynonymDecl! decl in synonymDecls) {
- if (!resolved.Contains(decl) &&
- forall{TypeSynonymDecl! d in deps[decl]; resolved.Contains(d)}) {
- decl.Resolve(rc);
- resolved.Add(decl);
- }
- }
-
- int newUnresolved = synonymDecls.Count - resolved.Count;
- if (newUnresolved < unresolved) {
- // we are making progress
- unresolved = newUnresolved;
- } else {
- // there have to be cycles in the definitions
- foreach (TypeSynonymDecl! decl in synonymDecls) {
- if (!resolved.Contains(decl)) {
- rc.Error(decl,
- "type synonym could not be resolved because of cycles: {0}" +
- " (replacing body with \"bool\" to continue resolving)",
- decl.Name);
-
- // we simply replace the bodies of all remaining type
- // synonyms with "bool" so that resolution can continue
- decl.Body = Type.Bool;
- decl.Resolve(rc);
- }
- }
-
- unresolved = 0;
- }
- }
- }
-
- // determine a list of all type synonyms that occur in "type"
- private static void FindDependencies(Type! type, List<TypeSynonymDecl!>! deps,
- ResolutionContext! rc) {
- if (type.IsVariable || type.IsBasic) {
- // nothing
- } else if (type.IsUnresolved) {
- UnresolvedTypeIdentifier! unresType = type.AsUnresolved;
- TypeSynonymDecl dep = rc.LookUpTypeSynonym(unresType.Name);
- if (dep != null)
- deps.Add(dep);
- foreach (Type! subtype in unresType.Arguments)
- FindDependencies(subtype, deps, rc);
- } else if (type.IsMap) {
- MapType! mapType = type.AsMap;
- foreach (Type! subtype in mapType.Arguments)
- FindDependencies(subtype, deps, rc);
- FindDependencies(mapType.Result, deps, rc);
- } else if (type.IsCtor) {
- // this can happen because we allow types to be resolved multiple times
- CtorType! ctorType = type.AsCtor;
- foreach (Type! subtype in ctorType.Arguments)
- FindDependencies(subtype, deps, rc);
- } else {
- System.Diagnostics.Debug.Fail("Did not expect this type during resolution: "
- + type);
- }
- }
-
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypeSynonymDecl(this);
- }
- }
-
-
- public abstract class Variable : NamedDeclaration, AI.IVariable
- {
- public TypedIdent! TypedIdent;
- public Variable(IToken! tok, TypedIdent! typedIdent)
- : base(tok, typedIdent.Name)
- {
- this.TypedIdent = typedIdent;
- // base(tok, typedIdent.Name);
- }
-
- public Variable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
- : base(tok, typedIdent.Name)
- {
- this.TypedIdent = typedIdent;
- // base(tok, typedIdent.Name);
- this.Attributes = kv;
- }
-
- public abstract bool IsMutable
- {
- get;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "var ");
- EmitAttributes(stream);
- EmitVitals(stream, level);
- stream.WriteLine(";");
- }
- public void EmitVitals(TokenTextWriter! stream, int level)
- {
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds && this.TypedIdent.HasName)
- {
- stream.Write("h{0}^^", this.GetHashCode()); // the idea is that this will prepend the name printed by TypedIdent.Emit
- }
- this.TypedIdent.Emit(stream);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- this.TypedIdent.Resolve(rc);
- }
- public void ResolveWhere(ResolutionContext! rc)
- {
- if (this.TypedIdent.WhereExpr != null) {
- this.TypedIdent.WhereExpr.Resolve(rc);
- }
- ResolveAttributes(rc);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(tc);
- this.TypedIdent.Typecheck(tc);
- }
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitVariable(this);
- }
- }
-
- public class VariableComparer : IComparer
- {
- public int Compare(object a, object b) {
- Variable A = a as Variable;
- Variable B = b as Variable;
- if (A == null || B == null) {
- throw new ArgumentException("VariableComparer works only on objects of type Variable");
- }
- return ((!)A.Name).CompareTo(B.Name);
- }
- }
-
- // class to specify the <:-parents of the values of constants
- public class ConstantParent {
- public readonly IdentifierExpr! Parent;
- // if true, the sub-dag underneath this constant-parent edge is
- // disjoint from all other unique sub-dags
- public readonly bool Unique;
-
- public ConstantParent(IdentifierExpr! parent, bool unique) {
- Parent = parent;
- Unique = unique;
- }
- }
-
- public class Constant : Variable
- {
- // when true, the value of this constant is meant to be distinct
- // from all other constants.
- public readonly bool Unique;
-
- // the <:-parents of the value of this constant. If the field is
- // null, no information about the parents is provided, which means
- // that the parental situation is unconstrained.
- public readonly List<ConstantParent!> Parents;
-
- // if true, it is assumed that the immediate <:-children of the
- // value of this constant are completely specified
- public readonly bool ChildrenComplete;
-
- public Constant(IToken! tok, TypedIdent! typedIdent)
- : base(tok, typedIdent)
- requires typedIdent.Name != null && typedIdent.Name.Length > 0;
- requires typedIdent.WhereExpr == null;
- {
- // base(tok, typedIdent);
- this.Unique = true;
- this.Parents = null;
- this.ChildrenComplete = false;
- }
- public Constant(IToken! tok, TypedIdent! typedIdent, bool unique)
- : base(tok, typedIdent)
- requires typedIdent.Name != null && typedIdent.Name.Length > 0;
- requires typedIdent.WhereExpr == null;
- {
- // base(tok, typedIdent);
- this.Unique = unique;
- this.Parents = null;
- this.ChildrenComplete = false;
- }
- public Constant(IToken! tok, TypedIdent! typedIdent,
- bool unique,
- List<ConstantParent!> parents, bool childrenComplete,
- QKeyValue kv)
- : base(tok, typedIdent, kv)
- requires typedIdent.Name != null && typedIdent.Name.Length > 0;
- requires typedIdent.WhereExpr == null;
- {
- // base(tok, typedIdent);
- this.Unique = unique;
- this.Parents = parents;
- this.ChildrenComplete = childrenComplete;
- }
- public override bool IsMutable
- {
- get
- {
- return false;
- }
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "const ");
- EmitAttributes(stream);
- if (this.Unique){
- stream.Write(this, level, "unique ");
- }
- EmitVitals(stream, level);
-
- if (Parents != null || ChildrenComplete) {
- stream.Write(this, level, " extends");
- string! sep = " ";
- foreach (ConstantParent! p in (!)Parents) {
- stream.Write(this, level, sep);
- sep = ", ";
- if (p.Unique)
- stream.Write(this, level, "unique ");
- p.Parent.Emit(stream);
- }
- if (ChildrenComplete)
- stream.Write(this, level, " complete");
- }
-
- stream.WriteLine(";");
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddVariable(this, true);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- base.Resolve(rc);
- if (Parents != null) {
- foreach (ConstantParent! p in Parents) {
- p.Parent.Resolve(rc);
- if (p.Parent.Decl != null && !(p.Parent.Decl is Constant))
- rc.Error(p.Parent, "the parent of a constant has to be a constant");
- if (this.Equals(p.Parent.Decl))
- rc.Error(p.Parent, "constant cannot be its own parent");
- }
- }
-
- // check that no parent occurs twice
- // (could be optimised)
- if (Parents != null) {
- for (int i = 0; i < Parents.Count; ++i) {
- if (Parents[i].Parent.Decl != null) {
- for (int j = i + 1; j < Parents.Count; ++j) {
- if (Parents[j].Parent.Decl != null &&
- ((!)Parents[i].Parent.Decl).Equals(Parents[j].Parent.Decl))
- rc.Error(Parents[j].Parent,
- "{0} occurs more than once as parent",
- Parents[j].Parent.Decl);
- }
- }
- }
- }
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- base.Typecheck(tc);
-
- if (Parents != null) {
- foreach (ConstantParent! p in Parents) {
- p.Parent.Typecheck(tc);
- if (!((!)p.Parent.Decl).TypedIdent.Type.Unify(this.TypedIdent.Type))
- tc.Error(p.Parent,
- "parent of constant has incompatible type ({0} instead of {1})",
- p.Parent.Decl.TypedIdent.Type, this.TypedIdent.Type);
- }
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitConstant(this);
- }
- }
- public class GlobalVariable : Variable
- {
- public GlobalVariable(IToken! tok, TypedIdent! typedIdent)
- : base(tok, typedIdent)
- {
- }
- public GlobalVariable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
- : base(tok, typedIdent, kv)
- {
- }
- public override bool IsMutable
- {
- get
- {
- return true;
- }
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddVariable(this, true);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitGlobalVariable(this);
- }
- }
- public class Formal : Variable
- {
- public bool InComing;
- public Formal(IToken! tok, TypedIdent! typedIdent, bool incoming)
- : base(tok, typedIdent)
- {
- InComing = incoming;
- }
- public override bool IsMutable
- {
- get
- {
- return !InComing;
- }
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddVariable(this, false);
- }
-
- /// <summary>
- /// Given a sequence of Formal declarations, returns sequence of Formals like the given one but without where clauses.
- /// The Type of each Formal is cloned.
- /// </summary>
- public static VariableSeq! StripWhereClauses(VariableSeq! w)
- {
- VariableSeq s = new VariableSeq();
- foreach (Variable! v in w) {
- Formal f = (Formal)v;
- TypedIdent ti = f.TypedIdent;
- s.Add(new Formal(f.tok, new TypedIdent(ti.tok, ti.Name, ti.Type.CloneUnresolved()), f.InComing));
- }
- return s;
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitFormal(this);
- }
- }
- public class LocalVariable : Variable
- {
- public LocalVariable(IToken! tok, TypedIdent! typedIdent, QKeyValue kv)
- {
- base(tok, typedIdent, kv);
- }
- public LocalVariable(IToken! tok, TypedIdent! typedIdent)
- {
- base(tok, typedIdent, null);
- }
- public override bool IsMutable
- {
- get
- {
- return true;
- }
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddVariable(this, false);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitLocalVariable(this);
- }
- }
- public class Incarnation : LocalVariable
- {
- public int incarnationNumber;
- public Incarnation(Variable! var, int i) :
- base(
- var.tok,
- new TypedIdent(var.TypedIdent.tok,var.TypedIdent.Name + "@" + i,var.TypedIdent.Type)
- )
- {
- incarnationNumber = i;
- }
-
- }
- public class BoundVariable : Variable
- {
- public BoundVariable(IToken! tok, TypedIdent! typedIdent)
- requires typedIdent.WhereExpr == null;
- {
- base(tok, typedIdent); // here for aesthetic reasons
- }
- public override bool IsMutable
- {
- get
- {
- return false;
- }
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddVariable(this, false);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBoundVariable(this);
- }
- }
-
- public abstract class DeclWithFormals : NamedDeclaration
- {
- public TypeVariableSeq! TypeParameters;
- public /*readonly--except in StandardVisitor*/ VariableSeq! InParams, OutParams;
-
- public DeclWithFormals (IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams)
- : base(tok, name)
- {
- this.TypeParameters = typeParams;
- this.InParams = inParams;
- this.OutParams = outParams;
- // base(tok, name);
- }
-
- protected DeclWithFormals (DeclWithFormals! that)
- : base(that.tok, (!) that.Name)
- {
- this.TypeParameters = that.TypeParameters;
- this.InParams = that.InParams;
- this.OutParams = that.OutParams;
- // base(that.tok, (!) that.Name);
- }
-
- protected void EmitSignature (TokenTextWriter! stream, bool shortRet)
- {
- Type.EmitOptionalTypeParams(stream, TypeParameters);
- stream.Write("(");
- InParams.Emit(stream);
- stream.Write(")");
-
- if (shortRet)
- {
- assert OutParams.Length == 1;
- stream.Write(" : ");
- ((!)OutParams[0]).TypedIdent.Type.Emit(stream);
- }
- else if (OutParams.Length > 0)
- {
- stream.Write(" returns (");
- OutParams.Emit(stream);
- stream.Write(")");
- }
- }
-
- // Register all type parameters at the resolution context
- protected void RegisterTypeParameters(ResolutionContext! rc) {
- foreach (TypeVariable! v in TypeParameters)
- rc.AddTypeBinder(v);
- }
-
- protected void SortTypeParams() {
- TypeSeq! allTypes = InParams.ToTypeSeq;
- allTypes.AddRange(OutParams.ToTypeSeq);
- TypeParameters = Type.SortTypeParams(TypeParameters, allTypes, null);
- }
-
- /// <summary>
- /// Adds the given formals to the current variable context, and then resolves
- /// the types of those formals. Does NOT resolve the where clauses of the
- /// formals.
- /// Relies on the caller to first create, and later tear down, that variable
- /// context.
- /// </summary>
- /// <param name="rc"></param>
- protected void RegisterFormals(VariableSeq! formals, ResolutionContext! rc)
- {
- foreach (Formal! f in formals)
- {
- if (f.Name != TypedIdent.NoName)
- {
- rc.AddVariable(f, false);
- }
- f.Resolve(rc);
- }
- }
-
- /// <summary>
- /// Resolves the where clauses (and attributes) of the formals.
- /// </summary>
- /// <param name="rc"></param>
- protected void ResolveFormals(VariableSeq! formals, ResolutionContext! rc)
- {
- foreach (Formal! f in formals)
- {
- f.ResolveWhere(rc);
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc) {
- TypecheckAttributes(tc);
- foreach (Formal! p in InParams) {
- p.Typecheck(tc);
- }
- foreach (Formal! p in OutParams) {
- p.Typecheck(tc);
- }
- }
- }
-
- public class Expansion {
- public string? ignore; // when to ignore
- public Expr! body;
- public TypeVariableSeq! TypeParameters;
- public Variable[]! formals;
-
- public Expansion(string? ignore, Expr! body,
- TypeVariableSeq! typeParams, Variable[]! formals)
- {
- this.ignore = ignore;
- this.body = body;
- this.TypeParameters = typeParams;
- this.formals = formals;
- }
- }
-
- public class Function : DeclWithFormals
- {
- public string? Comment;
-
- // the body is only set if the function is declared with {:expand true}
- public Expr Body;
- public List<Expansion!>? expansions;
- public bool doingExpansion;
-
- private bool neverTrigger;
- private bool neverTriggerComputed;
-
- public Function(IToken! tok, string! name, VariableSeq! args, Variable! result)
- {
- this(tok, name, new TypeVariableSeq(), args, result, null);
- }
- public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result)
- {
- this(tok, name, typeParams, args, result, null);
- }
- public Function(IToken! tok, string! name, VariableSeq! args, Variable! result,
- string? comment)
- {
- this(tok, name, new TypeVariableSeq(), args, result, comment);
- }
- public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result,
- string? comment)
- : base(tok, name, typeParams, args, new VariableSeq(result))
- {
- Comment = comment;
- // base(tok, name, args, new VariableSeq(result));
- }
- public Function(IToken! tok, string! name, TypeVariableSeq! typeParams, VariableSeq! args, Variable! result,
- string? comment, QKeyValue kv)
- {
- this(tok, name, typeParams, args, result, comment);
- this.Attributes = kv;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "function ");
- EmitAttributes(stream);
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds) {
- stream.Write("h{0}^^{1}", this.GetHashCode(), TokenTextWriter.SanitizeIdentifier(this.Name));
- } else {
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- EmitSignature(stream, true);
- if (Body != null) {
- stream.WriteLine();
- stream.WriteLine("{");
- stream.Write(level+1, "");
- Body.Emit(stream);
- stream.WriteLine();
- stream.WriteLine("}");
- } else {
- stream.WriteLine(";");
- }
- }
- public override void Register(ResolutionContext! rc)
- {
- rc.AddProcedure(this);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
- rc.PushVarContext();
- RegisterFormals(InParams, rc);
- RegisterFormals(OutParams, rc);
- ResolveAttributes(rc);
- if (Body != null)
- Body.Resolve(rc);
- rc.PopVarContext();
- Type.CheckBoundVariableOccurrences(TypeParameters,
- InParams.ToTypeSeq, OutParams.ToTypeSeq,
- this.tok, "function arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- // PR: why was the base call left out previously?
- base.Typecheck(tc);
- // TypecheckAttributes(tc);
- if (Body != null) {
- Body.Typecheck(tc);
- if (!((!)Body.Type).Unify(((!)OutParams[0]).TypedIdent.Type))
- tc.Error(Body,
- "function body with invalid type: {0} (expected: {1})",
- Body.Type, ((!)OutParams[0]).TypedIdent.Type);
- }
- }
-
- public bool NeverTrigger
- {
- get {
- if (!neverTriggerComputed) {
- this.CheckBooleanAttribute("never_pattern", ref neverTrigger);
- neverTriggerComputed = true;
- }
- return neverTrigger;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitFunction(this);
- }
- }
-
- public class Requires : Absy, IPotentialErrorNode
- {
- public readonly bool Free;
- public Expr! Condition;
- public string? Comment;
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get { return errorData; }
- set { errorData = value; }
- }
- invariant errorData != null ==> errorData is string;
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get { return errorDataEnhanced; }
- set { errorDataEnhanced = value; }
- }
-
- public QKeyValue Attributes;
-
- public String ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- public Requires(IToken! token, bool free, Expr! condition, string? comment, QKeyValue kv)
- : base(token)
- {
- this.Free = free;
- this.Condition = condition;
- this.Comment = comment;
- this.Attributes = kv;
- // base(token);
- }
-
- public Requires(IToken! token, bool free, Expr! condition, string? comment)
- {
- this(token, free, condition, comment, null);
- }
-
- public Requires(bool free, Expr! condition)
- {
- this(Token.NoToken, free, condition, null);
- }
-
- public Requires(bool free, Expr! condition, string? comment)
- {
- this(Token.NoToken, free, condition, comment);
- }
-
- public void Emit(TokenTextWriter! stream, int level)
- {
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "{0}requires ", Free ? "free " : "");
- this.Condition.Emit(stream);
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
- this.Condition.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- this.Condition.Typecheck(tc);
- assert this.Condition.Type != null; // follows from postcondition of Expr.Typecheck
- if (!this.Condition.Type.Unify(Type.Bool))
- {
- tc.Error(this, "preconditions must be of type bool");
- }
- }
- }
-
- public class Ensures : Absy, IPotentialErrorNode
- {
- public readonly bool Free;
- public Expr! Condition;
- public string? Comment;
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get { return errorData; }
- set { errorData = value; }
- }
- invariant errorData != null ==> errorData is string;
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get { return errorDataEnhanced; }
- set { errorDataEnhanced = value; }
- }
-
- public String ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- public QKeyValue Attributes;
-
- public Ensures(IToken! token, bool free, Expr! condition, string? comment, QKeyValue kv)
- : base(token)
- {
- this.Free = free;
- this.Condition = condition;
- this.Comment = comment;
- this.Attributes = kv;
- // base(token);
- }
-
- public Ensures(IToken! token, bool free, Expr! condition, string? comment)
- {
- this(token, free, condition, comment, null);
- }
-
- public Ensures(bool free, Expr! condition)
- {
- this(Token.NoToken, free, condition, null);
- }
-
- public Ensures(bool free, Expr! condition, string? comment)
- {
- this(Token.NoToken, free, condition, comment);
- }
-
- public void Emit(TokenTextWriter! stream, int level)
- {
- if (Comment != null) {
- stream.WriteLine(this, level, "// " + Comment);
- }
- stream.Write(this, level, "{0}ensures ", Free ? "free " : "");
- this.Condition.Emit(stream);
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
- this.Condition.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- this.Condition.Typecheck(tc);
- assert this.Condition.Type != null; // follows from postcondition of Expr.Typecheck
- if (!this.Condition.Type.Unify(Type.Bool))
- {
- tc.Error(this, "postconditions must be of type bool");
- }
- }
- }
-
- public class Procedure : DeclWithFormals
- {
- public RequiresSeq! Requires;
- public IdentifierExprSeq! Modifies;
- public EnsuresSeq! Ensures;
-
- // Abstract interpretation: Procedure-specific invariants...
- [Rep]
- public readonly ProcedureSummary! Summary;
-
- public Procedure (
- IToken! tok,
- string! name,
- TypeVariableSeq! typeParams,
- VariableSeq! inParams,
- VariableSeq! outParams,
- RequiresSeq! @requires,
- IdentifierExprSeq! @modifies,
- EnsuresSeq! @ensures
- )
- {
- this(tok, name, typeParams, inParams, outParams, @requires, @modifies, @ensures, null);
- }
-
- public Procedure (
- IToken! tok,
- string! name,
- TypeVariableSeq! typeParams,
- VariableSeq! inParams,
- VariableSeq! outParams,
- RequiresSeq! @requires,
- IdentifierExprSeq! @modifies,
- EnsuresSeq! @ensures,
- QKeyValue kv
- )
- : base(tok, name, typeParams, inParams, outParams)
- {
- this.Requires = @requires;
- this.Modifies = @modifies;
- this.Ensures = @ensures;
- this.Summary = new ProcedureSummary();
- this.Attributes = kv;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "procedure ");
- EmitAttributes(stream);
- stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- EmitSignature(stream, false);
- stream.WriteLine(";");
-
- level++;
-
- foreach (Requires! e in this.Requires)
- {
- e.Emit(stream, level);
- }
-
- if (this.Modifies.Length > 0)
- {
- stream.Write(level, "modifies ");
- this.Modifies.Emit(stream, false);
- stream.WriteLine(";");
- }
-
- foreach (Ensures! e in this.Ensures)
- {
- e.Emit(stream, level);
- }
-
- if (!CommandLineOptions.Clo.IntraproceduralInfer)
- {
- for (int s=0; s < this.Summary.Count; s++)
- {
- ProcedureSummaryEntry! entry = (!) this.Summary[s];
- stream.Write(level + 1, "// ");
- Expr e;
- e = (Expr)entry.Lattice.ToPredicate(entry.OnEntry);
- e.Emit(stream);
- stream.Write(" ==> ");
- e = (Expr)entry.Lattice.ToPredicate(entry.OnExit);
- e.Emit(stream);
- stream.WriteLine();
- }
- }
-
- stream.WriteLine();
- stream.WriteLine();
- }
-
- public override void Register(ResolutionContext! rc)
- {
- rc.AddProcedure(this);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- rc.PushVarContext();
-
- foreach (IdentifierExpr! ide in Modifies)
- {
- ide.Resolve(rc);
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
-
- RegisterFormals(InParams, rc);
- ResolveFormals(InParams, rc); // "where" clauses of in-parameters are resolved without the out-parameters in scope
- foreach (Requires! e in Requires)
- {
- e.Resolve(rc);
- }
- RegisterFormals(OutParams, rc);
- ResolveFormals(OutParams, rc); // "where" clauses of out-parameters are resolved with both in- and out-parametes in scope
-
- rc.StateMode = ResolutionContext.State.Two;
- foreach (Ensures! e in Ensures)
- {
- e.Resolve(rc);
- }
- rc.StateMode = ResolutionContext.State.Single;
- ResolveAttributes(rc);
-
- Type.CheckBoundVariableOccurrences(TypeParameters,
- InParams.ToTypeSeq, OutParams.ToTypeSeq,
- this.tok, "procedure arguments",
- rc);
-
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
-
- rc.PopVarContext();
-
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- base.Typecheck(tc);
- foreach (IdentifierExpr! ide in Modifies)
- {
- assume ide.Decl != null;
- if (!ide.Decl.IsMutable)
- {
- tc.Error(this, "modifies list contains constant: {0}", ide.Name);
- }
- ide.Typecheck(tc);
- }
- foreach (Requires! e in Requires)
- {
- e.Typecheck(tc);
- }
- foreach (Ensures! e in Ensures)
- {
- e.Typecheck(tc);
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitProcedure(this);
- }
- }
-
- public class Implementation : DeclWithFormals
- {
- public VariableSeq! LocVars;
- [Rep] public StmtList StructuredStmts;
- [Rep] public List<Block!>! Blocks;
- public Procedure Proc;
-
- // Blocks before applying passification etc.
- // Both are used only when /inline is set.
- public List<Block!>? OriginalBlocks;
- public VariableSeq? OriginalLocVars;
-
- // Strongly connected components
- private StronglyConnectedComponents<Block!> scc;
- private bool BlockPredecessorsComputed;
- public bool StronglyConnectedComponentsComputed
- {
- get
- {
- return this.scc != null;
- }
- }
-
- public bool SkipVerification
- {
- get
- {
- bool verify = true;
- ((!)this.Proc).CheckBooleanAttribute("verify", ref verify);
- this.CheckBooleanAttribute("verify", ref verify);
- if (!verify) {
- return true;
- }
-
- if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert ||
- CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume) {
- Expr? inl = this.FindExprAttribute("inline");
- if (inl == null) inl = this.Proc.FindExprAttribute("inline");
- if (inl != null && inl is LiteralExpr && ((LiteralExpr)inl).isBigNum && ((LiteralExpr)inl).asBigNum.Signum > 0) {
- return true;
- }
- }
-
- return false;
- }
- }
-
- public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams,
- VariableSeq! localVariables, [Captured] StmtList! structuredStmts)
- {
- this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, new Errors());
- }
-
- public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams,
- VariableSeq! localVariables, [Captured] StmtList! structuredStmts,
- Errors! errorHandler)
- {
- this(tok, name, typeParams, inParams, outParams, localVariables, structuredStmts, null, errorHandler);
- }
-
- public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams,
- VariableSeq! localVariables, [Captured] StmtList! structuredStmts, QKeyValue kv,
- Errors! errorHandler)
- : base(tok, name, typeParams, inParams, outParams)
- {
- LocVars = localVariables;
- StructuredStmts = structuredStmts;
- BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler);
- Blocks = ctx.Blocks;
- BlockPredecessorsComputed = false;
- scc = null;
- Attributes = kv;
-
- // base(tok, name, inParams, outParams);
- }
-
- public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams,
- VariableSeq! localVariables, [Captured] List<Block!>! block)
- {
- this(tok, name, typeParams, inParams, outParams, localVariables, block, null);
- }
-
- public Implementation(IToken! tok, string! name, TypeVariableSeq! typeParams,
- VariableSeq! inParams, VariableSeq! outParams,
- VariableSeq! localVariables, [Captured] List<Block!>! blocks, QKeyValue kv)
- : base(tok, name, typeParams, inParams, outParams)
- {
- LocVars = localVariables;
- Blocks = blocks;
- BlockPredecessorsComputed = false;
- scc = null;
- Attributes = kv;
-
- //base(tok, name, inParams, outParams);
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "implementation ");
- EmitAttributes(stream);
- stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- EmitSignature(stream, false);
- stream.WriteLine();
-
- stream.WriteLine(level, "{0}", '{');
-
- foreach (Variable! v in this.LocVars) {
- v.Emit(stream, level + 1);
- }
-
- if (this.StructuredStmts != null && !CommandLineOptions.Clo.PrintInstrumented && !CommandLineOptions.Clo.PrintInlined) {
- if (this.LocVars.Length > 0) {
- stream.WriteLine();
- }
- if (CommandLineOptions.Clo.PrintUnstructured < 2) {
- if (CommandLineOptions.Clo.PrintUnstructured == 1) {
- stream.WriteLine(this, level+1, "/*** structured program:");
- }
- this.StructuredStmts.Emit(stream, level+1);
- if (CommandLineOptions.Clo.PrintUnstructured == 1) {
- stream.WriteLine(level+1, "**** end structured program */");
- }
- }
- }
-
- if (this.StructuredStmts == null || 1 <= CommandLineOptions.Clo.PrintUnstructured ||
- CommandLineOptions.Clo.PrintInstrumented || CommandLineOptions.Clo.PrintInlined)
- {
- foreach (Block b in this.Blocks)
- {
- b.Emit(stream, level+1);
- }
- }
-
- stream.WriteLine(level, "{0}", '}');
-
- stream.WriteLine();
- stream.WriteLine();
- }
- public override void Register(ResolutionContext! rc)
- {
- // nothing to register
- }
- public override void Resolve(ResolutionContext! rc)
- {
- if (Proc != null)
- {
- // already resolved
- return;
- }
- DeclWithFormals dwf = rc.LookUpProcedure((!) this.Name);
- Proc = dwf as Procedure;
- if (dwf == null)
- {
- rc.Error(this, "implementation given for undeclared procedure: {0}", this.Name);
- }
- else if (Proc == null)
- {
- rc.Error(this, "implementations given for function, not procedure: {0}", this.Name);
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- RegisterTypeParameters(rc);
-
- rc.PushVarContext();
- RegisterFormals(InParams, rc);
- RegisterFormals(OutParams, rc);
-
- foreach (Variable! v in LocVars)
- {
- v.Register(rc);
- v.Resolve(rc);
- }
- foreach (Variable! v in LocVars)
- {
- v.ResolveWhere(rc);
- }
-
- rc.PushProcedureContext();
- foreach (Block b in Blocks)
- {
- b.Register(rc);
- }
-
- ResolveAttributes(rc);
-
- rc.StateMode = ResolutionContext.State.Two;
- foreach (Block b in Blocks)
- {
- b.Resolve(rc);
- }
- rc.StateMode = ResolutionContext.State.Single;
-
- rc.PopProcedureContext();
- rc.PopVarContext();
-
- Type.CheckBoundVariableOccurrences(TypeParameters,
- InParams.ToTypeSeq, OutParams.ToTypeSeq,
- this.tok, "implementation arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- SortTypeParams();
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- base.Typecheck(tc);
-
- assume this.Proc != null;
-
- if (this.TypeParameters.Length != Proc.TypeParameters.Length) {
- tc.Error(this, "mismatched number of type parameters in procedure implementation: {0}",
- this.Name);
- } else {
- // if the numbers of type parameters are different, it is
- // difficult to compare the argument types
- MatchFormals(this.InParams, Proc.InParams, "in", tc);
- MatchFormals(this.OutParams, Proc.OutParams, "out", tc);
- }
-
- foreach (Variable! v in LocVars)
- {
- v.Typecheck(tc);
- }
- IdentifierExprSeq oldFrame = tc.Frame;
- tc.Frame = Proc.Modifies;
- foreach (Block b in Blocks)
- {
- b.Typecheck(tc);
- }
- assert tc.Frame == Proc.Modifies;
- tc.Frame = oldFrame;
- }
- void MatchFormals(VariableSeq! implFormals, VariableSeq! procFormals,
- string! inout, TypecheckingContext! tc)
- {
- if (implFormals.Length != procFormals.Length)
- {
- tc.Error(this, "mismatched number of {0}-parameters in procedure implementation: {1}",
- inout, this.Name);
- }
- else
- {
- // unify the type parameters so that types can be compared
- assert Proc != null;
- assert this.TypeParameters.Length == Proc.TypeParameters.Length;
-
- IDictionary<TypeVariable!, Type!>! subst1 =
- new Dictionary<TypeVariable!, Type!> ();
- IDictionary<TypeVariable!, Type!>! subst2 =
- new Dictionary<TypeVariable!, Type!> ();
-
- for (int i = 0; i < this.TypeParameters.Length; ++i) {
- TypeVariable! newVar =
- new TypeVariable (Token.NoToken, Proc.TypeParameters[i].Name);
- subst1.Add(Proc.TypeParameters[i], newVar);
- subst2.Add(this.TypeParameters[i], newVar);
- }
-
- for (int i = 0; i < implFormals.Length; i++)
- {
- // the names of the formals are allowed to change from the proc to the impl
-
- // but types must be identical
- Type t = ((Variable!)implFormals[i]).TypedIdent.Type.Substitute(subst2);
- Type u = ((Variable!)procFormals[i]).TypedIdent.Type.Substitute(subst1);
- if (!t.Equals(u))
- {
- string! a = (!) ((Variable!)implFormals[i]).Name;
- string! b = (!) ((Variable!)procFormals[i]).Name;
- string! c;
- if (a == b) {
- c = a;
- } else {
- c = String.Format("{0} (named {1} in implementation)", b, a);
- }
- tc.Error(this, "mismatched type of {0}-parameter in implementation {1}: {2}", inout, this.Name, c);
- }
- }
- }
- }
-
- private Hashtable/*Variable->Expr*//*?*/ formalMap = null;
- public void ResetImplFormalMap() {
- this.formalMap = null;
- }
- public Hashtable /*Variable->Expr*/! GetImplFormalMap()
- {
- if (this.formalMap != null)
- return this.formalMap;
- else
- {
- Hashtable /*Variable->Expr*/! map = new Hashtable /*Variable->Expr*/ (InParams.Length + OutParams.Length);
-
- assume this.Proc != null;
- assume InParams.Length == Proc.InParams.Length;
- for (int i = 0; i < InParams.Length; i++)
- {
- Variable! v = (!) InParams[i];
- IdentifierExpr ie = new IdentifierExpr(v.tok, v);
- Variable! pv = (!) Proc.InParams[i];
- map.Add(pv, ie);
- }
- System.Diagnostics.Debug.Assert(OutParams.Length == Proc.OutParams.Length);
- for (int i = 0; i < OutParams.Length; i++)
- {
- Variable! v = (!) OutParams[i];
- IdentifierExpr ie = new IdentifierExpr(v.tok, v);
- Variable! pv = (!) Proc.OutParams[i];
- map.Add(pv, ie);
- }
- this.formalMap = map;
-
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
- {
- Console.WriteLine("Implementation.GetImplFormalMap on {0}:", this.Name);
- using (TokenTextWriter stream = new TokenTextWriter("<console>", Console.Out, false))
- {
- foreach (DictionaryEntry e in map)
- {
- Console.Write(" ");
- ((Variable!)e.Key).Emit(stream, 0);
- Console.Write(" --> ");
- ((Expr!)e.Value).Emit(stream);
- Console.WriteLine();
- }
- }
- }
-
- return map;
- }
- }
-
- /// <summary>
- /// Instrument the blocks with the inferred invariants
- /// </summary>
- public override void InstrumentWithInvariants()
- {
- foreach (Block b in this.Blocks)
- {
- if (b.Lattice != null)
- {
- assert b.PreInvariant != null; /* If the pre-abstract state is null, then something is wrong */
- assert b.PostInvariant != null; /* If the post-state is null, then something is wrong */
-
- bool instrumentEntry;
- bool instrumentExit;
- switch (CommandLineOptions.Clo.InstrumentInfer) {
- case CommandLineOptions.InstrumentationPlaces.Everywhere:
- instrumentEntry = true;
- instrumentExit = true;
- break;
- case CommandLineOptions.InstrumentationPlaces.LoopHeaders:
- instrumentEntry = b.widenBlock;
- instrumentExit = false;
- break;
- default:
- assert false; // unexpected InstrumentationPlaces value
- }
-
- if (instrumentEntry || instrumentExit) {
- CmdSeq newCommands = new CmdSeq();
- if (instrumentEntry) {
- Expr inv = (Expr) b.Lattice.ToPredicate(b.PreInvariant); /*b.PreInvariantBuckets.GetDisjunction(b.Lattice);*/
- PredicateCmd cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken,inv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv);
- newCommands.Add(cmd);
- }
- newCommands.AddRange(b.Cmds);
- if (instrumentExit) {
- Expr inv = (Expr) b.Lattice.ToPredicate(b.PostInvariant);
- PredicateCmd cmd = CommandLineOptions.Clo.InstrumentWithAsserts ? (PredicateCmd)new AssertCmd(Token.NoToken,inv) : (PredicateCmd)new AssumeCmd(Token.NoToken, inv);
- newCommands.Add(cmd);
- }
- b.Cmds = newCommands;
- }
- }
- }
- }
-
- /// <summary>
- /// Return a collection of blocks that are reachable from the block passed as a parameter.
- /// The block must be defined in the current implementation
- /// </summary>
- public ICollection<Block!> GetConnectedComponents(Block! startingBlock)
- {
- assert this.Blocks.Contains(startingBlock);
-
- if(!this.BlockPredecessorsComputed)
- ComputeStronglyConnectedComponents();
-
-#if DEBUG_PRINT
- System.Console.WriteLine("* Strongly connected components * \n{0} \n ** ", scc);
-#endif
-
- foreach(ICollection<Block!> component in (!) this.scc)
- {
- foreach(Block! b in component)
- {
- if(b == startingBlock) // We found the compontent that owns the startingblock
- {
- return component;
- }
- }
- }
-
- assert false; // if we are here, it means that the block is not in one of the components. This is an error.
- }
-
- /// <summary>
- /// Compute the strongly connected compontents of the blocks in the implementation.
- /// As a side effect, it also computes the "predecessor" relation for the block in the implementation
- /// </summary>
- override public void ComputeStronglyConnectedComponents()
- {
- if(!this.BlockPredecessorsComputed)
- ComputedPredecessorsForBlocks();
-
- Adjacency<Block!> next = new Adjacency<Block!>(Successors);
- Adjacency<Block!> prev = new Adjacency<Block!>(Predecessors);
-
- this.scc = new StronglyConnectedComponents<Block!>(this.Blocks, next, prev);
- scc.Compute();
-
- foreach(Block! block in this.Blocks)
- {
- block.Predecessors = new BlockSeq();
- }
-
- }
-
- /// <summary>
- /// Reset the abstract stated computed before
- /// </summary>
- override public void ResetAbstractInterpretationState()
- {
- foreach(Block! b in this.Blocks)
- {
- b.ResetAbstractInterpretationState();
- }
- }
-
- /// <summary>
- /// A private method used as delegate for the strongly connected components.
- /// It return, given a node, the set of its successors
- /// </summary>
- private IEnumerable/*<Block!>*/! Successors(Block! node)
- {
- GotoCmd gotoCmd = node.TransferCmd as GotoCmd;
-
- if(gotoCmd != null)
- { // If it is a gotoCmd
- assert gotoCmd.labelTargets != null;
-
- return gotoCmd.labelTargets;
- }
- else
- { // otherwise must be a ReturnCmd
- assert node.TransferCmd is ReturnCmd;
-
- return new List<Block!>();
- }
- }
-
- /// <summary>
- /// A private method used as delegate for the strongly connected components.
- /// It return, given a node, the set of its predecessors
- /// </summary>
- private IEnumerable/*<Block!>*/! Predecessors(Block! node)
- {
- assert this.BlockPredecessorsComputed;
-
- return node.Predecessors;
- }
-
- /// <summary>
- /// Compute the predecessor informations for the blocks
- /// </summary>
- private void ComputedPredecessorsForBlocks()
- {
- foreach (Block b in this.Blocks)
- {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null)
- {
- assert gtc.labelTargets != null;
- foreach (Block! dest in gtc.labelTargets)
- {
- dest.Predecessors.Add(b);
- }
- }
- }
- this.BlockPredecessorsComputed = true;
- }
-
- public void PruneUnreachableBlocks() {
- ArrayList /*Block!*/ visitNext = new ArrayList /*Block!*/ ();
- List<Block!> reachableBlocks = new List<Block!>();
- System.Compiler.IMutableSet /*Block!*/ reachable = new System.Compiler.HashSet /*Block!*/ (); // the set of elements in "reachableBlocks"
-
- visitNext.Add(this.Blocks[0]);
- while (visitNext.Count != 0) {
- Block! b = (Block!)visitNext[visitNext.Count-1];
- visitNext.RemoveAt(visitNext.Count-1);
- if (!reachable.Contains(b)) {
- reachableBlocks.Add(b);
- reachable.Add(b);
- if (b.TransferCmd is GotoCmd) {
- foreach (Cmd! s in b.Cmds) {
- if (s is PredicateCmd) {
- LiteralExpr e = ((PredicateCmd)s).Expr as LiteralExpr;
- if (e != null && e.IsFalse) {
- // This statement sequence will never reach the end, because of this "assume false" or "assert false".
- // Hence, it does not reach its successors.
- b.TransferCmd = new ReturnCmd(b.TransferCmd.tok);
- goto NEXT_BLOCK;
- }
- }
- }
- // it seems that the goto statement at the end may be reached
- foreach (Block! succ in (!)((GotoCmd)b.TransferCmd).labelTargets) {
- visitNext.Add(succ);
- }
- }
- }
- NEXT_BLOCK: {}
- }
-
- this.Blocks = reachableBlocks;
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitImplementation(this);
- }
- }
-
-
- public class TypedIdent : Absy
- {
- public const string NoName = "";
- public string! Name;
- public Type! Type;
- public Expr WhereExpr;
- // [NotDelayed]
- public TypedIdent (IToken! tok, string! name, Type! type)
- ensures this.WhereExpr == null; //PM: needed to verify BoogiePropFactory.FreshBoundVariable
- {
- this(tok, name, type, null); // here for aesthetic reasons
- }
- // [NotDelayed]
- public TypedIdent (IToken! tok, string! name, Type! type, Expr whereExpr)
- : base(tok)
- ensures this.WhereExpr == whereExpr;
- {
- this.Name = name;
- this.Type = type;
- this.WhereExpr = whereExpr;
- // base(tok);
- }
- public bool HasName {
- get {
- return this.Name != NoName;
- }
- }
- public void Emit(TokenTextWriter! stream)
- {
- stream.SetToken(this);
- if (this.Name != NoName)
- {
- stream.Write("{0}: ", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- this.Type.Emit(stream);
- if (this.WhereExpr != null)
- {
- stream.Write(" where ");
- this.WhereExpr.Emit(stream);
- }
- }
- public override void Resolve(ResolutionContext! rc)
- {
- // NOTE: WhereExpr needs to be resolved by the caller, because the caller must provide a modified ResolutionContext
- this.Type = this.Type.ResolveType(rc);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
-// type variables can occur when working with polymorphic functions/procedures
-// if (!this.Type.IsClosed)
-// tc.Error(this, "free variables in type of an identifier: {0}",
-// this.Type.FreeVariables);
- if (this.WhereExpr != null) {
- this.WhereExpr.Typecheck(tc);
- assert this.WhereExpr.Type != null; // follows from postcondition of Expr.Typecheck
- if (!this.WhereExpr.Type.Unify(Type.Bool))
- {
- tc.Error(this, "where clauses must be of type bool");
- }
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypedIdent(this);
- }
- }
-
- /// <summary>
- /// Conceptually, a LatticeElementList is a infinite array indexed from 0,
- /// where some finite number of elements have a non-null value. All elements
- /// have type Lattice.Element.
- ///
- /// The Count property returns the first index above all non-null values.
- ///
- /// The [i] getter returns the element at position i, which may be null. The
- /// index i is not allowed to be negative.
- /// The [i] setter sets the element at position i. As a side effect, this
- /// operation may increase Count. The index i is not allowed to be negative.
- /// The right-hand value of the setter is not allowed to be null; that is,
- /// null can occur in the list only as an "unused" element.
- /// </summary>
- public class LatticeElementList : ArrayList
- {
- public new /*Maybe null*/ AI.Lattice.Element this [ int i ]
- {
- get
- {
- if (i < Count)
- {
- return (AI.Lattice.Element)base[i];
- }
- else
- {
- return null;
- }
- }
- set
- {
- System.Diagnostics.Debug.Assert(value != null);
- while (Count <= i)
- {
- Add(null);
- }
- base[i] = value;
- }
- }
- /// <summary>
- /// Returns the disjunction of (the expression formed from) the
- /// non-null lattice elements in the list. The expressions are
- /// formed according to the given "lattice", which is assumed to
- /// be the lattice of the lattice elements stored in the list.
- /// </summary>
- /// <param name="lattice"></param>
- /// <returns></returns>
- public Expr GetDisjunction(AI.Lattice! lattice)
- {
- Expr disjunction = null;
- foreach (AI.Lattice.Element el in this)
- {
- if (el != null)
- {
- Expr e = (Expr) lattice.ToPredicate(el);
- if (disjunction == null)
- {
- disjunction = e;
- }
- else
- {
- disjunction = Expr.Or(disjunction, e);
- }
- }
- }
- if (disjunction == null)
- {
- return Expr.False;
- }
- else
- {
- return disjunction;
- }
- }
- }
-
-
-
- public abstract class BoogieFactory {
- public static Expr! IExpr2Expr(AI.IExpr! e) {
- Variable v = e as Variable;
- if (v != null) {
- return new IdentifierExpr(Token.NoToken, v);
- }
- else if (e is AI.IVariable) { // but not a Variable
- return new AIVariableExpr(Token.NoToken, (AI.IVariable)e);
- }
- else if (e is IdentifierExpr.ConstantFunApp) {
- return ((IdentifierExpr.ConstantFunApp)e).IdentifierExpr;
- }
- else if (e is QuantifierExpr.AIQuantifier) {
- return ((QuantifierExpr.AIQuantifier)e).arg.RealQuantifier;
- }
- else {
- return (Expr)e;
- }
- }
- public static ExprSeq! IExprArray2ExprSeq(IList/*<AI.IExpr!>*/! a) {
- Expr[] e = new Expr[a.Count];
- int i = 0;
- foreach (AI.IExpr! aei in a) {
- e[i] = IExpr2Expr(aei);
- i++;
- }
- return new ExprSeq(e);
- }
-
- // Convert a Boogie type into an AIType if possible. This should be
- // extended when AIFramework gets more types.
- public static AI.AIType! Type2AIType(Type! t)
- {
-// if (t.IsRef)
-// return AI.Ref.Type;
-// else
- if (t.IsInt)
- return AI.Int.Type;
-// else if (t.IsName) PR: how to handle this case?
-// return AI.FieldName.Type;
- else
- return AI.Value.Type;
- }
- }
-
- #region Generic Sequences
- //---------------------------------------------------------------------
- // Generic Sequences
- //---------------------------------------------------------------------
-
- public sealed class TypedIdentSeq : PureCollections.Sequence
- {
- public TypedIdentSeq(params Type[]! args) : base(args) { }
- public new TypedIdent this[int index]
- {
- get
- {
- return (TypedIdent)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public sealed class RequiresSeq : PureCollections.Sequence
- {
- public RequiresSeq(params Requires[]! args) : base(args) { }
- public new Requires! this[int index]
- {
- get
- {
- return (Requires!) base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public sealed class EnsuresSeq : PureCollections.Sequence
- {
- public EnsuresSeq(params Ensures[]! args) : base(args) { }
- public new Ensures! this[int index]
- {
- get
- {
- return (Ensures!) base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public sealed class VariableSeq : PureCollections.Sequence
- {
- public VariableSeq(params Variable[]! args)
- : base(args)
- {
- }
- public VariableSeq(VariableSeq! varSeq)
- : base(varSeq)
- {
- }
- public new Variable this[int index]
- {
- get
- {
- return (Variable)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- public void Emit(TokenTextWriter! stream)
- {
- string sep = "";
- foreach (Variable! v in this)
- {
- stream.Write(sep);
- sep = ", ";
- v.EmitVitals(stream, 0);
- }
- }
- public TypeSeq! ToTypeSeq { get {
- TypeSeq! res = new TypeSeq ();
- foreach(Variable! v in this)
- res.Add(v.TypedIdent.Type);
- return res;
- } }
- }
-
- public sealed class TypeSeq : PureCollections.Sequence
- {
- public TypeSeq(params Type[]! args)
- : base(args)
- {
- }
- public TypeSeq(TypeSeq! varSeq)
- : base(varSeq)
- {
- }
- public new Type! this[int index]
- {
- get
- {
- return (Type!)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- public List<Type!>! ToList() {
- List<Type!>! res = new List<Type!> (Length);
- foreach (Type! t in this)
- res.Add(t);
- return res;
- }
- public void Emit(TokenTextWriter! stream, string! separator)
- {
- string sep = "";
- foreach (Type! v in this)
- {
- stream.Write(sep);
- sep = separator;
- v.Emit(stream);
- }
- }
- }
-
- public sealed class TypeVariableSeq : PureCollections.Sequence
- {
- public TypeVariableSeq(params TypeVariable[]! args)
- : base(args)
- {
- }
- public TypeVariableSeq(TypeVariableSeq! varSeq)
- : base(varSeq)
- {
- }
-/* PR: the following two constructors cause Spec# crashes
- public TypeVariableSeq(TypeVariable! var)
- : base(new TypeVariable! [] { var })
- {
- }
- public TypeVariableSeq()
- : base(new TypeVariable![0])
- {
- } */
- public new TypeVariable! this[int index]
- {
- get
- {
- return (TypeVariable!)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- public void AppendWithoutDups(TypeVariableSeq! s1) {
- for (int i = 0; i < s1.card; i++) {
- TypeVariable! next = s1[i];
- if (!this.Has(next)) this.Add(next);
- }
- }
- public void Emit(TokenTextWriter! stream, string! separator)
- {
- string sep = "";
- foreach (TypeVariable! v in this)
- {
- stream.Write(sep);
- sep = separator;
- v.Emit(stream);
- }
- }
- public new TypeVariable[]! ToArray() {
- TypeVariable[]! n = new TypeVariable[Length];
- int ct = 0;
- foreach (TypeVariable! var in this)
- n[ct++] = var;
- return n;
- }
- public List<TypeVariable!>! ToList() {
- List<TypeVariable!>! res = new List<TypeVariable!> (Length);
- foreach (TypeVariable! var in this)
- res.Add(var);
- return res;
- }
- }
-
- public sealed class IdentifierExprSeq : PureCollections.Sequence
- {
- public IdentifierExprSeq(params IdentifierExpr[]! args)
- : base(args)
- {
- }
- public IdentifierExprSeq(IdentifierExprSeq! ideSeq)
- : base(ideSeq)
- {
- }
- public new IdentifierExpr! this[int index]
- {
- get
- {
- return (IdentifierExpr!)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
-
- public void Emit(TokenTextWriter! stream, bool printWhereComments)
- {
- string sep = "";
- foreach (IdentifierExpr! e in this)
- {
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
-
- if (printWhereComments && e.Decl != null && e.Decl.TypedIdent.WhereExpr != null) {
- stream.Write(" /* where ");
- e.Decl.TypedIdent.WhereExpr.Emit(stream);
- stream.Write(" */");
- }
- }
- }
- }
-
-
- public sealed class CmdSeq : PureCollections.Sequence
- {
- public CmdSeq(params Cmd[]! args) : base(args){}
- public CmdSeq(CmdSeq! cmdSeq)
- : base(cmdSeq)
- {
- }
- public new Cmd! this[int index]
- {
- get
- {
- return (Cmd!)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public sealed class ExprSeq : PureCollections.Sequence
- {
- public ExprSeq(params Expr[]! args)
- : base(args)
- {
- }
- public ExprSeq(ExprSeq! exprSeq)
- : base(exprSeq)
- {
- }
- public new Expr this[int index]
- {
- get
- {
- return (Expr)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
-
- public new Expr Last() { return (Expr)base.Last(); }
-
- public static ExprSeq operator +(ExprSeq a, ExprSeq b)
- {
- if (a==null) throw new ArgumentNullException("a");
- if (b==null) throw new ArgumentNullException("b");
- return Append(a,b);
- }
-
- public static ExprSeq Append(ExprSeq! s, ExprSeq! t)
- {
- Expr[] n = new Expr[s.card+t.card];
- for (int i = 0; i< s.card; i++) n[i] = s[i];
- for (int i = 0; i< t.card; i++) n[s.card+i] = t[i];
- return new ExprSeq(n);
- }
- public void Emit(TokenTextWriter! stream)
- {
- string sep = "";
- foreach (Expr! e in this)
- {
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
- }
- public TypeSeq! ToTypeSeq { get {
- TypeSeq! res = new TypeSeq ();
- foreach(Expr e in this)
- res.Add(((!)e).Type);
- return res;
- } }
- }
-
- public sealed class TokenSeq : PureCollections.Sequence
- {
- public TokenSeq(params Token[]! args)
- : base(args)
- {
- }
- public new Token this[int index]
- {
- get
- {
- return (Token)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public sealed class StringSeq : PureCollections.Sequence
- {
- public StringSeq(params string[]! args)
- : base(args)
- {
- }
- public new String this[int index]
- {
- get
- {
- return (String)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- public void Emit(TokenTextWriter! stream)
- {
- string sep = "";
- foreach (string! s in this)
- {
- stream.Write(sep);
- sep = ", ";
- stream.Write(s);
- }
- }
- }
-
- public sealed class BlockSeq : PureCollections.Sequence
- {
- public BlockSeq(params Block[]! args)
- : base(args)
- {
- }
- public BlockSeq(BlockSeq! blockSeq)
- : base(blockSeq)
- {
- }
-
- public new Block this[int index]
- {
- get
- {
- return (Block)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- }
-
- public static class Emitter {
- public static void Declarations(List<Declaration!>! decls, TokenTextWriter! stream)
- {
- bool first = true;
- foreach (Declaration d in decls)
- {
- if (d == null) continue;
- if (first)
- {
- first = false;
- }
- else
- {
- stream.WriteLine();
- }
- d.Emit(stream, 0);
- }
- }
- }
- public sealed class DeclarationSeq : PureCollections.Sequence
- {
- public DeclarationSeq(params string[]! args)
- : base(args)
- {
- }
- public new Declaration this[int index]
- {
- get
- {
- return (Declaration)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- public void Emit(TokenTextWriter! stream)
- {
- bool first = true;
- foreach (Declaration d in this)
- {
- if (d == null) continue;
- if (first)
- {
- first = false;
- }
- else
- {
- stream.WriteLine();
- }
- d.Emit(stream, 0);
- }
- }
- public void InstrumentWithInvariants ()
- {
- foreach (Declaration! d in this)
- {
- d.InstrumentWithInvariants();
- }
- }
- }
- #endregion
-
-
- #region Regular Expressions
- // a data structure to recover the "program structure" from the flow graph
- public sealed class RESeq : PureCollections.Sequence
- {
- public RESeq(params RE[]! args)
- : base (args)
- {
- }
- public RESeq(RESeq! reSeq)
- : base(reSeq)
- {
- }
- public new RE this[int index]
- {
- get
- {
- return (RE)base[index];
- }
- set
- {
- base[index] = value;
- }
- }
- // public void Emit(TokenTextWriter stream)
- // {
- // string sep = "";
- // foreach (RE e in this)
- // {
- // stream.Write(sep);
- // sep = ", ";
- // e.Emit(stream);
- // }
- // }
- }
- public abstract class RE : Cmd
- {
- public RE() : base(Token.NoToken) {}
- public override void AddAssignedVariables(VariableSeq! vars) { throw new NotImplementedException(); }
- }
- public class AtomicRE : RE
- {
- public Block! b;
- public AtomicRE(Block! block) { b = block; }
- public override void Resolve(ResolutionContext! rc)
- {
- b.Resolve(rc);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- b.Typecheck(tc);
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- b.Emit(stream,level);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAtomicRE(this);
- }
- }
- public abstract class CompoundRE : RE
- {
- public override void Resolve(ResolutionContext! rc)
- {
- return;
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- return;
- }
- }
- public class Sequential : CompoundRE
- {
- public RE! first;
- public RE! second;
- public Sequential(RE! a, RE! b)
- {
- first = a;
- second = b;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.WriteLine();
- stream.WriteLine("{0};", Indent(level));
- first.Emit(stream,level+1);
- second.Emit(stream,level+1);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitSequential(this);
- }
- }
- public class Choice : CompoundRE
- {
- public RESeq! rs;
- public Choice(RESeq! operands)
- {
- rs = operands;
- // base();
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.WriteLine();
- stream.WriteLine("{0}[]", Indent(level));
- foreach (RE! r in rs )
- r.Emit(stream,level+1);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitChoice(this);
- }
- }
- public class DAG2RE
- {
- public static RE! Transform(Block! b)
- {
- TransferCmd tc = b.TransferCmd;
- if ( tc is ReturnCmd )
- {
- return new AtomicRE(b);
- }
- else if ( tc is GotoCmd )
- {
- GotoCmd! g = (GotoCmd) tc ;
- assume g.labelTargets != null;
- if ( g.labelTargets.Length == 1 )
- {
- return new Sequential(new AtomicRE(b),Transform( (!) g.labelTargets[0]));
- }
- else
- {
- RESeq rs = new RESeq();
- foreach (Block! target in g.labelTargets )
- {
- RE r = Transform(target);
- rs.Add(r);
- }
- RE second = new Choice(rs);
- return new Sequential(new AtomicRE(b),second);
- }
- }
- else
- {
- assume false;
- return new AtomicRE(b);
- }
- }
- }
-
- #endregion
-
- // NOTE: This class is here for convenience, since this file's
- // classes are used pretty much everywhere.
-
- public class BoogieDebug
- {
- public static bool DoPrinting = false;
-
- public static void Write (string! format, params object[]! args)
- {
- if (DoPrinting) { Console.Error.Write(format, args); }
- }
-
- public static void WriteLine (string! format, params object[]! args)
- {
- if (DoPrinting) { Console.Error.WriteLine(format, args); }
- }
-
- public static void WriteLine () { if (DoPrinting) { Console.Error.WriteLine(); } }
- }
-
-}
diff --git a/Source/Core/AbsyCmd.ssc b/Source/Core/AbsyCmd.ssc
deleted file mode 100644
index 7aa3e1fc..00000000
--- a/Source/Core/AbsyCmd.ssc
+++ /dev/null
@@ -1,2472 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie
-{
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.Contracts;
-
-
- //---------------------------------------------------------------------
- // BigBlock
- public class BigBlock
- {
- public readonly IToken! tok;
- public string LabelName;
- public readonly bool Anonymous;
- invariant !Anonymous ==> LabelName != null;
- [Rep] public CmdSeq! simpleCmds;
- public StructuredCmd ec;
- public TransferCmd tc;
- invariant ec == null || tc == null;
- public BigBlock successorBigBlock; // null if successor is end of proceduure body (or if field has not yet been initialized)
-
- public BigBlock(IToken! tok, string? labelName, [Captured] CmdSeq! simpleCmds, StructuredCmd? ec, TransferCmd? tc)
- requires ec == null || tc == null;
- {
- this.tok = tok;
- this.LabelName = labelName;
- this.Anonymous = labelName == null;
- this.simpleCmds = simpleCmds;
- this.ec = ec;
- this.tc = tc;
- }
-
- public void Emit(TokenTextWriter! stream, int level) {
- if (!Anonymous) {
- stream.WriteLine(level, "{0}:",
- CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.LabelName) : this.LabelName);
- }
-
- foreach (Cmd! c in this.simpleCmds) {
- c.Emit(stream, level+1);
- }
-
- if (this.ec != null) {
- this.ec.Emit(stream, level+1);
- } else if (this.tc != null) {
- this.tc.Emit(stream, level+1);
- }
- }
- }
-
- public class StmtList
- {
- [Rep] public readonly List<BigBlock!>! BigBlocks;
- public CmdSeq PrefixCommands;
- public readonly IToken! EndCurly;
- public StmtList ParentContext;
- public BigBlock ParentBigBlock;
- public Set<string!>! Labels = new Set<string!>();
-
- public StmtList([Captured] List<BigBlock!>! bigblocks, IToken! endCurly)
- requires bigblocks.Count > 0;
- {
- this.BigBlocks = bigblocks;
- this.EndCurly = endCurly;
- }
-
- // prints the list of statements, not the surrounding curly braces
- public void Emit(TokenTextWriter! stream, int level) {
- bool needSeperator = false;
- foreach (BigBlock b in BigBlocks) {
- assume b.IsPeerConsistent;
- if (needSeperator) {
- stream.WriteLine();
- }
- b.Emit(stream, level);
- needSeperator = true;
- }
- }
-
- /// <summary>
- /// Tries to insert the commands "prefixCmds" at the beginning of the first block
- /// of the StmtList, and returns "true" iff it succeeded.
- /// In the event of success, the "suggestedLabel" returns as the name of the
- /// block inside StmtList where "prefixCmds" were inserted. This name may be the
- /// same as the one passed in, in case this StmtList has no preference as to what
- /// to call its first block. In the event of failure, "suggestedLabel" is returned
- /// as its input value.
- /// Note, to be conservative (that is, ignoring the possible optimization that this
- /// method enables), this method can do nothing and return false.
- /// </summary>
- public bool PrefixFirstBlock([Captured] CmdSeq! prefixCmds, ref string! suggestedLabel)
- ensures !result ==> Owner.None(prefixCmds); // "prefixCmds" is captured only on success
- {
- assume PrefixCommands == null; // prefix has not been used
-
- BigBlock bb0 = BigBlocks[0];
- if (prefixCmds.Length == 0) {
- // This is always a success, since there is nothing to insert. Now, decide
- // which name to use for the first block.
- if (bb0.Anonymous) {
- bb0.LabelName = suggestedLabel;
- } else {
- assert bb0.LabelName != null;
- suggestedLabel = bb0.LabelName;
- }
- return true;
-
- } else {
- // There really is something to insert. We can do this inline only if the first
- // block is anonymous (which implies there is no branch to it from within the block).
- if (bb0.Anonymous) {
- PrefixCommands = prefixCmds;
- bb0.LabelName = suggestedLabel;
- return true;
- } else {
- return false;
- }
- }
- }
- }
-
- /// <summary>
- /// The AST for Boogie structured commands was designed to support backward compatibility with
- /// the Boogie unstructured commands. This has made the structured commands hard to construct.
- /// The StmtListBuilder class makes it easier to build structured commands.
- /// </summary>
- public class StmtListBuilder {
- List<BigBlock!>! bigBlocks = new List<BigBlock!>();
- string label;
- CmdSeq simpleCmds;
-
- void Dump(StructuredCmd scmd, TransferCmd tcmd)
- requires scmd == null || tcmd == null;
- ensures label == null && simpleCmds == null;
- {
- if (label == null && simpleCmds == null && scmd == null && tcmd == null) {
- // nothing to do
- } else {
- if (simpleCmds == null) {
- simpleCmds = new CmdSeq();
- }
- bigBlocks.Add(new BigBlock(Token.NoToken, label, simpleCmds, scmd, tcmd));
- label = null;
- simpleCmds = null;
- }
- }
-
- /// <summary>
- /// Collects the StmtList built so far and returns it. The StmtListBuilder should no longer
- /// be used once this method has been invoked.
- /// </summary>
- public StmtList! Collect(IToken! endCurlyBrace) {
- Dump(null, null);
- if (bigBlocks.Count == 0) {
- simpleCmds = new CmdSeq(); // the StmtList constructor doesn't like an empty list of BigBlock's
- Dump(null, null);
- }
- return new StmtList(bigBlocks, endCurlyBrace);
- }
-
- public void Add(Cmd! cmd) {
- if (simpleCmds == null) {
- simpleCmds = new CmdSeq();
- }
- simpleCmds.Add(cmd);
- }
-
- public void Add(StructuredCmd! scmd) {
- Dump(scmd, null);
- }
-
- public void Add(TransferCmd! tcmd) {
- Dump(null, tcmd);
- }
-
- public void AddLabelCmd(string! label) {
- Dump(null, null);
- this.label = label;
- }
-
- public void AddLocalVariable(string! name) {
- // TODO
- }
- }
-
- class BigBlocksResolutionContext {
- StmtList! stmtList;
- [Peer] List<Block!> blocks;
- string! prefix = "anon";
- int anon = 0;
- Set<string!> allLabels = new Set<string!>();
- Errors! errorHandler;
-
- public BigBlocksResolutionContext(StmtList! stmtList, Errors! errorHandler) {
- this.stmtList = stmtList;
- this.errorHandler = errorHandler;
- }
-
- public List<Block!>! Blocks {
- get {
- if (blocks == null) {
- blocks = new List<Block!>();
-
- int startErrorCount = this.errorHandler.count;
- // Check that there are no goto's into the middle of a block, and no break statement to a non-enclosing loop.
- // Also, determine a good value for "prefix".
- CheckLegalLabels(stmtList, null, null);
-
- // fill in names of anonymous blocks
- NameAnonymousBlocks(stmtList);
-
- // determine successor blocks
- RecordSuccessors(stmtList, null);
-
- if (this.errorHandler.count == startErrorCount) {
- // generate blocks from the big blocks
- CreateBlocks(stmtList, null);
- }
- }
- return blocks;
- }
- }
-
- void CheckLegalLabels(StmtList! stmtList, StmtList parentContext, BigBlock parentBigBlock)
- requires parentContext == null <==> parentBigBlock == null;
- requires stmtList.ParentContext == null; // it hasn't been set yet
- modifies stmtList.*;
- ensures stmtList.ParentContext == parentContext;
- {
- stmtList.ParentContext = parentContext;
- stmtList.ParentBigBlock = parentBigBlock;
-
- // record the labels declared in this StmtList
- foreach (BigBlock b in stmtList.BigBlocks) {
- if (b.LabelName != null) {
- string n = b.LabelName;
- if (n.StartsWith(prefix)) {
- if (prefix.Length < n.Length && n[prefix.Length] == '0') {
- prefix += "1";
- } else {
- prefix += "0";
- }
- }
- stmtList.Labels.Add(b.LabelName);
- }
- }
-
- // check that labels in this and nested StmtList's are legal
- foreach (BigBlock b in stmtList.BigBlocks) {
- // goto's must reference blocks in enclosing blocks
- if (b.tc is GotoCmd) {
- GotoCmd g = (GotoCmd)b.tc;
- foreach (string! lbl in (!)g.labelNames) {
- bool found = false;
- for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
- if (sl.Labels.Contains(lbl)) {
- found = true;
- break;
- }
- }
- if (!found) {
- this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
- }
- }
- }
-
- // break labels must refer to an enclosing while statement
- else if (b.ec is BreakCmd) {
- BreakCmd bcmd = (BreakCmd)b.ec;
- assert bcmd.BreakEnclosure == null; // it hasn't been initialized yet
- bool found = false;
- for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext)
- invariant sl != null;
- {
- BigBlock bb = sl.ParentBigBlock;
-
- if (bcmd.Label == null) {
- // a label-less break statement breaks out of the innermost enclosing while statement
- if (bb.ec is WhileCmd) {
- bcmd.BreakEnclosure = bb;
- found = true;
- break;
- }
- } else if (bcmd.Label == bb.LabelName) {
- // a break statement with a label can break out of both if statements and while statements
- if (bb.simpleCmds.Length == 0) {
- // this is a good target: the label refers to the if/while statement
- bcmd.BreakEnclosure = bb;
- } else {
- // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
- this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
- }
- found = true; // don't look any further, since we've found a matching label
- break;
- }
- }
- if (!found) {
- if (bcmd.Label == null) {
- this.errorHandler.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
- } else {
- this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
- }
- }
- }
-
- // recurse
- else if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- CheckLegalLabels(wcmd.Body, stmtList, b);
- } else {
- for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- CheckLegalLabels(ifcmd.thn, stmtList, b);
- if (ifcmd.elseBlock != null) {
- CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
- }
- }
- }
- }
- }
-
- void NameAnonymousBlocks(StmtList! stmtList) {
- foreach (BigBlock b in stmtList.BigBlocks) {
- if (b.LabelName == null) {
- b.LabelName = prefix + anon;
- anon++;
- }
- if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- NameAnonymousBlocks(wcmd.Body);
- } else {
- for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- NameAnonymousBlocks(ifcmd.thn);
- if (ifcmd.elseBlock != null) {
- NameAnonymousBlocks(ifcmd.elseBlock);
- }
- }
- }
- }
- }
-
- void RecordSuccessors(StmtList! stmtList, BigBlock successor) {
- for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
- BigBlock big = stmtList.BigBlocks[i];
- big.successorBigBlock = successor;
-
- if (big.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)big.ec;
- RecordSuccessors(wcmd.Body, successor);
- } else {
- for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
- RecordSuccessors(ifcmd.thn, successor);
- if (ifcmd.elseBlock != null) {
- RecordSuccessors(ifcmd.elseBlock, successor);
- }
- }
- }
-
- successor = big;
- }
- }
-
- // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label;
- // otherwise, it is null.
- void CreateBlocks(StmtList! stmtList, string runOffTheEndLabel)
- requires blocks != null;
- {
- CmdSeq cmdPrefixToApply = stmtList.PrefixCommands;
-
- int n = stmtList.BigBlocks.Count;
- foreach (BigBlock b in stmtList.BigBlocks) {
- n--;
- assert b.LabelName != null;
- CmdSeq theSimpleCmds;
- if (cmdPrefixToApply == null) {
- theSimpleCmds = b.simpleCmds;
- } else {
- theSimpleCmds = new CmdSeq();
- theSimpleCmds.AddRange(cmdPrefixToApply);
- theSimpleCmds.AddRange(b.simpleCmds);
- cmdPrefixToApply = null; // now, we've used 'em up
- }
-
- if (b.tc != null) {
- // this BigBlock has the very same components as a Block
- assert b.ec == null;
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc);
- blocks.Add(block);
-
- } else if (b.ec == null) {
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(stmtList.EndCurly, new StringSeq(runOffTheEndLabel));
- } else {
- trCmd = GotoSuccessor(stmtList.EndCurly, b);
- }
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd);
- blocks.Add(block);
-
- } else if (b.ec is BreakCmd) {
- BreakCmd bcmd = (BreakCmd)b.ec;
- assert bcmd.BreakEnclosure != null;
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure));
- blocks.Add(block);
-
- } else if (b.ec is WhileCmd) {
- WhileCmd wcmd = (WhileCmd)b.ec;
- string loopHeadLabel = prefix + anon + "_LoopHead";
- string! loopBodyLabel = prefix + anon + "_LoopBody";
- string loopDoneLabel = prefix + anon + "_LoopDone";
- anon++;
-
- CmdSeq ssBody = new CmdSeq();
- CmdSeq ssDone = new CmdSeq();
- if (wcmd.Guard != null) {
- ssBody.Add(new AssumeCmd(wcmd.tok, wcmd.Guard));
- ssDone.Add(new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard)));
- }
-
- // Try to squeeze in ssBody into the first block of wcmd.Body
- bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel);
-
- // ... goto LoopHead;
- Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new StringSeq(loopHeadLabel)));
- blocks.Add(block);
-
- // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody;
- CmdSeq ssHead = new CmdSeq();
- foreach (PredicateCmd inv in wcmd.Invariants) {
- ssHead.Add(inv);
- }
- block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new StringSeq(loopDoneLabel, loopBodyLabel)));
- blocks.Add(block);
-
- if (!bodyGuardTakenCareOf) {
- // LoopBody: assume guard; goto firstLoopBlock;
- block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new StringSeq(wcmd.Body.BigBlocks[0].LabelName)));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the loop body
- CreateBlocks(wcmd.Body, loopHeadLabel);
-
- // LoopDone: assume !guard; goto loopSuccessor;
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(wcmd.tok, new StringSeq(runOffTheEndLabel));
- } else {
- trCmd = GotoSuccessor(wcmd.tok, b);
- }
- block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd);
- blocks.Add(block);
-
- } else {
- IfCmd ifcmd = (IfCmd)b.ec;
- string predLabel = b.LabelName;
- CmdSeq predCmds = theSimpleCmds;
-
- for (; ifcmd != null; ifcmd = ifcmd.elseIf) {
- string! thenLabel = prefix + anon + "_Then";
- string! elseLabel = prefix + anon + "_Else";
- anon++;
-
- CmdSeq ssThen = new CmdSeq();
- CmdSeq ssElse = new CmdSeq();
- if (ifcmd.Guard != null) {
- ssThen.Add(new AssumeCmd(ifcmd.tok, ifcmd.Guard));
- ssElse.Add(new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)));
- }
-
- // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock
- bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel);
- bool elseGuardTakenCareOf = false;
- if (ifcmd.elseBlock != null) {
- elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel);
- }
-
- // ... goto Then, Else;
- Block block = new Block(b.tok, predLabel, predCmds,
- new GotoCmd(ifcmd.tok, new StringSeq(thenLabel, elseLabel)));
- blocks.Add(block);
-
- if (!thenGuardTakenCareOf) {
- // Then: assume guard; goto firstThenBlock;
- block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new StringSeq(ifcmd.thn.BigBlocks[0].LabelName)));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the then branch
- CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null);
-
- if (ifcmd.elseBlock != null) {
- assert ifcmd.elseIf == null;
- if (!elseGuardTakenCareOf) {
- // Else: assume !guard; goto firstElseBlock;
- block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new StringSeq(ifcmd.elseBlock.BigBlocks[0].LabelName)));
- blocks.Add(block);
- }
-
- // recurse to create the blocks for the else branch
- CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null);
-
- } else if (ifcmd.elseIf != null) {
- // this is an "else if"
- predLabel = elseLabel;
- predCmds = new CmdSeq();
- if (ifcmd.Guard != null) {
- predCmds.Add(new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)));
- }
-
- } else {
- // no else alternative is specified, so else branch is just "skip"
- // Else: assume !guard; goto ifSuccessor;
- TransferCmd trCmd;
- if (n == 0 && runOffTheEndLabel != null) {
- // goto the given label instead of the textual successor block
- trCmd = new GotoCmd(ifcmd.tok, new StringSeq(runOffTheEndLabel));
- } else {
- trCmd = GotoSuccessor(ifcmd.tok, b);
- }
- block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd);
- blocks.Add(block);
- }
- }
- }
- }
- }
-
- TransferCmd! GotoSuccessor(IToken! tok, BigBlock! b) {
- if (b.successorBigBlock != null) {
- return new GotoCmd(tok, new StringSeq(b.successorBigBlock.LabelName));
- } else {
- return new ReturnCmd(tok);
- }
- }
- }
-
- public abstract class StructuredCmd
- {
- public IToken! tok;
- public StructuredCmd(IToken! tok)
- {
- this.tok = tok;
- }
-
- public abstract void Emit(TokenTextWriter! stream, int level);
- }
-
- public class IfCmd : StructuredCmd
- {
- public Expr? Guard;
- public StmtList! thn;
- public IfCmd? elseIf;
- public StmtList elseBlock;
- invariant elseIf == null || elseBlock == null;
-
- public IfCmd(IToken! tok, Expr? guard, StmtList! thn, IfCmd? elseIf, StmtList elseBlock)
- : base(tok)
- requires elseIf == null || elseBlock == null;
- {
- this.Guard = guard;
- this.thn = thn;
- this.elseIf = elseIf;
- this.elseBlock = elseBlock;
- // base(tok);
- }
-
- public override void Emit(TokenTextWriter! stream, int level) {
- stream.Write(level, "if (");
- IfCmd! ifcmd = this;
- while (true) {
- if (ifcmd.Guard == null) {
- stream.Write("*");
- } else {
- ifcmd.Guard.Emit(stream);
- }
- stream.WriteLine(")");
-
- stream.WriteLine(level, "{");
- ifcmd.thn.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
-
- if (ifcmd.elseIf != null) {
- stream.Write(level, "else if (");
- ifcmd = ifcmd.elseIf;
- continue;
- } else if (ifcmd.elseBlock != null) {
- stream.WriteLine(level, "else");
- stream.WriteLine(level, "{");
- ifcmd.elseBlock.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
- }
- break;
- }
- }
- }
-
- public class WhileCmd : StructuredCmd
- {
- [Peer] public Expr? Guard;
- public List<PredicateCmd!>! Invariants;
- public StmtList! Body;
-
- public WhileCmd(IToken! tok, [Captured] Expr? guard, List<PredicateCmd!>! invariants, StmtList! body)
- : base(tok)
- {
- this.Guard = guard;
- this.Invariants = invariants;
- this.Body = body;
- /// base(tok);
- }
-
- public override void Emit(TokenTextWriter! stream, int level) {
- stream.Write(level, "while (");
- if (Guard == null) {
- stream.Write("*");
- } else {
- Guard.Emit(stream);
- }
- stream.WriteLine(")");
-
- foreach (PredicateCmd inv in Invariants) {
- if (inv is AssumeCmd) {
- stream.Write(level + 1, "free invariant ");
- } else {
- stream.Write(level + 1, "invariant ");
- }
- inv.Expr.Emit(stream);
- stream.WriteLine(";");
- }
-
- stream.WriteLine(level, "{");
- Body.Emit(stream, level + 1);
- stream.WriteLine(level, "}");
- }
- }
-
- public class BreakCmd : StructuredCmd
- {
- public string Label;
- public BigBlock BreakEnclosure;
-
- public BreakCmd(IToken! tok, string? label)
- : base(tok)
- {
- this.Label = label;
- // base(tok);
- }
-
- public override void Emit(TokenTextWriter! stream, int level) {
- if (Label == null) {
- stream.WriteLine(level, "break;");
- } else {
- stream.WriteLine(level, "break {0};", Label);
- }
- }
- }
-
- //---------------------------------------------------------------------
- // Block
- public sealed class Block : Absy
- {
- public string! Label; // Note, Label is mostly readonly, but it can change to the name of a nearby block during block coalescing and empty-block removal
- [Rep] [ElementsPeer] public CmdSeq! Cmds;
- [Rep] //PM: needed to verify Traverse.Visit
- public TransferCmd TransferCmd; // maybe null only because we allow deferred initialization (necessary for cyclic structures)
-
- // Abstract interpretation
-
- // public bool currentlyTraversed;
-
- public enum VisitState {ToVisit, BeingVisited, AlreadyVisited}; // used by WidenPoints.Compute
- public VisitState TraversingStatus;
-
- public bool widenBlock;
- public int iterations; // Count the number of time we visited the block during fixpoint computation. Used to decide if we widen or not
-
- // Block-specific invariants...
- public AI.Lattice Lattice; // The lattice used for the analysis of this block
- public AI.Lattice.Element PreInvariant; // The initial abstract states for this block
- public AI.Lattice.Element PostInvariant; // The exit abstract states for this block
- // KRML: We want to include the following invariant, but at the moment, doing so causes a run-time error (something about committed): invariant PreInvariant != null <==> PostInvariant != null;
-
- // VC generation and SCC computation
- public BlockSeq! Predecessors;
-
- public Set<Variable!> liveVarsBefore;
- public bool IsLive(Variable! v) {
- if (liveVarsBefore == null) return true;
- return liveVarsBefore.Contains(v);
- }
-
- public Block() { this(Token.NoToken, "", new CmdSeq(), new ReturnCmd(Token.NoToken));}
-
- public Block (IToken! tok, string! label, CmdSeq! cmds, TransferCmd transferCmd)
- : base(tok)
- {
- this.Label = label;
- this.Cmds = cmds;
- this.TransferCmd = transferCmd;
- this.PreInvariant = null;
- this.PostInvariant = null;
- this.Predecessors = new BlockSeq();
- this.liveVarsBefore = null;
- this.TraversingStatus = VisitState.ToVisit;
- this.iterations = 0;
- // base(tok);
- }
-
- public void Emit (TokenTextWriter! stream, int level)
- {
- stream.WriteLine();
- stream.WriteLine(
- this,
- level,
- "{0}:{1}",
- CommandLineOptions.Clo.PrintWithUniqueASTIds ? String.Format("h{0}^^{1}", this.GetHashCode(), this.Label) : this.Label,
- this.widenBlock ? " // cut point" : "");
-
- foreach (Cmd! c in this.Cmds)
- {
- c.Emit(stream, level + 1);
- }
- assume this.TransferCmd != null;
- this.TransferCmd.Emit(stream, level + 1);
- }
-
- public void Register (ResolutionContext! rc)
- {
- rc.AddBlock(this);
- }
-
- public override void Resolve (ResolutionContext! rc)
- {
- foreach (Cmd! c in Cmds)
- {
- c.Resolve(rc);
- }
- assume this.TransferCmd != null;
- TransferCmd.Resolve(rc);
- }
-
- public override void Typecheck (TypecheckingContext! tc)
- {
- foreach (Cmd! c in Cmds)
- {
- c.Typecheck(tc);
- }
- assume this.TransferCmd != null;
- TransferCmd.Typecheck(tc);
- }
-
- /// <summary>
- /// Reset the abstract intepretation state of this block. It does this by putting the iterations to 0 and the pre and post states to null
- /// </summary>
- public void ResetAbstractInterpretationState()
- {
-// this.currentlyTraversed = false;
- this.TraversingStatus = VisitState.ToVisit;
- this.iterations = 0;
- this.Lattice = null;
- this.PreInvariant = null;
- this.PostInvariant = null;
- }
-
- [Pure]
- public override string! ToString()
- {
- return this.Label + (this.widenBlock? "[w]" : "");
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBlock(this);
- }
- }
-
- //---------------------------------------------------------------------
- // Commands
-
- public abstract class Cmd : Absy
- {
- public Cmd(IToken! tok) : base(tok) { }
- public abstract void Emit(TokenTextWriter! stream, int level);
- public abstract void AddAssignedVariables(VariableSeq! vars);
- public void CheckAssignments(TypecheckingContext! tc)
- {
- VariableSeq! vars = new VariableSeq();
- this.AddAssignedVariables(vars);
- foreach (Variable! v in vars)
- {
- if (!v.IsMutable)
- {
- tc.Error(this, "command assigns to an immutable variable: {0}", v.Name);
- }
- else if (v is GlobalVariable && !tc.InFrame(v))
- {
- tc.Error(this, "command assigns to a global variable that is not in the enclosing method's modifies clause: {0}", v.Name);
- }
- }
- }
-
- // Methods to simulate the old SimpleAssignCmd and MapAssignCmd
- public static AssignCmd! SimpleAssign(IToken! tok, IdentifierExpr! lhs, Expr! rhs) {
- List<AssignLhs!>! lhss = new List<AssignLhs!> ();
- List<Expr!>! rhss = new List<Expr!> ();
-
- lhss.Add(new SimpleAssignLhs (lhs.tok, lhs));
- rhss.Add(rhs);
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- public static AssignCmd! MapAssign(IToken! tok,
- IdentifierExpr! map,
- ExprSeq! indexes, Expr! rhs) {
- List<AssignLhs!>! lhss = new List<AssignLhs!> ();
- List<Expr!>! rhss = new List<Expr!> ();
- List<Expr!>! indexesList = new List<Expr!> ();
-
- foreach (Expr e in indexes)
- indexesList.Add((!)e);
-
- lhss.Add(new MapAssignLhs (map.tok,
- new SimpleAssignLhs (map.tok, map),
- indexesList));
- rhss.Add(rhs);
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- public static AssignCmd! MapAssign(IToken! tok,
- IdentifierExpr! map,
- params Expr[]! args)
- requires args.Length > 0; // at least the rhs
- requires forall{int i in (0:args.Length); args[i] != null};
- {
- List<AssignLhs!>! lhss = new List<AssignLhs!> ();
- List<Expr!>! rhss = new List<Expr!> ();
- List<Expr!>! indexesList = new List<Expr!> ();
-
- for (int i = 0; i < args.Length - 1; ++i)
- indexesList.Add((!)args[i]);
-
- lhss.Add(new MapAssignLhs (map.tok,
- new SimpleAssignLhs (map.tok, map),
- indexesList));
- rhss.Add((!)args[args.Length - 1]);
-
- return new AssignCmd(tok, lhss, rhss);
- }
-
- /// <summary>
- /// This is a helper routine for printing a linked list of attributes. Each attribute
- /// is terminated by a space.
- /// </summary>
- public static void EmitAttributes(TokenTextWriter! stream, QKeyValue attributes)
- {
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- }
- public static void ResolveAttributes(QKeyValue attributes, ResolutionContext! rc)
- {
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- }
- public static void TypecheckAttributes(QKeyValue attributes, TypecheckingContext! tc)
- {
- for (QKeyValue kv = attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- }
- }
-
- public class CommentCmd : Cmd // just a convenience for debugging
- {
- public readonly string! Comment;
- public CommentCmd (string! c)
- : base(Token.NoToken)
- {
- Comment = c;
- // base(Token.NoToken);
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- if (this.Comment.Contains("\n")) {
- stream.WriteLine(this, level, "/* {0} */", this.Comment);
- } else {
- stream.WriteLine(this, level, "// {0}", this.Comment);
- }
- }
- public override void Resolve(ResolutionContext! rc) { }
- public override void AddAssignedVariables(VariableSeq! vars) { }
- public override void Typecheck(TypecheckingContext! tc) { }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitCommentCmd(this);
- }
- }
-
- // class for parallel assignments, which subsumes both the old
- // SimpleAssignCmd and the old MapAssignCmd
- public class AssignCmd : Cmd {
- public List<AssignLhs!>! Lhss;
- public List<Expr!>! Rhss;
-
- public AssignCmd(IToken! tok, List<AssignLhs!>! lhss, List<Expr!>! rhss) {
- base(tok);
- Lhss = lhss;
- Rhss = rhss;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "");
-
- string! sep = "";
- foreach (AssignLhs! l in Lhss) {
- stream.Write(sep);
- sep = ", ";
- l.Emit(stream);
- }
-
- stream.Write(" := ");
-
- sep = "";
- foreach (Expr! e in Rhss) {
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
-
- stream.WriteLine(";");
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
- if (Lhss.Count != Rhss.Count)
- rc.Error(this,
- "number of left-hand sides does not match number of right-hand sides");
-
- foreach (AssignLhs! e in Lhss)
- e.Resolve(rc);
- foreach (Expr! e in Rhss)
- e.Resolve(rc);
-
- // check for double occurrences of assigned variables
- // (could be optimised)
- for (int i = 0; i < Lhss.Count; ++i) {
- for (int j = i + 1; j < Lhss.Count; ++j) {
- if (((!)Lhss[i].DeepAssignedVariable).Equals(
- Lhss[j].DeepAssignedVariable))
- rc.Error(Lhss[j],
- "variable {0} is assigned more than once in parallel assignment",
- Lhss[j].DeepAssignedVariable);
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc) {
- foreach (AssignLhs! e in Lhss)
- e.Typecheck(tc);
- foreach (Expr! e in Rhss)
- e.Typecheck(tc);
-
- this.CheckAssignments(tc);
-
- for (int i = 0; i < Lhss.Count; ++i) {
- Type ltype = Lhss[i].Type;
- Type rtype = Rhss[i].Type;
- if (ltype != null && rtype != null) {
- // otherwise, there has already been an error when
- // typechecking the lhs or rhs
- if (!ltype.Unify(rtype))
- tc.Error(Lhss[i],
- "mismatched types in assignment command (cannot assign {0} to {1})",
- rtype, ltype);
- }
- }
- }
-
- public override void AddAssignedVariables(VariableSeq! vars)
- {
- foreach (AssignLhs! l in Lhss)
- vars.Add(l.DeepAssignedVariable);
- }
-
- // transform away the syntactic sugar of map assignments and
- // determine an equivalent assignment in which all rhs are simple
- // variables
- public AssignCmd! AsSimpleAssignCmd { get {
- List<AssignLhs!>! newLhss = new List<AssignLhs!> ();
- List<Expr!>! newRhss = new List<Expr!> ();
-
- for (int i = 0; i < Lhss.Count; ++i) {
- IdentifierExpr! newLhs;
- Expr! newRhs;
- Lhss[i].AsSimpleAssignment(Rhss[i], out newLhs, out newRhs);
- newLhss.Add(new SimpleAssignLhs(Token.NoToken, newLhs));
- newRhss.Add(newRhs);
- }
-
- return new AssignCmd(Token.NoToken, newLhss, newRhss);
- } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAssignCmd(this);
- }
- }
-
- // There are two different kinds of left-hand sides in assignments:
- // simple variables (identifiers), or locations of a map
- public abstract class AssignLhs : Absy {
- // The type of the lhs is determined during typechecking
- public abstract Type Type { get; }
- // Determine the variable that is actually assigned in this lhs
- public abstract IdentifierExpr! DeepAssignedIdentifier { get; }
- public abstract Variable DeepAssignedVariable { get; }
-
- public AssignLhs(IToken! tok) : base(tok) {}
- public abstract void Emit(TokenTextWriter! stream);
-
- public abstract Expr! AsExpr { get; }
-
- // transform away the syntactic sugar of map assignments and
- // determine an equivalent simple assignment
- internal abstract void AsSimpleAssignment(Expr! rhs,
- out IdentifierExpr! simpleLhs,
- out Expr! simpleRhs);
- }
-
- public class SimpleAssignLhs : AssignLhs {
- public IdentifierExpr! AssignedVariable;
-
- public override Type Type { get {
- return AssignedVariable.Type;
- } }
-
- public override IdentifierExpr! DeepAssignedIdentifier { get {
- return AssignedVariable;
- } }
-
- public override Variable DeepAssignedVariable { get {
- return AssignedVariable.Decl;
- } }
-
- public SimpleAssignLhs(IToken! tok, IdentifierExpr! assignedVariable) {
- base(tok);
- AssignedVariable = assignedVariable;
- }
- public override void Resolve(ResolutionContext! rc) {
- AssignedVariable.Resolve(rc);
- }
- public override void Typecheck(TypecheckingContext! tc) {
- AssignedVariable.Typecheck(tc);
- }
- public override void Emit(TokenTextWriter! stream) {
- AssignedVariable.Emit(stream);
- }
- public override Expr! AsExpr { get {
- return AssignedVariable;
- } }
- internal override void AsSimpleAssignment(Expr! rhs,
- out IdentifierExpr! simpleLhs,
- out Expr! simpleRhs) {
- simpleLhs = AssignedVariable;
- simpleRhs = rhs;
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitSimpleAssignLhs(this);
- }
- }
-
- // A map-assignment-lhs (m[t1, t2, ...] := ...) is quite similar to
- // a map select expression, but it is cleaner to keep those two
- // things separate
- public class MapAssignLhs : AssignLhs {
- public AssignLhs! Map;
-
- public List<Expr!>! Indexes;
-
- // The instantiation of type parameters of the map that is
- // determined during type checking.
- public TypeParamInstantiation TypeParameters = null;
-
- private Type TypeAttr = null;
-
- public override Type Type { get {
- return TypeAttr;
- } }
-
- public override IdentifierExpr! DeepAssignedIdentifier { get {
- return Map.DeepAssignedIdentifier;
- } }
-
- public override Variable DeepAssignedVariable { get {
- return Map.DeepAssignedVariable;
- } }
-
- public MapAssignLhs(IToken! tok, AssignLhs! map, List<Expr!>! indexes) {
- base(tok);
- Map = map;
- Indexes = indexes;
- }
- public override void Resolve(ResolutionContext! rc) {
- Map.Resolve(rc);
- foreach (Expr! e in Indexes)
- e.Resolve(rc);
- }
- public override void Typecheck(TypecheckingContext! tc) {
- Map.Typecheck(tc);
- foreach (Expr! e in Indexes)
- e.Typecheck(tc);
-
- // we use the same typechecking code as in MapSelect
- ExprSeq! selectArgs = new ExprSeq ();
- foreach (Expr! e in Indexes)
- selectArgs.Add(e);
- TypeParamInstantiation! tpInsts;
- TypeAttr =
- MapSelect.Typecheck((!)Map.Type, Map,
- selectArgs, out tpInsts, tc, tok, "map assignment");
- TypeParameters = tpInsts;
- }
- public override void Emit(TokenTextWriter! stream) {
- Map.Emit(stream);
- stream.Write("[");
- string! sep = "";
- foreach (Expr! e in Indexes) {
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
- stream.Write("]");
- }
- public override Expr! AsExpr { get {
- NAryExpr! res = Expr.Select(Map.AsExpr, Indexes);
- res.TypeParameters = this.TypeParameters;
- return res;
- } }
- internal override void AsSimpleAssignment(Expr! rhs,
- out IdentifierExpr! simpleLhs,
- out Expr! simpleRhs) {
- NAryExpr! newRhs = Expr.Store(Map.AsExpr, Indexes, rhs);
- newRhs.TypeParameters = this.TypeParameters;
- Map.AsSimpleAssignment(newRhs, out simpleLhs, out simpleRhs);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitMapAssignLhs(this);
- }
- }
-
- /// <summary>
- /// A StateCmd is like an imperative-let binding around a sequence of commands.
- /// There is no user syntax for a StateCmd. Instead, a StateCmd is only used
- /// temporarily during the desugaring phase inside the VC generator.
- /// </summary>
- public class StateCmd : Cmd
- {
- public /*readonly, except for the StandardVisitor*/ VariableSeq! Locals;
- public /*readonly, except for the StandardVisitor*/ CmdSeq! Cmds;
-
- public StateCmd(IToken! tok, VariableSeq! locals, CmdSeq! cmds)
- : base(tok)
- {
- this.Locals = locals;
- this.Cmds = cmds;
- // base(tok);
- }
-
- public override void Resolve(ResolutionContext! rc) {
- rc.PushVarContext();
- foreach (Variable! v in Locals) {
- rc.AddVariable(v, false);
- }
- foreach (Cmd! cmd in Cmds) {
- cmd.Resolve(rc);
- }
- rc.PopVarContext();
- }
-
- public override void AddAssignedVariables(VariableSeq! vars) {
- VariableSeq! vs = new VariableSeq();
- foreach (Cmd! cmd in this.Cmds)
- {
- cmd.AddAssignedVariables(vs);
- }
- System.Collections.Hashtable! localsSet = new System.Collections.Hashtable();
- foreach (Variable! local in this.Locals)
- {
- localsSet[local] = bool.TrueString;
- }
- foreach (Variable! v in vs)
- {
- if (!localsSet.ContainsKey(v))
- {
- vars.Add(v);
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc) {
- foreach (Cmd! cmd in Cmds) {
- cmd.Typecheck(tc);
- }
- }
-
- public override void Emit(TokenTextWriter! stream, int level) {
- stream.WriteLine(this, level, "{");
- foreach (Variable! v in Locals) {
- v.Emit(stream, level+1);
- }
- foreach (Cmd! c in Cmds) {
- c.Emit(stream, level+1);
- }
- stream.WriteLine(level, "}");
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitStateCmd(this);
- }
- }
-
- abstract public class SugaredCmd : Cmd
- {
- private Cmd desugaring; // null until desugared
-
- public SugaredCmd(IToken! tok) : base(tok) {}
-
- public Cmd! Desugaring {
- get {
- if (desugaring == null) {
- desugaring = ComputeDesugaring();
- }
- return desugaring;
- }
- }
- protected abstract Cmd! ComputeDesugaring();
-
- public override void Emit(TokenTextWriter! stream, int level) {
- if (CommandLineOptions.Clo.PrintDesugarings) {
- stream.WriteLine(this, level, "/*** desugaring:");
- Desugaring.Emit(stream, level);
- stream.WriteLine(level, "**** end desugaring */");
- }
- }
- }
-
- public abstract class CallCommonality : SugaredCmd
- {
- public QKeyValue Attributes;
-
- protected CallCommonality(IToken! tok, QKeyValue kv) {
- base(tok);
- Attributes = kv;
- }
-
- protected enum TempVarKind { Formal, Old, Bound }
-
- // We have to give the type explicitly, because the type of the formal "likeThisOne" can contain type variables
- protected Variable! CreateTemporaryVariable(VariableSeq! tempVars, Variable! likeThisOne, Type! ty, TempVarKind kind) {
- string! tempNamePrefix;
- switch (kind) {
- case TempVarKind.Formal:
- tempNamePrefix = "formal@";
- break;
- case TempVarKind.Old:
- tempNamePrefix = "old@";
- break;
- case TempVarKind.Bound:
- tempNamePrefix = "forall@";
- break;
- default:
- assert false; // unexpected kind
- }
- TypedIdent ti = likeThisOne.TypedIdent;
- TypedIdent newTi = new TypedIdent(ti.tok, "call" + UniqueId + tempNamePrefix + ti.Name, ty);
- Variable! v;
- if (kind == TempVarKind.Bound) {
- v = new BoundVariable(likeThisOne.tok, newTi);
- } else {
- v = new LocalVariable(likeThisOne.tok, newTi);
- tempVars.Add(v);
- }
- return v;
- }
- }
-
- public class CallCmd : CallCommonality, IPotentialErrorNode
- {
- string! callee;
- public Procedure Proc;
-
- // Element of the following lists can be null, which means that
- // the call happens with * as these parameters
- public List<Expr>! Ins;
- public List<IdentifierExpr>! Outs;
- //public Lattice.Element StateAfterCall;
-
- // The instantiation of type parameters that is determined during
- // type checking
- public TypeParamInstantiation TypeParameters = null;
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get { return errorData; }
- set { errorData = value; }
- }
-
- public CallCmd(IToken! tok, string! callee, ExprSeq! ins, IdentifierExprSeq! outs)
- {
- List<Expr>! insList = new List<Expr> ();
- List<IdentifierExpr>! outsList = new List<IdentifierExpr> ();
- foreach (Expr e in ins)
- insList.Add(e);
- foreach (IdentifierExpr e in outs)
- outsList.Add(e);
-
- this(tok, callee, insList, outsList);
- }
- public CallCmd(IToken! tok, string! callee, List<Expr>! ins, List<IdentifierExpr>! outs)
- {
- base(tok, null);
- this.callee = callee;
- this.Ins = ins;
- this.Outs = outs;
- }
- public CallCmd(IToken! tok, string! callee, List<Expr>! ins, List<IdentifierExpr>! outs, QKeyValue kv)
- {
- base(tok, kv);
- this.callee = callee;
- this.Ins = ins;
- this.Outs = outs;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "call ");
- EmitAttributes(stream, Attributes);
- string sep = "";
- if (Outs.Count > 0) {
- foreach (Expr arg in Outs) {
- stream.Write(sep);
- sep = ", ";
- if (arg == null) {
- stream.Write("*");
- } else {
- arg.Emit(stream);
- }
- }
- stream.Write(" := ");
- }
- stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
- stream.Write("(");
- sep = "";
- foreach (Expr arg in Ins) {
- stream.Write(sep);
- sep = ", ";
- if (arg == null) {
- stream.Write("*");
- } else {
- arg.Emit(stream);
- }
- }
- stream.WriteLine(");");
- base.Emit(stream, level);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- if (Proc != null)
- {
- // already resolved
- return;
- }
- ResolveAttributes(Attributes, rc);
- Proc = rc.LookUpProcedure(callee) as Procedure;
- if (Proc == null) {
- rc.Error(this, "call to undeclared procedure: {0}", callee);
- }
- foreach (Expr e in Ins)
- {
- if (e!=null) {
- e.Resolve(rc);
- }
- }
- Set/*<Variable>*/ actualOuts = new Set/*<Variable>*/ (Outs.Count);
- foreach (IdentifierExpr ide in Outs)
- {
- if (ide != null) {
- ide.Resolve(rc);
- if (ide.Decl != null) {
- if (actualOuts[ide.Decl]) {
- rc.Error(this, "left-hand side of call command contains variable twice: {0}", ide.Name);
- } else {
- actualOuts.Add(ide.Decl);
- }
- }
- }
- }
-
- if (Proc == null)
- return;
-
- // first make sure that the right number of parameters is given
- // (a similar check is in CheckArgumentTypes, but we are not
- // able to call this method because it cannot cope with Ins/Outs
- // that are null)
- if (Ins.Count != Proc.InParams.Length) {
- rc.Error(this.tok,
- "wrong number of arguments in call to {0}: {1}",
- callee, Ins.Count);
- return;
- }
- if (Outs.Count != Proc.OutParams.Length) {
- rc.Error(this.tok,
- "wrong number of result variables in call to {0}: {1}",
- callee, Outs.Count);
- return;
- }
- if (QKeyValue.FindBoolAttribute(this.Attributes, "async")) {
- if (Proc.OutParams.Length > 1) {
- rc.Error(this.tok, "a procedure called asynchronously can have at most one output parameter");
- return;
- }
- }
-
- // Check that type parameters can be determined using the given
- // actual i/o arguments. This is done already during resolution
- // because CheckBoundVariableOccurrences needs a resolution
- // context
- TypeSeq! formalInTypes = new TypeSeq();
- TypeSeq! formalOutTypes = new TypeSeq();
- for (int i = 0; i < Ins.Count; ++i)
- if (Ins[i] != null)
- formalInTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
- for (int i = 0; i < Outs.Count; ++i)
- if (Outs[i] != null)
- formalOutTypes.Add(((!)Proc.OutParams[i]).TypedIdent.Type);
-
- // we need to bind the type parameters for this
- // (this is expected by CheckBoundVariableOccurrences)
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- foreach (TypeVariable! v in Proc.TypeParameters)
- rc.AddTypeBinder(v);
- Type.CheckBoundVariableOccurrences(Proc.TypeParameters,
- formalInTypes, formalOutTypes,
- this.tok, "types of given arguments",
- rc);
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- }
-
- public override void AddAssignedVariables(VariableSeq! vars)
- {
- foreach (IdentifierExpr e in Outs)
- {
- if (e!=null) {
- vars.Add(e.Decl);
- }
- }
- assume this.Proc != null;
- foreach (IdentifierExpr! e in this.Proc.Modifies)
- {
- vars.Add(e.Decl);
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- assume this.Proc != null; // we assume the CallCmd has been successfully resolved before calling this Typecheck method
-
- TypecheckAttributes(Attributes, tc);
-
- // typecheck in-parameters
- foreach (Expr e in Ins)
- if (e!=null)
- e.Typecheck(tc);
- foreach (Expr e in Outs)
- if (e!=null)
- e.Typecheck(tc);
- this.CheckAssignments(tc);
-
- TypeSeq! formalInTypes = new TypeSeq();
- TypeSeq! formalOutTypes = new TypeSeq();
- ExprSeq! actualIns = new ExprSeq();
- IdentifierExprSeq! actualOuts = new IdentifierExprSeq();
- for (int i = 0; i < Ins.Count; ++i)
- {
- if (Ins[i] != null) {
- formalInTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
- actualIns.Add(Ins[i]);
- }
- }
- for (int i = 0; i < Outs.Count; ++i)
- {
- if (Outs[i] != null) {
- formalOutTypes.Add(((!)Proc.OutParams[i]).TypedIdent.Type);
- actualOuts.Add(Outs[i]);
- }
- }
-
- if (QKeyValue.FindBoolAttribute(this.Attributes, "async") && Outs.Count > 0) {
- Type returnType = ((!)Outs[0]).ShallowType;
- if (!returnType.Equals(Type.Int))
- {
- tc.Error(this.tok, "the return from an asynchronous call should be an integer");
- return;
- }
- }
-
- // match actuals with formals
- List<Type!>! actualTypeParams;
- Type.CheckArgumentTypes(Proc.TypeParameters,
- out actualTypeParams,
- formalInTypes, actualIns,
- formalOutTypes, actualOuts,
- this.tok,
- "call to " + callee,
- tc);
- TypeParameters = SimpleTypeParamInstantiation.From(Proc.TypeParameters,
- actualTypeParams);
- }
-
- private IDictionary<TypeVariable!, Type!>! TypeParamSubstitution() {
- assume TypeParameters != null;
- IDictionary<TypeVariable!, Type!>! res = new Dictionary<TypeVariable!, Type!> ();
- foreach (TypeVariable! v in TypeParameters.FormalTypeParams)
- res.Add(v, TypeParameters[v]);
- return res;
- }
-
- protected override Cmd! ComputeDesugaring() {
- CmdSeq newBlockBody = new CmdSeq();
- Hashtable /*Variable -> Expr*/ substMap = new Hashtable/*Variable -> Expr*/();
- Hashtable /*Variable -> Expr*/ substMapOld = new Hashtable/*Variable -> Expr*/();
- Hashtable /*Variable -> Expr*/ substMapBound = new Hashtable/*Variable -> Expr*/();
- VariableSeq! tempVars = new VariableSeq();
-
- // proc P(ins) returns (outs)
- // requires Pre
- // modifies frame
- // ensures Post
- //
- // call aouts := P(ains)
-
- // ins : formal in parameters of procedure
- // frame : a list of global variables from the modifies clause
- // outs : formal out parameters of procedure
- // ains : actual in arguments passed to call
- // aouts : actual variables assigned to from call
- // cins : new variables created just for this call, one per ains
- // cframe : new variables created just for this call, to keep track of OLD values
- // couts : new variables created just for this call, one per aouts
- // WildcardVars : new variables created just for this call, one per null in ains
-
- #region Create cins; each one is an incarnation of the corresponding in parameter
- VariableSeq! cins = new VariableSeq();
- VariableSeq wildcardVars = new VariableSeq();
- assume this.Proc != null;
- for (int i = 0; i < this.Proc.InParams.Length; ++i)
- {
- Variable! param = (!)this.Proc.InParams[i];
- bool isWildcard = this.Ins[i] == null;
-
- Type! actualType;
- if (isWildcard)
- actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
- else
- // during type checking, we have ensured that the type of the actual
- // parameter Ins[i] is correct, so we can use it here
- actualType = (!)((!)Ins[i]).Type;
-
- Variable cin = CreateTemporaryVariable(tempVars, param, actualType,
- TempVarKind.Formal);
- cins.Add(cin);
- IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
- substMap.Add(param, ie);
- if (isWildcard) {
- cin = CreateTemporaryVariable(tempVars, param,
- actualType, TempVarKind.Bound);
- wildcardVars.Add(cin);
- ie = new IdentifierExpr(cin.tok, cin);
- }
- substMapBound.Add(param, ie);
- }
- #endregion
- #region call aouts := P(ains) becomes: (open outlining one level to see)
- #region cins := ains (or havoc cin when ain is null)
- for (int i = 0, n = this.Ins.Count; i < n; i++)
- {
- IdentifierExpr! cin_exp = new IdentifierExpr(((!)cins[i]).tok, (!) cins[i]);
- if (this.Ins[i] != null) {
- AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, (!) this.Ins[i]);
- newBlockBody.Add(assign);
- } else {
- IdentifierExprSeq! ies = new IdentifierExprSeq();
- ies.Add(cin_exp);
- HavocCmd havoc = new HavocCmd(Token.NoToken, ies);
- newBlockBody.Add(havoc);
- }
- }
- #endregion
-
- #region assert (exists wildcardVars :: Pre[ins := cins])
- Substitution s = Substituter.SubstitutionFromHashtable(substMapBound);
- bool hasWildcard = (wildcardVars.Length != 0);
- Expr preConjunction = null;
- for (int i = 0; i < this.Proc.Requires.Length; i++)
- {
- Requires! req = (!) this.Proc.Requires[i];
- if (!req.Free) {
- if (hasWildcard) {
- Expr pre = Substituter.Apply(s, req.Condition);
- if (preConjunction == null) {
- preConjunction = pre;
- } else {
- preConjunction = Expr.And(preConjunction, pre);
- }
- } else {
- Requires! reqCopy = (Requires!) req.Clone();
- reqCopy.Condition = Substituter.Apply(s, req.Condition);
- AssertCmd! a = new AssertRequiresCmd(this, reqCopy);
- a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
- newBlockBody.Add(a);
- }
- }
- }
- if (hasWildcard) {
- if (preConjunction == null) {
- preConjunction = Expr.True;
- }
- Expr! expr = new ExistsExpr(tok, wildcardVars, preConjunction);
- AssertCmd! a = new AssertCmd(tok, expr);
- a.ErrorDataEnhanced = AssertCmd.GenerateBoundVarMiningStrategy(expr);
- newBlockBody.Add(a);
- }
- #endregion
-
- #region assume Pre[ins := cins] with formal paramters
- if (hasWildcard) {
- s = Substituter.SubstitutionFromHashtable(substMap);
- for (int i = 0; i < this.Proc.Requires.Length; i++)
- {
- Requires! req = (!) this.Proc.Requires[i];
- if (!req.Free) {
- Requires! reqCopy = (Requires!) req.Clone();
- reqCopy.Condition = Substituter.Apply(s, req.Condition);
- AssumeCmd! a = new AssumeCmd(tok, reqCopy.Condition);
- newBlockBody.Add(a);
- }
- }
- }
- #endregion
-
- #region cframe := frame (to hold onto frame values in case they are referred to in the postcondition)
- IdentifierExprSeq havocVarExprs = new IdentifierExprSeq();
-
- foreach (IdentifierExpr! f in this.Proc.Modifies)
- {
- assume f.Decl != null;
- assert f.Type != null;
- Variable v = CreateTemporaryVariable(tempVars, f.Decl, f.Type, TempVarKind.Old);
- IdentifierExpr v_exp = new IdentifierExpr(v.tok, v);
- substMapOld.Add(f.Decl, v_exp); // this assumes no duplicates in this.Proc.Modifies
- AssignCmd assign = Cmd.SimpleAssign(f.tok, v_exp, f);
- newBlockBody.Add(assign);
-
- // fra
- if(!havocVarExprs.Has(f))
- havocVarExprs.Add(f);
- }
- #endregion
- #region Create couts
- VariableSeq! couts = new VariableSeq();
- for (int i = 0; i < this.Proc.OutParams.Length; ++i)
- {
- Variable! param = (!)this.Proc.OutParams[i];
- bool isWildcard = this.Outs[i] == null;
-
- Type! actualType;
- if (isWildcard)
- actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution());
- else
- // during type checking, we have ensured that the type of the actual
- // out parameter Outs[i] is correct, so we can use it here
- actualType = (!)((!)Outs[i]).Type;
-
- Variable cout = CreateTemporaryVariable(tempVars, param, actualType,
- TempVarKind.Formal);
- couts.Add(cout);
- IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
- substMap.Add(param, ie);
-
- if(!havocVarExprs.Has(ie))
- havocVarExprs.Add(ie);
- }
- // add the where clauses, now that we have the entire substitution map
- foreach (Variable! param in this.Proc.OutParams) {
- Expr w = param.TypedIdent.WhereExpr;
- if (w != null) {
- IdentifierExpr ie = (IdentifierExpr!)substMap[param];
- assert ie.Decl != null;
- ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
- }
- }
- #endregion
-
- #region havoc frame, couts
- // pass on this's token
- HavocCmd hc = new HavocCmd(this.tok, havocVarExprs);
- newBlockBody.Add(hc);
- #endregion
-
- #region assume Post[ins, outs, old(frame) := cins, couts, cframe]
- Substitution s2 = Substituter.SubstitutionFromHashtable(substMap);
- Substitution s2old = Substituter.SubstitutionFromHashtable(substMapOld);
- foreach (Ensures! e in this.Proc.Ensures)
- {
- Expr copy = Substituter.ApplyReplacingOldExprs(s2, s2old, e.Condition);
- AssumeCmd assume = new AssumeCmd(this.tok, copy);
- newBlockBody.Add(assume);
- }
- #endregion
-
- #region aouts := couts
- for (int i = 0, n = this.Outs.Count; i < n; i++)
- {
- if (this.Outs[i]!=null) {
- Variable! param_i = (!) this.Proc.OutParams[i];
- Expr! cout_exp = new IdentifierExpr(((!)couts[i]).tok, (!) couts[i]);
- AssignCmd assign = Cmd.SimpleAssign(param_i.tok, (!) this.Outs[i], cout_exp);
- newBlockBody.Add(assign);
- }
- }
- #endregion
- #endregion
-
- return new StateCmd(this.tok, tempVars, newBlockBody);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitCallCmd(this);
- }
- }
-
- public class CallForallCmd : CallCommonality
- {
- string! callee;
- public Procedure Proc;
- public List<Expr>! Ins;
-
- // the types of the formal in-parameters after instantiating all
- // type variables whose value could be inferred using the given
- // actual non-wildcard arguments
- public TypeSeq InstantiatedTypes;
-
- public CallForallCmd(IToken! tok, string! callee, List<Expr>! ins)
- {
- base(tok, null);
- this.callee = callee;
- this.Ins = ins;
- }
- public CallForallCmd(IToken! tok, string! callee, List<Expr>! ins, QKeyValue kv)
- {
- base(tok, kv);
- this.callee = callee;
- this.Ins = ins;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "call ");
- EmitAttributes(stream, Attributes);
- stream.Write("forall ");
- stream.Write(TokenTextWriter.SanitizeIdentifier(callee));
- stream.Write("(");
- string sep = "";
- foreach (Expr arg in Ins) {
- stream.Write(sep);
- sep = ", ";
- if (arg == null) {
- stream.Write("*");
- } else {
- arg.Emit(stream);
- }
- }
- stream.WriteLine(");");
- base.Emit(stream, level);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- if (Proc != null) {
- // already resolved
- return;
- }
- ResolveAttributes(Attributes, rc);
- Proc = rc.LookUpProcedure(callee) as Procedure;
- if (Proc == null) {
- rc.Error(this, "call to undeclared procedure: {0}", callee);
- }
- foreach (Expr e in Ins) {
- if (e != null) {
- e.Resolve(rc);
- }
- }
- }
- public override void AddAssignedVariables(VariableSeq! vars) { }
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(Attributes, tc);
- // typecheck in-parameters
- foreach (Expr e in Ins) {
- if (e != null) {
- e.Typecheck(tc);
- }
- }
-
- if (this.Proc == null)
- {
- // called procedure didn't resolve, so bug out
- return;
- }
-
- // match actuals with formals
- if (Ins.Count != Proc.InParams.Length)
- {
- tc.Error(this, "wrong number of in-parameters in call: {0}", callee);
- }
- else
- {
- // determine the lists of formal and actual arguments that need
- // to be matched (stars are left out)
- TypeSeq! formalTypes = new TypeSeq ();
- ExprSeq! actualArgs = new ExprSeq ();
- for (int i = 0; i < Ins.Count; i++)
- if (Ins[i] != null) {
- formalTypes.Add(((!)Proc.InParams[i]).TypedIdent.Type);
- actualArgs.Add(Ins[i]);
- }
- IDictionary<TypeVariable!, Type!>! subst =
- Type.MatchArgumentTypes(Proc.TypeParameters,
- formalTypes, actualArgs, null, null,
- "call forall to " + callee, tc);
-
- InstantiatedTypes = new TypeSeq ();
- foreach (Variable! var in Proc.InParams) {
- InstantiatedTypes.Add(var.TypedIdent.Type.Substitute(subst));
- }
- }
-
-// if (Proc.OutParams.Length != 0)
-// {
-// tc.Error(this, "call forall is allowed only on procedures with no out-parameters: {0}", callee);
-// }
-
- if (Proc.Modifies.Length != 0)
- {
- tc.Error(this, "call forall is allowed only on procedures with no modifies clause: {0}", callee);
- }
- }
-
- protected override Cmd! ComputeDesugaring() {
- CmdSeq newBlockBody = new CmdSeq();
- Hashtable /*Variable -> Expr*/ substMap = new Hashtable/*Variable -> Expr*/();
- VariableSeq! tempVars = new VariableSeq();
-
- // proc P(ins) returns ()
- // requires Pre;
- // modifies ;
- // ensures Post;
- //
- // call forall P(ains);
-
- // ins : formal in-parameters of procedure
- // ains : actual in-arguments passed to call
- // cins : new variables created just for this call, one per ains
- // wildcardVars : the bound variables to be wrapped up in a quantification
-
- #region Create cins; each one is an incarnation of the corresponding in parameter
- VariableSeq! cins = new VariableSeq();
- VariableSeq wildcardVars = new VariableSeq();
- assume this.Proc != null;
- for (int i = 0, n = this.Proc.InParams.Length; i < n; i++) {
- Variable param = (!)this.Proc.InParams[i];
- Type! paramType = ((!)this.InstantiatedTypes)[i]; // might contain type variables
- bool isWildcard = this.Ins[i] == null;
- Variable cin = CreateTemporaryVariable(tempVars, param, paramType,
- isWildcard ? TempVarKind.Bound : TempVarKind.Formal);
- if (isWildcard) {
- cins.Add(null);
- wildcardVars.Add(cin);
- } else {
- cins.Add(cin);
- }
- IdentifierExpr ie = new IdentifierExpr(cin.tok, cin);
- substMap.Add(param, ie);
- }
- #endregion
-
- #region call forall P(ains) becomes: (open outlining one level to see)
- #region cins := ains
- for (int i = 0, n = this.Ins.Count; i < n; i++)
- {
- if (this.Ins[i] != null) {
- IdentifierExpr! cin_exp = new IdentifierExpr(((!)cins[i]).tok, (!) cins[i]);
- AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, (!) this.Ins[i]);
- newBlockBody.Add(assign);
- }
- }
- #endregion
-
- #region assert Pre[ins := cins]
- Substitution s = Substituter.SubstitutionFromHashtable(substMap);
- Expr preConjunction = null;
- for (int i = 0; i < this.Proc.Requires.Length; i++)
- {
- Requires! req = (!) this.Proc.Requires[i];
- if (!req.Free) {
- Expr pre = Substituter.Apply(s, req.Condition);
- if (preConjunction == null) {
- preConjunction = pre;
- } else {
- preConjunction = Expr.And(preConjunction, pre);
- }
- }
- }
- if (preConjunction == null) {
- preConjunction = Expr.True;
- }
- #endregion
-
- #region Create couts
- VariableSeq! couts = new VariableSeq();
- foreach ( Variable! param in this.Proc.OutParams )
- {
- Variable cout = CreateTemporaryVariable(tempVars, param,
- param.TypedIdent.Type, TempVarKind.Bound);
- couts.Add(cout);
- IdentifierExpr ie = new IdentifierExpr(cout.tok, cout);
- substMap.Add(param, ie);
- }
- // add the where clauses, now that we have the entire substitution map
- foreach (Variable! param in this.Proc.OutParams) {
- Expr w = param.TypedIdent.WhereExpr;
- if (w != null) {
- IdentifierExpr ie = (IdentifierExpr!)substMap[param];
- assert ie.Decl != null;
- ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w);
- }
- }
- #endregion
-
- #region assume Post[ins := cins]
- s = Substituter.SubstitutionFromHashtable(substMap);
- Expr postConjunction = null;
- foreach (Ensures! e in this.Proc.Ensures)
- {
- Expr post = Substituter.Apply(s, e.Condition);
- if (postConjunction == null) {
- postConjunction = post;
- } else {
- postConjunction = Expr.And(postConjunction, post);
- }
- }
- if (postConjunction == null) {
- postConjunction = Expr.True;
- }
- #endregion
-
- #region assume (forall wildcardVars :: Pre ==> Post);
- Expr body = postConjunction;
- if (couts.Length > 0) {
- body = new ExistsExpr(tok, couts, body);
- }
- body = Expr.Imp(preConjunction, body);
- if (wildcardVars.Length != 0) {
- TypeVariableSeq! typeParams = Type.FreeVariablesIn((!)InstantiatedTypes);
- body = new ForallExpr(tok, typeParams, wildcardVars, body);
- }
- newBlockBody.Add(new AssumeCmd(tok, body));
- #endregion
- #endregion
-
- return new StateCmd(this.tok, tempVars, newBlockBody);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitCallForallCmd(this);
- }
- }
-
- public abstract class PredicateCmd : Cmd
- {
- public /*readonly--except in StandardVisitor*/ Expr! Expr;
- public PredicateCmd(IToken! tok, Expr! expr)
- : base(tok)
- {
- Expr = expr;
- }
- public override void Resolve(ResolutionContext! rc)
- {
- Expr.Resolve(rc);
- }
- public override void AddAssignedVariables(VariableSeq! vars) { }
- }
-
- public abstract class MiningStrategy {
- // abstract class to bind all MiningStrategys, i.e., all types of enhanced error data
- // types together
- }
-
- public class ListOfMiningStrategies : MiningStrategy {
- public List<MiningStrategy>! msList;
-
- public ListOfMiningStrategies (List<MiningStrategy>! l) {
- this.msList = l;
- }
- }
-
- public class EEDTemplate : MiningStrategy {
- public string! reason;
- public List<Expr!>! exprList;
-
- public EEDTemplate (string! reason, List<Expr!>! exprList) {
- this.reason = reason;
- this.exprList = exprList;
- }
- }
-
- public class AssertCmd : PredicateCmd, IPotentialErrorNode
- {
- public Expr OrigExpr;
- public Hashtable /*Variable -> Expr*/ IncarnationMap;
-
- // TODO: convert to use generics
- private object errorData;
- public object ErrorData {
- get { return errorData; }
- set { errorData = value; }
- }
-
- public string ErrorMessage {
- get {
- return QKeyValue.FindStringAttribute(Attributes, "msg");
- }
- }
-
- public QKeyValue Attributes;
-
- private MiningStrategy errorDataEnhanced;
- public MiningStrategy ErrorDataEnhanced {
- get { return errorDataEnhanced; }
- set { errorDataEnhanced = value; }
- }
-
- public AssertCmd(IToken! tok, Expr! expr)
- : base(tok, expr)
- {
- errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
- }
-
- public AssertCmd(IToken! tok, Expr! expr, QKeyValue kv)
- : base(tok, expr)
- {
- errorDataEnhanced = GenerateBoundVarMiningStrategy(expr);
- Attributes = kv;
- }
-
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "assert ");
- EmitAttributes(stream, Attributes);
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext! rc)
- {
- ResolveAttributes(Attributes, rc);
- base.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- TypecheckAttributes(Attributes, tc);
- Expr.Typecheck(tc);
- assert Expr.Type != null; // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool))
- {
- tc.Error(this, "an asserted expression must be of type bool (got: {0})", Expr.Type);
- }
- }
-
- public static MiningStrategy GenerateBoundVarMiningStrategy (Expr! expr) {
- List<MiningStrategy> l = new List<MiningStrategy>();
- if (expr != null) {
- l = GenerateBoundVarListForMining(expr, l);
- }
- return new ListOfMiningStrategies(l);
- }
-
- public static List<MiningStrategy>! GenerateBoundVarListForMining (Expr! expr, List<MiningStrategy>! l) {
- // go through the origExpr and identify all bound variables in the AST.
- if (expr is LiteralExpr || expr is IdentifierExpr) {
- //end recursion
- }
- else if (expr is NAryExpr) {
- NAryExpr e = (NAryExpr)expr;
- foreach (Expr! arg in e.Args) {
- l = GenerateBoundVarListForMining(arg, l);
- }
- }
- else if (expr is OldExpr) {
- OldExpr e = (OldExpr)expr;
- l = GenerateBoundVarListForMining(e.Expr, l);
- }
- else if (expr is QuantifierExpr) {
- QuantifierExpr qe = (QuantifierExpr) expr;
- VariableSeq vs = qe.Dummies;
- foreach (Variable! x in vs) {
- string name = x.Name;
- if (name.StartsWith("^")) {
- name = name.Substring(1);
- List<Expr!> exprList = new List<Expr!>();
- exprList.Add(new IdentifierExpr(Token.NoToken, x.ToString(), x.TypedIdent.Type));
- MiningStrategy eed = new EEDTemplate("The bound variable " + name + " has the value {0}.", exprList);
- l.Add(eed);
- }
- }
- l = GenerateBoundVarListForMining(qe.Body, l);
- }
- return l;
- }
-
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAssertCmd(this);
- }
- }
-
- // An AssertCmd that is a loop invariant check before the loop iteration starts
- public class LoopInitAssertCmd : AssertCmd
- {
- public LoopInitAssertCmd(IToken! tok, Expr! expr)
- : base(tok, expr)
- {
- }
- }
-
- // An AssertCmd that is a loop invariant check to maintain the invariant after iteration
- public class LoopInvMaintainedAssertCmd : AssertCmd
- {
- public LoopInvMaintainedAssertCmd(IToken! tok, Expr! expr)
- : base(tok, expr)
- {
- }
- }
-
- /// <summary>
- /// An AssertCmd that is introduced in translation from the requires on a call.
- /// </summary>
- public class AssertRequiresCmd : AssertCmd
- {
- public CallCmd! Call;
- public Requires! Requires;
-
- public AssertRequiresCmd(CallCmd! call, Requires! @requires)
- : base(call.tok, @requires.Condition)
- {
- this.Call = call;
- this.Requires = @requires;
- // base(call.tok, @requires.Condition);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAssertRequiresCmd(this);
- }
- }
-
- /// <summary>
- /// An AssertCmd that is introduced in translation from an ensures
- /// declaration.
- /// </summary>
- public class AssertEnsuresCmd : AssertCmd
- {
- public Ensures! Ensures;
- public AssertEnsuresCmd(Ensures! ens)
- : base(ens.tok, ens.Condition)
- {
- this.Ensures = ens;
- // base(ens.tok, ens.Condition);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAssertEnsuresCmd(this);
- }
- }
-
- public class AssumeCmd : PredicateCmd
- {
- public AssumeCmd(IToken! tok, Expr! expr)
- : base(tok, expr)
- {
- //Debug.Assert(expr != null);
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "assume ");
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- Expr.Typecheck(tc);
- assert Expr.Type != null; // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool))
- {
- tc.Error(this, "an assumed expression must be of type bool (got: {0})", Expr.Type);
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAssumeCmd(this);
- }
- }
-
- public class ReturnExprCmd : ReturnCmd
- {
- public Expr! Expr;
- public ReturnExprCmd(IToken! tok, Expr! expr)
- : base(tok)
- {
- Expr = expr;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "return ");
- this.Expr.Emit(stream);
- stream.WriteLine(";");
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- Expr.Typecheck(tc);
- assert Expr.Type != null; // follows from Expr.Typecheck postcondition
- if (!Expr.Type.Unify(Type.Bool))
- {
- tc.Error(this, "a return expression must be of type bool (got: {0})", Expr.Type);
- }
- }
- public override void Resolve(ResolutionContext! rc)
- {
- Expr.Resolve(rc);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitReturnExprCmd(this);
- }
- }
-
- public class HavocCmd : Cmd
- {
- public IdentifierExprSeq! Vars;
- public HavocCmd(IToken! tok, IdentifierExprSeq! vars)
- : base(tok)
- {
- Vars = vars;
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.Write(this, level, "havoc ");
- Vars.Emit(stream, true);
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext! rc)
- {
- foreach (IdentifierExpr! ide in Vars)
- {
- ide.Resolve(rc);
- }
- }
- public override void AddAssignedVariables(VariableSeq! vars)
- {
- foreach (IdentifierExpr! e in this.Vars)
- {
- vars.Add(e.Decl);
- }
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- this.CheckAssignments(tc);
- }
-
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitHavocCmd(this);
- }
- }
-
- //---------------------------------------------------------------------
- // Transfer commands
-
- public abstract class TransferCmd : Absy
- {
- internal TransferCmd(IToken! tok)
- : base(tok)
- {
- }
- public abstract void Emit(TokenTextWriter! stream, int level);
- public override void Typecheck(TypecheckingContext! tc)
- {
- // nothing to typecheck
- }
- }
-
- public class ReturnCmd : TransferCmd
- {
- public ReturnCmd(IToken! tok)
- : base(tok)
- {
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- stream.WriteLine(this, level, "return;");
- }
- public override void Resolve(ResolutionContext! rc)
- {
- // nothing to resolve
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitReturnCmd(this);
- }
- }
-
- public class GotoCmd : TransferCmd
- {
- [Rep]
- public StringSeq labelNames;
- [Rep]
- public BlockSeq labelTargets;
-
- invariant labelNames != null && labelTargets != null ==> labelNames.Length == labelTargets.Length;
-
- [NotDelayed]
- public GotoCmd(IToken! tok, StringSeq! labelSeq)
- : base (tok)
- {
- this.labelNames = labelSeq;
- }
- public GotoCmd(IToken! tok, StringSeq! labelSeq, BlockSeq! blockSeq)
- : base (tok)
- {
- Debug.Assert(labelSeq.Length == blockSeq.Length);
- for (int i=0; i<labelSeq.Length; i++) { Debug.Assert(Equals(labelSeq[i], ((!)blockSeq[i]).Label)); }
-
- this.labelNames = labelSeq;
- this.labelTargets = blockSeq;
- }
- public GotoCmd(IToken! tok, BlockSeq! blockSeq)
- : base (tok)
- { //requires blockSeq[i] != null ==> blockSeq[i].Label != null;
- StringSeq labelSeq = new StringSeq();
- for (int i=0; i<blockSeq.Length; i++)
- labelSeq.Add(((!)blockSeq[i]).Label);
- this.labelNames = labelSeq;
- this.labelTargets = blockSeq;
- }
- public void AddTarget(Block! b)
- requires b.Label != null;
- requires this.labelTargets != null;
- requires this.labelNames != null;
- {
- this.labelTargets.Add(b);
- this.labelNames.Add(b.Label);
- }
- public override void Emit(TokenTextWriter! stream, int level)
- {
- assume this.labelNames != null;
- stream.Write(this, level, "goto ");
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
- {
- if (labelTargets == null)
- {
- string sep = "";
- foreach (string name in labelNames)
- {
- stream.Write("{0}{1}^^{2}", sep, "NoDecl", name);
- sep = ", ";
- }
- }
- else
- {
- string sep = "";
- foreach (Block! b in labelTargets)
- {
- stream.Write("{0}h{1}^^{2}", sep, b.GetHashCode(), b.Label);
- sep = ", ";
- }
- }
- }
- else
- {
- labelNames.Emit(stream);
- }
- stream.WriteLine(";");
- }
- public override void Resolve(ResolutionContext! rc)
- ensures labelTargets != null;
- {
- if (labelTargets != null)
- {
- // already resolved
- return;
- }
- assume this.labelNames != null;
- labelTargets = new BlockSeq();
- foreach (string! lbl in labelNames)
- {
- Block b = rc.LookUpBlock(lbl);
- if (b == null)
- {
- rc.Error(this, "goto to unknown block: {0}", lbl);
- }
- else
- {
- labelTargets.Add(b);
- }
- }
- Debug.Assert(rc.ErrorCount > 0 || labelTargets.Length == labelNames.Length);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitGotoCmd(this);
- }
- }
-
-}
diff --git a/Source/Core/AbsyExpr.ssc b/Source/Core/AbsyExpr.ssc
deleted file mode 100644
index 250820ed..00000000
--- a/Source/Core/AbsyExpr.ssc
+++ /dev/null
@@ -1,2430 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie
-{
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.Contracts;
- using Microsoft.Basetypes;
-
-
- //---------------------------------------------------------------------
- // Expressions
- //
- // For expressions, we override the Equals and GetHashCode method to
- // implement structural equality. Note this is not logical equivalence
- // and is not modulo alpha-renaming.
- //---------------------------------------------------------------------
-
-
- public abstract class Expr : Absy
- {
- public Expr(IToken! tok)
- : base(tok)
- {
- }
-
- public void Emit (TokenTextWriter! stream)
- {
- Emit(stream, 0, false);
- }
-
- public abstract void Emit (TokenTextWriter! wr, int contextBindingStrength, bool fragileContext);
-
- [Pure]
- public override string! ToString ()
- {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false))
- {
- this.Emit(stream, 0, false);
- }
- return buffer.ToString();
- }
-
- /// <summary>
- /// Add to "freeVars" the free variables in the expression.
- /// </summary>
- public abstract void ComputeFreeVariables(Set /*Variable*/! freeVars);
-
- /// <summary>
- /// Filled in by the Typecheck method. A value of "null" means a succeeding
- /// call to Typecheck has not taken place (that is, either Typecheck hasn't
- /// been called or Typecheck encountered an error in the expression to be
- /// typechecked).
- /// </summary>
- public Type Type;
-
- public override void Typecheck (TypecheckingContext! tc)
- ensures Type != null;
- {
- // This body is added only because C# insists on it. It should really be left out, as if TypeCheck still were abstract.
- // The reason for mentioning the method here at all is to give TypeCheck a postcondition for all expressions.
- assert false;
- }
-
- /// <summary>
- /// Returns the type of the expression, supposing that all its subexpressions are well typed.
- /// </summary>
- public abstract Type! ShallowType { get; }
-
- // Handy syntactic sugar follows:
-
- public static NAryExpr! Unary (IToken! x, UnaryOperator.Opcode op, Expr! e1)
- {
- return new NAryExpr(x, new UnaryOperator(x, op), new ExprSeq(e1));
- }
-
- public static NAryExpr! Binary (IToken! x, BinaryOperator.Opcode op, Expr! e0, Expr! e1)
- {
- return new NAryExpr(x, new BinaryOperator(x, op), new ExprSeq(e0, e1));
- }
-
- public static NAryExpr! Binary (BinaryOperator.Opcode op, Expr! e0, Expr! e1)
- {
- return Binary(Token.NoToken, op, e0, e1);
- }
-
- public static NAryExpr! Eq (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Eq, e1, e2); }
- public static NAryExpr! Neq (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Neq, e1, e2); }
- public static NAryExpr! Le (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Le, e1, e2); }
- public static NAryExpr! Ge (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Ge, e1, e2); }
- public static NAryExpr! Lt (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Lt, e1, e2); }
- public static NAryExpr! Gt (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Gt, e1, e2); }
- public static Expr! And (Expr! e1, Expr! e2) {
- if (e1 == true_) { return e2; }
- else if (e2 == true_) { return e1; }
- else if (e1 == false_ || e2 == false_) { return false_; }
- else { return Binary(BinaryOperator.Opcode.And, e1, e2); }
- }
- public static Expr! Or (Expr! e1, Expr! e2) {
- if (e1 == false_) { return e2; }
- else if (e2 == false_) { return e1; }
- else if (e1 == true_ || e2 == true_) { return true_; }
- else { return Binary(BinaryOperator.Opcode.Or, e1, e2); }
- }
- public static Expr! Not (Expr! e1) {
- NAryExpr nary = e1 as NAryExpr;
-
- if (e1 == true_) { return false_; }
- else if (e1 == false_) { return true_; }
- else if (nary != null)
- {
- if (nary.Fun is UnaryOperator)
- {
- UnaryOperator op = (UnaryOperator)nary.Fun;
- if (op.Op == UnaryOperator.Opcode.Not) { return (!) nary.Args[0]; }
- }
- else if (nary.Fun is BinaryOperator)
- {
- BinaryOperator op = (BinaryOperator)nary.Fun;
- Expr arg0 = (!)nary.Args[0];
- Expr arg1 = (!)nary.Args[1];
- if (op.Op == BinaryOperator.Opcode.Eq) { return Neq(arg0, arg1); }
- else if (op.Op == BinaryOperator.Opcode.Neq) { return Eq(arg0, arg1); }
- else if (op.Op == BinaryOperator.Opcode.Lt) { return Ge(arg0, arg1); }
- else if (op.Op == BinaryOperator.Opcode.Le) { return Gt(arg0, arg1); }
- else if (op.Op == BinaryOperator.Opcode.Ge) { return Lt(arg0, arg1); }
- else if (op.Op == BinaryOperator.Opcode.Gt) { return Le(arg0, arg1); }
- }
- }
-
- return Unary(Token.NoToken, UnaryOperator.Opcode.Not, e1);
- }
- public static NAryExpr! Imp (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Imp, e1, e2); }
- public static NAryExpr! Iff (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Iff, e1, e2); }
- public static NAryExpr! Add (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Add, e1, e2); }
- public static NAryExpr! Sub (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Sub, e1, e2); }
- public static NAryExpr! Mul (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Mul, e1, e2); }
- public static NAryExpr! Div (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Div, e1, e2); }
- public static NAryExpr! Mod (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Mod, e1, e2); }
- public static NAryExpr! Subtype (Expr! e1, Expr! e2) { return Binary(BinaryOperator.Opcode.Subtype, e1, e2); }
-
- public static IdentifierExpr! Ident (string! name, Type! type)
- {
- return new IdentifierExpr(Token.NoToken, name, type);
- }
-
- public static IdentifierExpr! Ident (Variable! decl)
- {
- IdentifierExpr result = new IdentifierExpr(Token.NoToken, decl);
- return result;
- }
-
- public static LiteralExpr! Literal (bool value) { return new LiteralExpr(Token.NoToken, value); }
- public static LiteralExpr! Literal (int value) { return new LiteralExpr(Token.NoToken, BigNum.FromInt(value)); }
- public static LiteralExpr! Literal (BigNum value) { return new LiteralExpr(Token.NoToken, value); }
-
- private static LiteralExpr! true_ = Literal(true);
- public static LiteralExpr! True { get { return true_; } }
-
- private static LiteralExpr! false_ = Literal(false);
- public static LiteralExpr! False { get { return false_; } }
-
-
- public static NAryExpr! Select(Expr! map, params Expr[]! args) {
- return SelectTok(Token.NoToken, map, args);
- }
-
- public static NAryExpr! Select(Expr! map, List<Expr!>! args) {
- return Select(map, args.ToArray());
- }
-
- // use a different name for this variant of the method
- // (-> some bug prevents overloading in this case)
- public static NAryExpr! SelectTok(IToken! x, Expr! map, params Expr[]! args)
- {
- ExprSeq! allArgs = new ExprSeq ();
- allArgs.Add(map);
- foreach (Expr! a in args)
- allArgs.Add(a);
- return new NAryExpr(x, new MapSelect(Token.NoToken, args.Length), allArgs);
- }
-
- public static NAryExpr! Store(Expr! map, params Expr[]! args) {
- return StoreTok(Token.NoToken, map, args);
- }
-
- public static NAryExpr! Store(Expr! map, List<Expr!>! indexes, Expr! rhs) {
- Expr[]! allArgs = new Expr [indexes.Count + 1];
- for (int i = 0; i < indexes.Count; ++i)
- allArgs[i] = indexes[i];
- allArgs[indexes.Count] = rhs;
- return Store(map, allArgs);
- }
-
- // use a different name for this variant of the method
- // (-> some bug prevents overloading in this case)
- public static NAryExpr! StoreTok(IToken! x, Expr! map, params Expr[]! args)
- requires args.Length > 0; // zero or more indices, plus the value
- {
- ExprSeq! allArgs = new ExprSeq ();
- allArgs.Add(map);
- foreach (Expr! a in args)
- allArgs.Add(a);
- return new NAryExpr(x, new MapStore(Token.NoToken, args.Length - 1), allArgs);
- }
-
- public static NAryExpr! CoerceType(IToken! x, Expr! subexpr, Type! type) {
- ExprSeq! args = new ExprSeq ();
- args.Add(subexpr);
- return new NAryExpr(x, new TypeCoercion(x, type), args);
- }
-
-
- /// <summary>
- /// This property returns a representation for the expression suitable for use
- /// by the AIFramework. Usually, the property just returns "this", but not
- /// every Expr is an AI.IExpr (besides, AI.IExpr is to be thought of as an
- /// abstract interface--any class that implements AI.IExpr is supposed to
- /// implement some proper subinterface of AI.IExpr).
- /// The converse operations of this property are found in AbsInt\ExprFactories.ssc.
- /// </summary>
- public abstract AI.IExpr! IExpr {
- [Peer] get;
- }
-
- }
-
- public class LiteralExpr : Expr, AI.IFunApp
- {
- public readonly object! Val; // false, true, a BigNum, or a BvConst
- /// <summary>
- /// Creates a literal expression for the boolean value "b".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="b"></param>
- public LiteralExpr(IToken! tok, bool b)
- : base(tok)
- {
- Val = b;
- }
- /// <summary>
- /// Creates a literal expression for the integer value "v".
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="v"></param>
- public LiteralExpr(IToken! tok, BigNum v)
- : base(tok)
- {
- Val = v;
- }
-
- /// <summary>
- /// Creates a literal expression for the bitvector value "v".
- /// </summary>
- public LiteralExpr(IToken! tok, BigNum v, int b)
- : base(tok)
- {
- Val = new BvConst(v, b);
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is LiteralExpr)) return false;
-
- LiteralExpr other = (LiteralExpr)obj;
- return object.Equals(this.Val, other.Val);
- }
- [Pure]
- public override int GetHashCode()
- {
- return this.Val.GetHashCode();
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(this);
- if (this.Val is bool)
- {
- stream.Write((bool)this.Val ? "true" : "false"); // correct capitalization
- }
- else
- {
- stream.Write((!) this.Val.ToString());
- }
- }
- public override void Resolve(ResolutionContext! rc)
- {
- // nothing to resolve
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- // no free variables to add
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- if (Val is BvConst && CommandLineOptions.Clo.Verify && CommandLineOptions.Clo.Bitvectors == CommandLineOptions.BvHandling.None)
- tc.Error(this, "no bitvector handling specified, please use /bv:i or /bv:z flag");
- this.Type = ShallowType;
- }
-
- public override Type! ShallowType {
- get {
- if (Val is bool)
- {
- return Type.Bool;
- }
- else if (Val is BigNum)
- {
- return Type.Int;
- }
- else if (Val is BvConst)
- {
- return Type.GetBvType(((BvConst)Val).Bits);
- }
- else
- {
- assert false; // like, where did this value come from?!
- }
- }
- }
-
- public bool IsFalse {
- get {
- return Val is bool && ((bool)Val) == false;
- }
- }
- public bool IsTrue {
- get {
- return Val is bool && ((bool)Val) == true;
- }
- }
- public override AI.IExpr! IExpr {
- get {
- return this;
- }
- }
-
- // should be eliminated after converting everything to BigNums
- private int asInt {
- get {
- return asBigNum.ToIntSafe;
- }
- }
-
- public bool isBigNum {
- get {
- return Val is BigNum;
- }
- }
-
- public BigNum asBigNum {
- get {
- assert isBigNum;
- return (BigNum)(!)Val;
- }
- }
-
- public bool isBool {
- get {
- return Val is bool;
- }
- }
-
- public bool asBool {
- get {
- assert isBool;
- return (bool)(!)Val;
- }
- }
-
- public AI.IFunctionSymbol! FunctionSymbol {
- get {
- if (Val is bool)
- {
- if ((bool)Val)
- {
- return AI.Prop.True;
- }
- else
- {
- return AI.Prop.False;
- }
- }
- else if (Val is BigNum)
- {
- return AI.Int.Const((BigNum)Val);
- }
- else if (Val is BvConst)
- {
- return AI.Bv.Const(((BvConst)Val).Value, ((BvConst)Val).Bits);
- }
- else
- {
- assert false; // like, where did this value come from?!
- }
- }
- }
- public IList/*<AI.IExpr!>*/! Arguments {
- get {
- return ArrayList.ReadOnly(new AI.IExpr[0]);
- }
- }
- public Microsoft.AbstractInterpretationFramework.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args) {
- assert args.Count == 0;
- return this;
- }
- public AI.AIType! AIType {
- get {
- if (Val is bool) {
- return AI.Prop.Type;
- } else if (Val is BigNum) {
- return AI.Int.Type;
- } else if (Val is BvConst) {
- return AI.Bv.Type;
- } else {
- assert false; // like, where did this value come from?!
- }
- }
- }
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitLiteralExpr(this);
- }
- }
-
- public class BvConst
- {
- public BigNum Value;
- public int Bits;
-
- public BvConst(BigNum v, int b)
- {
- assert v.Signum >= 0;
- Value = v;
- Bits = b;
- }
-
- [Pure]
- public override string! ToString()
- {
- return Value + "bv" + Bits;
- }
-
- [Pure]
- public string! ToReadableString()
- {
- if (Value > BigNum.FromInt(10000)) {
- string! val = (!)Value.ToString("x");
- int pos = val.Length % 4;
- string! res = "0x" + val.Substring(0, pos);
- while (pos < val.Length) {
- res += "." + val.Substring(pos, 4);
- pos += 4;
- }
- return res + ".bv" + Bits;
- } else
- return ToString();
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- BvConst other = obj as BvConst;
- if (other == null) return false;
-
- return Bits == other.Bits && Value == other.Value;
- }
-
- [Pure]
- public override int GetHashCode()
- {
- unchecked {
- return Value.GetHashCode() ^ Bits;
- }
- }
- }
-
- public class AIVariableExpr : Expr
- {
-
- public string Name; // identifier symbol
- public AI.IVariable! Decl; // identifier declaration
-
- /// <summary>
- /// Creates an unresolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- public AIVariableExpr(IToken! tok, AI.IVariable! var)
- : base(tok)
- {
- Name = var.ToString();
- Decl = var;
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is AIVariableExpr)) return false;
-
- AIVariableExpr other = (AIVariableExpr)obj;
- return object.Equals(this.Name, other.Name) && object.Equals(this.Decl, other.Decl);
- }
- [Pure]
- public override int GetHashCode()
- {
- int h = this.Name == null ? 0 : this.Name.GetHashCode();
- h ^= this.Decl == null ? 0 : this.Decl.GetHashCode();
- return h;
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
- {
- stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h"+this.Decl.GetHashCode());
- }
- stream.Write(this, "{0}", this.Name);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- if (Decl is Variable) {
- freeVars.Add((Variable)Decl);
- }
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- throw new System.NotImplementedException();
- }
- public override Type! ShallowType
- {
- get { throw new System.NotImplementedException(); }
- }
- public override AI.IExpr! IExpr {
- get {
- return Decl;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitAIVariableExpr(this);
- }
- }
-
- public class IdentifierExpr : Expr
- {
- public string! Name; // identifier symbol
- public Variable Decl; // identifier declaration
-
- /// <summary>
- /// Creates an unresolved identifier expression. This constructor is intended to be called
- /// only from within the parser; for use inside the translation, use another constructor, which
- /// specifies the type of the expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- internal IdentifierExpr(IToken! tok, string! name)
- : base(tok)
- {
- Name = name;
- // base(tok);
- }
- /// <summary>
- /// Creates an unresolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="name"></param>
- /// <param name="type"></param>
- public IdentifierExpr(IToken! tok, string! name, Type! type)
- : base(tok)
- {
- Name = name;
- Type = type;
- // base(tok);
- }
-
- /// <summary>
- /// Creates a resolved identifier expression.
- /// </summary>
- /// <param name="tok"></param>
- /// <param name="d"></param>
- public IdentifierExpr(IToken! tok, Variable! d)
- : base(tok)
- {
- Name = (!) d.Name;
- Decl = d;
- Type = d.TypedIdent.Type;
- // base(tok);
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is IdentifierExpr)) return false;
-
- IdentifierExpr other = (IdentifierExpr)obj;
- return object.Equals(this.Name, other.Name) && object.Equals(this.Decl, other.Decl);
- }
- [Pure]
- public override int GetHashCode()
- {
- int h = this.Name == null ? 0 : this.Name.GetHashCode();
- h ^= this.Decl == null ? 0 : this.Decl.GetHashCode();
- return h;
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- if (CommandLineOptions.Clo.PrintWithUniqueASTIds)
- {
- stream.Write("{0}^^", this.Decl == null ? "NoDecl" : "h"+this.Decl.GetHashCode());
- }
- stream.Write(this, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- public override void Resolve(ResolutionContext! rc)
- {
- if (Decl != null)
- {
- // already resolved, but re-resolve type just in case it came from an unresolved type
- if (Type != null) {
- Type = Type.ResolveType(rc);
- }
- return;
- }
- Decl = rc.LookUpVariable(Name);
- if (Decl == null) {
- rc.Error(this, "undeclared identifier: {0}", Name);
- } else if (rc.StateMode == ResolutionContext.State.StateLess && Decl is GlobalVariable) {
- rc.Error(this, "cannot refer to a global variable in this context: {0}", Name);
- }
- if (Type != null) {
- Type = Type.ResolveType(rc);
- }
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- assume this.Decl != null;
- freeVars.Add(Decl);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- if (this.Decl != null)
- {
- // sanity check
- if (Type != null && !Type.Equals(Decl.TypedIdent.Type)) {
- tc.Error(this, "internal error, shallow-type assignment was done incorrectly, {0}:{1} != {2}",
- Name, Type, Decl.TypedIdent.Type);
- assert false;
- }
- Type = Decl.TypedIdent.Type;
- }
- }
-
- public override Type! ShallowType {
- get {
- assert Type != null;
- return Type;
- }
- }
-
- public sealed class ConstantFunApp : AI.IFunApp
- {
- private IdentifierExpr! identifierExpr;
- public IdentifierExpr! IdentifierExpr { get { return identifierExpr; } }
-
- private AI.IFunctionSymbol! symbol;
- public AI.IFunctionSymbol! FunctionSymbol { get { return symbol; } }
-
- private static IList! emptyArgs = ArrayList.ReadOnly((IList!)new ArrayList());
- public IList! Arguments { get { return emptyArgs; } }
-
- public AI.IFunApp! CloneWithArguments(IList! newargs) { return this; }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor) { return visitor.VisitFunApp(this); }
-
- public ConstantFunApp(IdentifierExpr! ie, Constant! c)
- {
- this.identifierExpr = ie;
- this.symbol =
- new AI.NamedSymbol(c.TypedIdent.Name, BoogieFactory.Type2AIType(c.TypedIdent.Type));
- // base();
- }
-
- }
- private AI.IExpr iexprCache = null;
- public override AI.IExpr! IExpr {
- get
- {
- if (iexprCache == null)
- {
- if (Decl is Constant)
- iexprCache = new ConstantFunApp(this, (Constant)Decl);
- else{
- assume this.Decl != null;
- iexprCache = Decl;
- }
- }
- return iexprCache;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitIdentifierExpr(this);
- }
- }
-
- public class OldExpr : Expr
- , AI.IFunApp // HACK
- {
- public Expr! Expr;
- public OldExpr(IToken! tok, Expr! expr)
- : base(tok)
- {
- Expr = expr;
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is OldExpr)) return false;
-
- OldExpr other = (OldExpr)obj;
- return object.Equals(this.Expr, other.Expr);
- }
- [Pure]
- public override int GetHashCode()
- {
- return this.Expr == null ? 0 : this.Expr.GetHashCode();
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.Write(this, "old(");
- this.Expr.Emit(stream);
- stream.Write(")");
- }
- public override void Resolve(ResolutionContext! rc)
- {
- if (rc.StateMode != ResolutionContext.State.Two)
- {
- rc.Error(this, "old expressions allowed only in two-state contexts");
- }
- Expr.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- Expr.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- Expr.Typecheck(tc);
- Type = Expr.Type;
- }
- public override Type! ShallowType {
- get {
- return Expr.ShallowType;
- }
- }
- public override AI.IExpr! IExpr {
- get {
-// Put back these lines when "HACK" removed
-// // An Old expression has no AI.IExpr representation
-// assert false;
-// throw new System.Exception(); // make compiler shut up
- return this; // HACK
- }
- }
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
- public AI.IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
- {
- assume args.Count == 1;
- AI.IExpr! iexpr = (AI.IExpr!)args[0];
- return new OldExpr(Token.NoToken, BoogieFactory.IExpr2Expr(iexpr));
- }
- private IList/*?*/ argCache = null;
- public IList/*<IExpr!*/! Arguments
- {
- get {
- if (argCache == null)
- {
- IList l = new ArrayList(1);
- l.Add(Expr.IExpr);
- argCache = ArrayList.ReadOnly(l);
- }
- return argCache;
- }
- }
- private sealed class OldFunctionSymbol : AI.IFunctionSymbol
- {
- private static AI.AIType! aitype = new AI.FunctionType(AI.Value.Type, AI.Value.Type);
- public AI.AIType! AIType { get { return aitype; } }
- private OldFunctionSymbol() { }
- internal static OldFunctionSymbol! Sym = new OldFunctionSymbol();
- [Pure]
- public override string! ToString() { return "old"; }
- }
- public AI.IFunctionSymbol! FunctionSymbol
- {
- get { return OldFunctionSymbol.Sym; }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitOldExpr(this);
- }
- }
-
- public interface IAppliableVisitor<T> {
-
- T Visit(UnaryOperator! unaryOperator);
-
- T Visit(BinaryOperator! binaryOperator);
-
- T Visit(FunctionCall! functionCall);
-
- T Visit(MapSelect! mapSelect);
-
- T Visit(MapStore! mapStore);
-
- T Visit(TypeCoercion! typeCoercion);
-
- T Visit(IfThenElse! ifThenElse);
- }
-
- public interface IAppliable
- {
- string! FunctionName { get; }
-
- /// <summary>
- /// Emits to "stream" the operator applied to the given arguments.
- /// The length of "args" can be anything that the parser allows for this appliable operator
- /// (but can be nothing else).
- /// </summary>
- /// <param name="args"></param>
- /// <param name="stream"></param>
- /// <param name="contextBindingStrength"></param>
- /// <param name="fragileContext"></param>
- void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext);
-
- void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting);
-
- /// <summary>
- /// Requires the object to have been properly resolved.
- /// </summary>
- int ArgumentCount { get; }
-
- /// <summary>
- /// Typechecks the arguments "args" for the Appliable. If the arguments are
- /// appropriate, returns the result type; otherwise returns null.
- /// As result of the type checking, the values of type parameters of the
- /// appliable can be returned (which are then stored in the NAryExpr and later
- /// also used in the VCExprAST).
- /// Requires the object to have been successfully resolved.
- /// Requires args.Length == ArgumentCount.
- /// Requires all elements of "args" to have a non-null Type field.
- /// </summary>
- /// <param name="args"></param>
- /// <param name="tc"></param>
- Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc);
- ensures args.Length == old(args.Length);
- // requires Microsoft.SpecSharp.Collections.Reductions.Forall{Expr! arg in args; arg.Type != null};
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- Type! ShallowType(ExprSeq! args);
-
- AI.IFunctionSymbol! AIFunctionSymbol { get; }
-
- T Dispatch<T>(IAppliableVisitor<T>! visitor);
- }
-
- public interface IOverloadedAppliable
- {
- void ResolveOverloading(NAryExpr! expr);
- }
-
- public class UnaryOperator : IAppliable
- {
- private IToken! tok;
- public enum Opcode { Not };
- private Opcode op;
- public Opcode Op { get { return op; } }
- public UnaryOperator (IToken! tok, Opcode op) { this.tok = tok; this.op = op; }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is UnaryOperator)) return false;
-
- UnaryOperator other = (UnaryOperator)obj;
- return object.Equals(this.op, other.op);
- }
- [Pure]
- public override int GetHashCode()
- {
- return (int) this.op;
- }
-
- public string! FunctionName
- {
- get
- {
- switch (this.op)
- {
- case Opcode.Not: return "!";
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol {
- get {
- switch (this.op) {
- case Opcode.Not: return AI.Prop.Not;
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(ref this.tok);
- assert args.Length == 1;
- // determine if parens are needed
- int opBindingStrength = 0x60;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- {
- stream.Write("(");
- }
- stream.Write(FunctionName);
- ((!)args[0]).Emit(stream, opBindingStrength, false);
- if (parensNeeded)
- {
- stream.Write(")");
- }
- }
-
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
- {
- if (rc.TriggerMode && this.op == Opcode.Not) {
- rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
- }
- }
-
- public int ArgumentCount
- {
- get
- {
- return 1;
- }
- }
-
- public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
- {
- assume args.Length == 1;
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Type arg0type = (!)((!)args[0]).Type;
- switch (this.op)
- {
- case Opcode.Not:
- if (arg0type.Unify(Type.Bool))
- {
- return Type.Bool;
- }
- goto BAD_TYPE;
- }
- System.Diagnostics.Debug.Fail("unknown unary operator: " + op.ToString());
- assert false;
- BAD_TYPE:
- tc.Error(this.tok, "invalid argument type ({1}) to unary operator {0}",
- this.FunctionName, arg0type);
- return null;
- }
- public Type! ShallowType(ExprSeq! args) {
- switch (this.op) {
- case Opcode.Not:
- return Type.Bool;
- default:
- assert false; // unexpected unary operator
- }
- }
-
- public object Evaluate (object argument)
- {
- if (argument == null) { return null; }
- switch (this.op)
- {
- case Opcode.Not:
- if (argument is bool) { return ! ((bool)argument); }
- throw new System.InvalidOperationException("unary Not only applies to bool");
- }
- return null; // unreachable
- }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
- }
-
- public class BinaryOperator : IAppliable, IOverloadedAppliable
- {
- private IToken! tok;
- public enum Opcode { Add, Sub, Mul, Div, Mod, Eq, Neq, Gt, Ge, Lt, Le, And, Or, Imp, Iff, Subtype };
- private Opcode op;
- public Opcode Op { get { return op; } }
- public BinaryOperator (IToken! tok, Opcode op) { this.tok = tok; this.op = op; }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is BinaryOperator)) return false;
-
- BinaryOperator other = (BinaryOperator)obj;
- return object.Equals(this.op, other.op);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return (int) this.op << 1;
- }
-
- public string! FunctionName
- {
- get
- {
- switch (this.op)
- {
- case Opcode.Add: return "+";
- case Opcode.Sub: return "-";
- case Opcode.Mul: return "*";
- case Opcode.Div: return "/";
- case Opcode.Mod: return "%";
- case Opcode.Eq: return "==";
- case Opcode.Neq: return "!=";
- case Opcode.Gt: return ">";
- case Opcode.Ge: return ">=";
- case Opcode.Lt: return "<";
- case Opcode.Le: return "<=";
- case Opcode.And: return "&&";
- case Opcode.Or: return "||";
- case Opcode.Imp: return "==>";
- case Opcode.Iff: return "<==>";
- case Opcode.Subtype: return "<:";
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol {
- get {
- switch (this.op) {
- case Opcode.Add: return AI.Int.Add;
- case Opcode.Sub: return AI.Int.Sub;
- case Opcode.Mul: return AI.Int.Mul;
- case Opcode.Div: return AI.Int.Div;
- case Opcode.Mod: return AI.Int.Mod;
- case Opcode.Eq: return AI.Value.Eq;
- case Opcode.Neq: return AI.Value.Neq;
- case Opcode.Gt: return AI.Int.Greater;
- case Opcode.Ge: return AI.Int.AtLeast;
- case Opcode.Lt: return AI.Int.Less;
- case Opcode.Le: return AI.Int.AtMost;
- case Opcode.And: return AI.Prop.And;
- case Opcode.Or: return AI.Prop.Or;
- case Opcode.Imp: return AI.Prop.Implies;
- case Opcode.Iff: return AI.Value.Eq;
- case Opcode.Subtype: return AI.Value.Subtype;
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- throw new Exception();
- }
- }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(ref this.tok);
- assert args.Length == 2;
- // determine if parens are needed
- int opBindingStrength;
- bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
- bool fragileRightContext = false; // false means "allow same binding power on right without parens"
- switch (this.op)
- {
- case Opcode.Add:
- opBindingStrength = 0x40; break;
- case Opcode.Sub:
- opBindingStrength = 0x40; fragileRightContext = true; break;
- case Opcode.Mul:
- opBindingStrength = 0x50; break;
- case Opcode.Div:
- opBindingStrength = 0x50; fragileRightContext = true; break;
- case Opcode.Mod:
- opBindingStrength = 0x50; fragileRightContext = true; break;
- case Opcode.Eq:
- case Opcode.Neq:
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- case Opcode.Subtype:
- opBindingStrength = 0x30;
- fragileLeftContext = fragileRightContext = true;
- break;
- case Opcode.And:
- opBindingStrength = 0x20; break;
- case Opcode.Or:
- opBindingStrength = 0x21; break;
- case Opcode.Imp:
- opBindingStrength = 0x10; fragileLeftContext = true; break;
- case Opcode.Iff:
- opBindingStrength = 0x00; break;
- default:
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- opBindingStrength = -1; // to please compiler, which refuses to consider whether or not all enumeration cases have been considered!
- break;
- }
- int opBS = opBindingStrength & 0xF0;
- int ctxtBS = contextBindingStrength & 0xF0;
- bool parensNeeded = opBS < ctxtBS ||
- (opBS == ctxtBS && (opBindingStrength != contextBindingStrength || fragileContext));
-
- if (parensNeeded)
- {
- stream.Write("(");
- }
- ((!)args[0]).Emit(stream, opBindingStrength, fragileLeftContext);
- stream.Write(" {0} ", FunctionName);
- ((!)args[1]).Emit(stream, opBindingStrength, fragileRightContext);
- if (parensNeeded)
- {
- stream.Write(")");
- }
- }
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
- {
- if (rc.TriggerMode) {
- switch (this.op)
- {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- case Opcode.Div:
- case Opcode.Mod:
- case Opcode.Neq: // Neq is allowed, but not Eq
- case Opcode.Subtype:
- // These are fine
- break;
-
- case Opcode.Eq:
- rc.Error(subjectForErrorReporting, "equality is not allowed in triggers");
- break;
-
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- rc.Error(subjectForErrorReporting, "arithmetic comparisons are not allowed in triggers");
- break;
-
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- rc.Error(subjectForErrorReporting, "boolean operators are not allowed in triggers");
- break;
-
- default:
- System.Diagnostics.Debug.Fail("unknown binary operator: " + this.op.ToString());
- break;
- }
- }
- }
- public int ArgumentCount
- {
- get
- {
- return 2;
- }
- }
- public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
- {
- assert args.Length == 2;
- // the default; the only binary operator with a type parameter is equality, but right
- // we don't store this parameter because it does not appear necessary
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Expr arg0 = (!)args[0];
- Expr arg1 = (!)args[1];
- Type arg0type = (!)arg0.Type;
- Type arg1type = (!)arg1.Type;
- switch (this.op)
- {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- case Opcode.Div:
- case Opcode.Mod:
- if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
- return Type.Int;
- }
- goto BAD_TYPE;
- case Opcode.Eq:
- case Opcode.Neq:
- // Comparison is allowed if the argument types are unifiable
- // (i.e., if there is any chance that the values of the arguments are
- // in the same domain)
- if (arg0type.Equals(arg1type)) {
- // quick path
- return Type.Bool;
- }
- TypeVariableSeq! unifiable = new TypeVariableSeq ();
- unifiable.AddRange(arg0type.FreeVariables);
- unifiable.AddRange(arg1type.FreeVariables);
-
- if (arg0type.Unify(arg1type, unifiable, new Dictionary<TypeVariable!, Type!> ()))
- return Type.Bool;
- goto BAD_TYPE;
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- if (arg0type.Unify(Type.Int) && arg1type.Unify(Type.Int)) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- if (arg0type.Unify(Type.Bool) && arg1type.Unify(Type.Bool)) {
- return Type.Bool;
- }
- goto BAD_TYPE;
- case Opcode.Subtype:
- // Subtype is polymorphically typed and can compare things of
- // arbitrary types (but both arguments must have the same type)
- if (arg0type.Unify(arg1type))
- {
- return Type.Bool;
- }
- goto BAD_TYPE;
- }
- System.Diagnostics.Debug.Fail("unknown binary operator: " + op.ToString());
- assert false;
- BAD_TYPE:
- tc.Error(this.tok, "invalid argument types ({1} and {2}) to binary operator {0}", this.FunctionName, arg0type, arg1type);
- return null;
- }
-
- public Type! ShallowType(ExprSeq! args) {
- switch (this.op)
- {
- case Opcode.Add:
- case Opcode.Sub:
- case Opcode.Mul:
- case Opcode.Div:
- case Opcode.Mod:
- return Type.Int;
-
- case Opcode.Eq:
- case Opcode.Neq:
- case Opcode.Gt:
- case Opcode.Ge:
- case Opcode.Lt:
- case Opcode.Le:
- case Opcode.And:
- case Opcode.Or:
- case Opcode.Imp:
- case Opcode.Iff:
- case Opcode.Subtype:
- return Type.Bool;
-
- default:
- assert false; // unexpected binary operator
- }
- }
-
- public void ResolveOverloading(NAryExpr! expr)
- {
- Expr arg0 = (!) expr.Args[0];
- Expr arg1 = (!) expr.Args[1];
- switch (op)
- {
- case Opcode.Eq:
- if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool)
- {
- expr.Fun = new BinaryOperator(tok, Opcode.Iff);
- }
- break;
- case Opcode.Neq:
- if (arg0.Type != null && arg0.Type.IsBool && arg1.Type != null && arg1.Type.IsBool)
- {
- expr.Fun = new BinaryOperator(tok, Opcode.Iff);
- arg1 = new NAryExpr(expr.tok, new UnaryOperator(tok, UnaryOperator.Opcode.Not), new ExprSeq(arg1));
-
- // ugly ... there should be some more general approach,
- // e.g., to typecheck the whole expression again
- arg1.Type = Type.Bool;
- ((NAryExpr)arg1).TypeParameters = SimpleTypeParamInstantiation.EMPTY;
-
- expr.Args[1] = arg1;
- }
- break;
- }
- }
-
- public object Evaluate (object e1, object e2)
- {
- if (e1 == null || e2 == null) { return null; }
-
- switch (this.op)
- {
- case Opcode.Add:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)+((BigNum)e2); }
- break;
- case Opcode.Sub:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)-((BigNum)e2); }
- break;
- case Opcode.Mul:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)*((BigNum)e2); }
- break;
- case Opcode.Div:
- if (e1 is BigNum && e2 is BigNum) { return /* TODO: right semantics? */ ((BigNum)e1)/((BigNum)e2); }
- break;
- case Opcode.Mod:
- if (e1 is BigNum && e2 is BigNum) { return /* TODO: right semantics? */ ((BigNum)e1)%((BigNum)e2); }
- break;
- case Opcode.Lt:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)<((BigNum)e2); }
- break;
- case Opcode.Le:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)<=((BigNum)e2); }
- break;
- case Opcode.Gt:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)>((BigNum)e2); }
- break;
- case Opcode.Ge:
- if (e1 is BigNum && e2 is BigNum) { return ((BigNum)e1)>=((BigNum)e2); }
- break;
-
- case Opcode.And: if (e1 is bool && e2 is bool) { return (bool)e1 && (bool)e2; } break;
- case Opcode.Or: if (e1 is bool && e2 is bool) { return (bool)e1 || (bool)e2; } break;
- case Opcode.Imp: if (e1 is bool && e2 is bool) { return ! (bool)e1 || (bool)e2; } break;
- case Opcode.Iff: if (e1 is bool && e2 is bool) { return e1 == e2; } break;
-
- case Opcode.Eq: return Equals(e1,e2);
- case Opcode.Neq: return ! Equals(e1,e2);
-
- case Opcode.Subtype: throw new System.NotImplementedException();
- }
- throw new System.InvalidOperationException("bad types to binary operator " + this.op);
- }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
-
- }
-
- public class FunctionCall : IAppliable, AI.IFunctionSymbol
- {
- private IdentifierExpr! name;
- public Function Func;
- public FunctionCall(IdentifierExpr! name) { this.name = name; }
- public FunctionCall(Function! f) { this.Func = f; this.name = new IdentifierExpr(Token.NoToken, f.Name); }
- public string! FunctionName { get { return this.name.Name; } }
-
- public AI.IFunctionSymbol! AIFunctionSymbol {
- get {
- if (name.Name == "$typeof") {
- return AI.Value.Typeof;
- } else if (name.Name == "$allocated") {
- return AI.FieldName.Allocated;
- } else {
- return this;
- }
- }
- }
-
- [Pure]
- public override string! ToString() {
- return name.Name;
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other) {
- FunctionCall fc = other as FunctionCall;
- return fc != null && this.Func == fc.Func;
- }
- [Pure]
- public override int GetHashCode()
- {
- assume this.Func != null;
- return Func.GetHashCode();
- }
-
- public AI.AIType! AIType {
- get
- {
- assume this.Func != null;
- return AI.Value.FunctionType(this.Func.InParams.Length);
- }
- }
-
- virtual public void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- this.name.Emit(stream, 0xF0, false);
- stream.Write("(");
- args.Emit(stream);
- stream.Write(")");
- }
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting)
- {
- if (Func != null)
- {
- // already resolved
- return;
- }
- Func = rc.LookUpProcedure(name.Name) as Function;
- if (Func == null)
- {
- rc.Error(this.name, "use of undeclared function: {0}", name.Name);
- }
- }
- public virtual int ArgumentCount
- {
- get
- {
- assume Func != null; // ArgumentCount requires object to be properly resolved.
- return Func.InParams.Length;
- }
- }
- public virtual Type Typecheck(ref ExprSeq! actuals, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
- {
- assume this.Func != null;
- assume actuals.Length == Func.InParams.Length;
- assume Func.OutParams.Length == 1;
-
- List<Type!>! resultingTypeArgs;
- TypeSeq actualResultType =
- Type.CheckArgumentTypes(Func.TypeParameters,
- out resultingTypeArgs,
- Func.InParams.ToTypeSeq,
- actuals,
- Func.OutParams.ToTypeSeq,
- null,
- // we need some token to report a possibly wrong number of
- // arguments
- actuals.Length > 0 ? ((!)actuals[0]).tok : Token.NoToken,
- "application of " + name.Name,
- tc);
-
- if (actualResultType == null) {
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else {
- assert actualResultType.Length == 1;
- tpInstantiation =
- SimpleTypeParamInstantiation.From(Func.TypeParameters, resultingTypeArgs);
- return actualResultType[0];
- }
- }
- public Type! ShallowType(ExprSeq! args) {
- assume name.Type != null;
- return name.Type;
- }
-
- public virtual T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
- }
-
- public class TypeCoercion : IAppliable {
- private IToken! tok;
- public Type! Type;
-
- public TypeCoercion(IToken! tok, Type! type) {
- this.tok = tok;
- this.Type = type;
- }
-
- public string! FunctionName { get {
- return ":";
- } }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream,
- int contextBindingStrength, bool fragileContext) {
- stream.SetToken(ref this.tok);
- assert args.Length == 1;
- // determine if parens are needed
- int opBindingStrength = 0x90;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- stream.Write("(");
-
- ((!)args[0]).Emit(stream, opBindingStrength, false);
- stream.Write("{0} ", FunctionName);
- Type.Emit(stream, 0);
-
- if (parensNeeded)
- stream.Write(")");
- }
-
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
- this.Type = this.Type.ResolveType(rc);
- }
-
- public int ArgumentCount { get {
- return 1;
- } }
-
- public Type Typecheck(ref ExprSeq! args,
- out TypeParamInstantiation! tpInstantiation,
- TypecheckingContext! tc) {
- assume args.Length == 1;
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
-
- if (!this.Type.Unify((!)((!)args[0]).Type))
- tc.Error(this.tok, "{0} cannot be coerced to {1}",
- ((!)args[0]).Type, this.Type);
- return this.Type;
- }
-
- public Type! ShallowType(ExprSeq! args) {
- return this.Type;
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol { get {
- // not really clear what should be returned here ...
- // should the operation be completely invisible for the abstract interpretation?
- return AI.Heap.UnsupportedHeapOp;
- } }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
-
- }
-
- public class NAryExpr : Expr, AI.IFunApp
- {
- [Additive] [Peer]
- public IAppliable! Fun;
- public ExprSeq! Args;
-
- // The instantiation of type parameters that is determined during type checking.
- // Which type parameters are available depends on the IAppliable
- public TypeParamInstantiation TypeParameters = null;
-
- [Captured]
- public NAryExpr(IToken! tok, IAppliable! fun, ExprSeq! args)
- : base(tok)
- {
- Fun = fun;
- Args = args;
- assert forall{Expr arg in args; arg != null};
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is NAryExpr)) return false;
-
- NAryExpr other = (NAryExpr)obj;
- return object.Equals(this.Fun, other.Fun) && object.Equals(this.Args, other.Args);
- }
- [Pure]
- public override int GetHashCode()
- {
- int h = this.Fun.GetHashCode();
- h ^= this.Args.GetHashCode();
- return h;
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(this);
- Fun.Emit(Args, stream, contextBindingStrength, fragileContext);
- }
- public override void Resolve(ResolutionContext! rc)
- {
- Fun.Resolve(rc, this);
- foreach (Expr! e in Args)
- {
- e.Resolve(rc);
- }
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- foreach (Expr! e in Args) {
- e.ComputeFreeVariables(freeVars);
- }
- // also add the free type variables
- if (TypeParameters != null) {
- foreach (TypeVariable! var in TypeParameters.FormalTypeParams)
- foreach (TypeVariable! w in TypeParameters[var].FreeVariables)
- freeVars.Add(w);
- }
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- int prevErrorCount = tc.ErrorCount;
- foreach (Expr! e in Args)
- {
- e.Typecheck(tc);
- }
- if (Fun.ArgumentCount != Args.Length)
- {
- tc.Error(this, "wrong number of arguments to function: {0} ({1} instead of {2})",
- Fun.FunctionName, Args.Length, Fun.ArgumentCount);
- }
- else if (tc.ErrorCount == prevErrorCount &&
- // if the type parameters are set, this node has already been
- // typechecked and does not need to be checked again
- TypeParameters == null)
- {
- TypeParamInstantiation! tpInsts;
- Type = Fun.Typecheck(ref Args, out tpInsts, tc);
- if (Type != null && Type.IsBv && CommandLineOptions.Clo.Verify && CommandLineOptions.Clo.Bitvectors == CommandLineOptions.BvHandling.None) {
- tc.Error(this, "no bitvector handling specified, please use /bv:i or /bv:z flag");
- }
- TypeParameters = tpInsts;
- }
- IOverloadedAppliable oa = Fun as IOverloadedAppliable;
- if (oa != null)
- {
- oa.ResolveOverloading(this);
- }
- if (Type == null) {
- // set Type to some non-null value
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
- public override Type! ShallowType {
- get {
- return Fun.ShallowType(Args);
- }
- }
-
- public override AI.IExpr! IExpr {
- get {
- return this;
- }
- }
- public AI.IFunctionSymbol! FunctionSymbol {
- get {
- return Fun.AIFunctionSymbol;
- }
- }
- public IList/*<AI.IExpr!>*/! Arguments {
- get {
- AI.IExpr[] a = new AI.IExpr[Args.Length];
- for (int i = 0; i < Args.Length; i++) {
- a[i] = ((!)Args[i]).IExpr;
- }
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args) {
- return new NAryExpr(this.tok, this.Fun, BoogieFactory.IExprArray2ExprSeq(args));
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitNAryExpr(this);
- }
- }
-
- public class MapSelect : IAppliable, AI.IFunctionSymbol {
-
- public readonly int Arity;
- private readonly IToken! tok;
-
- public MapSelect(IToken! tok, int arity) {
- this.tok = tok;
- this.Arity = arity;
- }
-
- public string! FunctionName { get {
- return "MapSelect";
- } }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (!(obj is MapSelect)) return false;
-
- MapSelect other = (MapSelect)obj;
- return this.Arity == other.Arity;
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return Arity.GetHashCode() * 2823;
- }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream,
- int contextBindingStrength, bool fragileContext) {
- assume args.Length == Arity + 1;
- Emit(args, stream, contextBindingStrength, fragileContext, false);
- }
-
- public static void Emit(ExprSeq! args, TokenTextWriter! stream,
- int contextBindingStrength, bool fragileContext,
- bool withRhs) {
- const int opBindingStrength = 0x70;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- {
- stream.Write("(");
- }
- ((!)args[0]).Emit(stream, opBindingStrength, false);
- stream.Write("[");
-
- string sep = "";
- int lastIndex = withRhs ? args.Length - 1 : args.Length;
- for (int i = 1; i < lastIndex; ++i) {
- stream.Write(sep);
- sep = ", ";
- ((!)args[i]).Emit(stream);
- }
-
- if (withRhs) {
- stream.Write(" := ");
- ((!)args.Last()).Emit(stream);
- }
-
- stream.Write("]");
- if (parensNeeded)
- {
- stream.Write(")");
- }
- }
-
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
- // PR: nothing?
- }
-
- public int ArgumentCount { get {
- return Arity + 1;
- } }
-
- // it is assumed that each of the arguments has already been typechecked
- public static Type Typecheck(Type! mapType,
- // we just pass an Absy, because in
- // the AssignCmd maps can also be
- // represented by non-expressions
- Absy! map,
- ExprSeq! indexes,
- // the type parameters, in this context, are the parameters of the
- // potentially polymorphic map type. Because it might happen that
- // the whole map type is unknown and represented using a MapTypeProxy,
- // the instantiations given in the following out-parameter are subject
- // to change if further unifications are done.
- out TypeParamInstantiation! tpInstantiation,
- TypecheckingContext! tc,
- IToken! typeCheckingSubject,
- string! opName) {
- mapType = mapType.Expanded;
- if (mapType.IsMap && mapType.MapArity != indexes.Length) {
- tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1} instead of {2}",
- opName, indexes.Length, mapType.MapArity);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else if (!mapType.Unify(new MapTypeProxy(map.tok, "select", indexes.Length))) {
- tc.Error(map.tok, "{0} applied to a non-map: {1}", opName, map);
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- }
- mapType = TypeProxy.FollowProxy(mapType);
-
- if (mapType is MapType) {
- MapType mt = (MapType)mapType;
- return mt.CheckArgumentTypes(indexes, out tpInstantiation,
- typeCheckingSubject, opName, tc);
- } else {
- MapTypeProxy mt = (MapTypeProxy)mapType;
- return mt.CheckArgumentTypes(indexes, out tpInstantiation,
- typeCheckingSubject, opName, tc);
- }
- }
-
- public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
- {
- assume args.Length == Arity + 1;
-
- ExprSeq actualArgs = new ExprSeq ();
- for (int i = 1; i < args.Length; ++i)
- actualArgs.Add(args[i]);
-
- return Typecheck((!)((!)args[0]).Type, (!)args[0],
- actualArgs, out tpInstantiation, tc, this.tok, "map select");
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type! ShallowType(ExprSeq! args) {
- Expr a0 = (!)args[0];
- Type a0Type = a0.ShallowType;
- if (a0Type == null || !a0Type.IsMap) {
- // we are unable to determine the type of the select, so just return an arbitrary type
- return Type.Int;
- }
- MapType mapType = a0Type.AsMap;
- TypeSeq actualArgTypes = new TypeSeq ();
- for (int i = 1; i < args.Length; ++i) {
- actualArgTypes.Add(((!)args[i]).ShallowType);
- }
- return Type.InferValueType(mapType.TypeParameters, mapType.Arguments, mapType.Result, actualArgTypes);
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol { get {
- switch (Arity) {
- case 1: return AI.Heap.Select1;
- case 2: return AI.Heap.Select2;
- default:
- // Maps with Arity arguments are not fully supported yet
- return AI.Heap.UnsupportedHeapOp;
- }
- } }
-
- public AI.AIType! AIType {
- [Rep][ResultNotNewlyAllocated]
- get {
- return AI.Prop.Type; // THAT is a type? PR: no idea whether this makes sense,
- // but it is the type of select1
- } }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
- }
-
- public class MapStore : IAppliable, AI.IFunctionSymbol {
-
- public readonly int Arity;
- public readonly IToken! tok;
-
- public MapStore(IToken! tok, int arity) {
- this.tok = tok;
- this.Arity = arity;
- }
-
- public string! FunctionName { get {
- return "MapStore";
- } }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (!(obj is MapStore)) return false;
-
- MapStore other = (MapStore)obj;
- return this.Arity == other.Arity;
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return Arity.GetHashCode() * 28231;
- }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream,
- int contextBindingStrength, bool fragileContext) {
- assert args.Length == Arity + 2;
- MapSelect.Emit(args, stream, contextBindingStrength, fragileContext, true);
- }
-
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
- // PR: nothing?
- }
-
- public int ArgumentCount { get {
- return Arity + 2;
- } }
-
- // it is assumed that each of the arguments has already been typechecked
- public static Type Typecheck(ExprSeq! args, out TypeParamInstantiation! tpInstantiation,
- TypecheckingContext! tc,
- IToken! typeCheckingSubject,
- string! opName) {
- // part of the type checking works exactly as for MapSelect
- ExprSeq! selectArgs = new ExprSeq ();
- for (int i = 1; i < args.Length - 1; ++i)
- selectArgs.Add(args[i]);
- Type resultType =
- MapSelect.Typecheck((!)((!)args[0]).Type, (!)args[0],
- selectArgs, out tpInstantiation, tc, typeCheckingSubject, opName);
-
- // check the the rhs has the right type
- if (resultType == null) {
- // error messages have already been created by MapSelect.Typecheck
- return null;
- }
- Type rhsType = (!)((!)args.Last()).Type;
- if (!resultType.Unify(rhsType)) {
- tc.Error(((!)args.Last()).tok,
- "right-hand side in {0} with wrong type: {1} (expected: {2})",
- opName, rhsType, resultType);
- return null;
- }
-
- return ((!)args[0]).Type;
- }
-
- public Type Typecheck(ref ExprSeq! args,
- out TypeParamInstantiation! tpInstantiation,
- TypecheckingContext! tc)
- {
- assert args.Length == Arity + 2;
- return Typecheck(args, out tpInstantiation, tc, this.tok, "map store");
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type! ShallowType(ExprSeq! args) {
- return ((!)args[0]).ShallowType;
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol { get {
- switch (Arity) {
- case 1: return AI.Heap.Update1;
- case 2: return AI.Heap.Update2;
- default:
- // Maps with Arity arguments are not fully supported yet
- return AI.Heap.UnsupportedHeapOp;
- }
- } }
-
- public AI.AIType! AIType {
- [Rep][ResultNotNewlyAllocated]
- get {
- return AI.Heap.Type;
- } }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
- }
-
-
- public class IfThenElse : IAppliable, AI.IFunctionSymbol {
-
- public IToken! tok;
-
- public IfThenElse(IToken! tok) {
- this.tok = tok;
- }
-
- public string! FunctionName { get {
- return "if-then-else";
- } }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (!(obj is IfThenElse)) return false;
- return true;
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return 1;
- }
-
- public void Emit(ExprSeq! args, TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(ref this.tok);
- assert args.Length == 3;
- stream.Write("(if ");
- ((!)args[0]).Emit(stream, 0x00, false);
- stream.Write(" then ");
- ((!)args[1]).Emit(stream, 0x00, false);
- stream.Write(" else ");
- ((!)args[2]).Emit(stream, 0x00, false);
- stream.Write(")");
- }
-
- public void Resolve(ResolutionContext! rc, Expr! subjectForErrorReporting) {
- // PR: nothing?
- }
-
- public int ArgumentCount { get {
- return 3;
- } }
-
- public Type Typecheck(ref ExprSeq! args, out TypeParamInstantiation! tpInstantiation, TypecheckingContext! tc)
- {
- assert args.Length == 3;
- // the default; the only binary operator with a type parameter is equality, but right
- // we don't store this parameter because it does not appear necessary
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- Expr arg0 = (!)args[0];
- Expr arg1 = (!)args[1];
- Expr arg2 = (!)args[2];
-
- if (!((!)arg0.Type).Unify(Type.Bool)) {
- tc.Error(this.tok, "the first argument to if-then-else should be bool, not {0}", arg0.Type);
- } else if (!((!)arg1.Type).Unify((!)arg2.Type)) {
- tc.Error(this.tok, "branches of if-then-else have incompatible types {0} and {1}", arg1.Type, arg2.Type);
- } else {
- return arg1.Type;
- }
-
- return null;
- }
-
- /// <summary>
- /// Returns the result type of the IAppliable, supposing the argument are of the correct types.
- /// </summary>
- public Type! ShallowType(ExprSeq! args) {
- return ((!)args[1]).ShallowType;
- }
-
- public AI.IFunctionSymbol! AIFunctionSymbol { get { return this; } }
-
- public AI.AIType! AIType {
- [Rep][ResultNotNewlyAllocated]
- get {
- return AI.Value.FunctionType(3);
- } }
-
- public T Dispatch<T>(IAppliableVisitor<T>! visitor) {
- return visitor.Visit(this);
- }
- }
-
-
-
- public class CodeExpr : Expr, AI.IUnknown
- {
- public VariableSeq! LocVars;
- [Rep]
- public List<Block!>! Blocks;
- public CodeExpr(VariableSeq! localVariables, List<Block!>! blocks)
- : base(Token.NoToken)
- requires 0 < blocks.Count;
- {
- LocVars = localVariables;
- Blocks = blocks;
- }
-
- public override AI.IExpr! IExpr { get { return this; } }
- [Pure] public object DoVisit(AI.ExprVisitor! visitor) { return this; }
-
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- // Treat a BlockEexpr as if it has no free variables at all
- }
- public override void Emit (TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- //level++;
- int level = 0;
- stream.WriteLine(level, "|{");
-
- if (this.LocVars.Length > 0)
- {
- stream.Write(level + 1, "var ");
- this.LocVars.Emit(stream);
- stream.WriteLine(";");
- }
-
- foreach (Block! b in this.Blocks)
- {
- b.Emit(stream, level+1);
- }
-
- stream.WriteLine();
- stream.WriteLine(level, "}|");
-
- stream.WriteLine();
- stream.WriteLine();
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
-
- rc.PushVarContext();
- foreach (Variable! v in LocVars)
- {
- v.Register(rc);
- v.Resolve(rc);
- }
-
- rc.PushProcedureContext();
- foreach (Block! b in Blocks)
- {
- b.Register(rc);
- }
-
- foreach (Block! b in Blocks)
- {
- b.Resolve(rc);
- }
-
- rc.PopProcedureContext();
- rc.PopVarContext();
- }
-
- public override void Typecheck(TypecheckingContext! tc){
- foreach (Variable! v in LocVars){
- v.Typecheck(tc);
- }
- foreach (Block! b in Blocks){
- b.Typecheck(tc);
- }
- this.Type = Type.Bool;
- }
- public override Type! ShallowType {
- get {
- return Type.Bool;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitCodeExpr(this);
- }
- }
-
-
-
- public class BvExtractExpr : Expr, AI.IFunApp
- {
- public /*readonly--except in StandardVisitor*/ Expr! Bitvector;
- public readonly int Start, End;
-
- public BvExtractExpr(IToken! tok, Expr! bv, int end, int start)
- : base(tok)
- {
- Bitvector = bv;
- Start = start;
- End = end;
- // base(tok);
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is BvExtractExpr)) return false;
-
- BvExtractExpr other = (BvExtractExpr)obj;
- return object.Equals(this.Bitvector, other.Bitvector) &&
- this.Start.Equals(other.Start) && this.End.Equals(other.End);
- }
- [Pure]
- public override int GetHashCode()
- {
- int h = this.Bitvector.GetHashCode();
- h ^= Start * 17 ^ End * 13;
- return h;
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(this);
- int opBindingStrength = 0x70;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- {
- stream.Write("(");
- }
- Bitvector.Emit(stream, opBindingStrength, false);
- stream.Write("[" + End + ":" + Start + "]");
- if (parensNeeded)
- {
- stream.Write(")");
- }
- }
- public override void Resolve(ResolutionContext! rc)
- {
- Bitvector.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- Bitvector.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- Bitvector.Typecheck(tc);
- assert Bitvector.Type != null; // follows from postcondition of Expr.Typecheck
-
- if (Start < 0) {
- tc.Error(this, "start index in extract must not be negative");
- } else if (End < 0) {
- tc.Error(this, "end index in extract must not be negative");
- } else if (End < Start) {
- tc.Error(this, "start index in extract must be no bigger than the end index");
- } else {
- Type typeConstraint = new BvTypeProxy(this.tok, "extract", End - Start);
- if (typeConstraint.Unify(Bitvector.Type)) {
- Type = Type.GetBvType(End - Start);
- } else {
- tc.Error(this, "extract operand must be a bitvector of at least {0} bits (got {1})", End - Start, Bitvector.Type);
- }
- }
- if (Type == null) {
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
-
- public override Type! ShallowType {
- get {
- return Type.GetBvType(End - Start);
- }
- }
-
- public override AI.IExpr! IExpr {
- get {
- return this;
- }
- }
- public AI.IFunctionSymbol! FunctionSymbol {
- get { return AI.Bv.Extract;
- }
- }
- public IList/*<AI.IExpr!>*/! Arguments {
- get {
- AI.IExpr[] a = new AI.IExpr[3];
- a[0] = Bitvector.IExpr;
- a[1] = new LiteralExpr(Token.NoToken, BigNum.FromInt(End));
- a[2] = new LiteralExpr(Token.NoToken, BigNum.FromInt(Start));
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args)
- {
- AI.IFunApp! retFun;
-
- if(args.Count == 3)
- {
- retFun = new BvExtractExpr(this.tok,
- BoogieFactory.IExpr2Expr((AI.IExpr!)args[0]),
- ((LiteralExpr!)args[1]).asBigNum.ToIntSafe,
- ((LiteralExpr!)args[2]).asBigNum.ToIntSafe);
- }
- else
- {
- assert false; // If we are something wrong is happended
- }
- return retFun;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBvExtractExpr(this);
- }
- }
-
- public class BvConcatExpr : Expr, AI.IFunApp
- {
- public /*readonly--except in StandardVisitor*/ Expr! E0, E1;
-
- public BvConcatExpr(IToken! tok, Expr! e0, Expr! e1)
- : base(tok)
- {
- E0 = e0;
- E1 = e1;
- // base(tok);
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is BvConcatExpr)) return false;
-
- BvConcatExpr other = (BvConcatExpr)obj;
- return object.Equals(this.E0, other.E0) && object.Equals(this.E1, other.E1);
- }
- [Pure]
- public override int GetHashCode()
- {
- int h = this.E0.GetHashCode() ^ this.E1.GetHashCode() * 17;
- return h;
- }
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.SetToken(this);
- int opBindingStrength = 0x32;
- bool parensNeeded = opBindingStrength < contextBindingStrength ||
- (fragileContext && opBindingStrength == contextBindingStrength);
-
- if (parensNeeded)
- {
- stream.Write("(");
- }
- E0.Emit(stream, opBindingStrength, false);
- stream.Write(" ++ ");
- // while this operator is associative, our incomplete axioms in int translation don't
- // make much use of it, so better stick to the actual tree shape
- E1.Emit(stream, opBindingStrength, true);
- if (parensNeeded)
- {
- stream.Write(")");
- }
- }
- public override void Resolve(ResolutionContext! rc)
- {
- E0.Resolve(rc);
- E1.Resolve(rc);
- }
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- E0.ComputeFreeVariables(freeVars);
- E1.ComputeFreeVariables(freeVars);
- }
- public override void Typecheck(TypecheckingContext! tc)
- {
- E0.Typecheck(tc);
- assert E0.Type != null; // follows from postcondition of Expr.Typecheck
- E1.Typecheck(tc);
- assert E1.Type != null; // follows from postcondition of Expr.Typecheck
-
- if (E0.Type.Unify(new BvTypeProxy(this.tok, "concat0", 0)) && E1.Type.Unify(new BvTypeProxy(this.tok, "concat1", 0))) {
- Type = new BvTypeProxy(this.tok, "concat", E0.Type, E1.Type);
- } else {
- tc.Error(this, "++ operands need to be bitvectors (got {0}, {1})", E0.Type, E1.Type);
- }
- if (Type == null) {
- Type = new TypeProxy(this.tok, "type_checking_error");
- }
- }
-
- public override Type! ShallowType {
- get {
- Type t0 = E0.ShallowType;
- Type t1 = E1.ShallowType;
- int len0 = t0.IsBv ? t0.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
- int len1 = t1.IsBv ? t1.BvBits : /*expression is not type correct, so just pick an arbitrary number of bits*/0;
- return Type.GetBvType(len0 + len1);
- }
- }
-
- public override AI.IExpr! IExpr {
- get {
- return this;
- }
- }
- public AI.IFunctionSymbol! FunctionSymbol {
- get { return AI.Bv.Concat;
- }
- }
- public IList/*<AI.IExpr!>*/! Arguments {
- get {
- AI.IExpr[] a = new AI.IExpr[2];
- a[0] = E0.IExpr;
- a[1] = E1.IExpr;
- return ArrayList.ReadOnly(a);
- }
- }
- public AI.IFunApp! CloneWithArguments(IList/*<AI.IExpr!>*/! args)
- {
- AI.IFunApp! retFun;
-
- if(args.Count == 2)
- {
- retFun = new BvConcatExpr(this.tok,
- BoogieFactory.IExpr2Expr((AI.IExpr!)args[0]),
- BoogieFactory.IExpr2Expr((AI.IExpr!)args[1]));
- }
- else
- {
- assert false; // If we are something wrong is happended
- }
- return retFun;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBvConcatExpr(this);
- }
- }
-}
-
diff --git a/Source/Core/AbsyQuant.ssc b/Source/Core/AbsyQuant.ssc
deleted file mode 100644
index 7515d37d..00000000
--- a/Source/Core/AbsyQuant.ssc
+++ /dev/null
@@ -1,860 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - AbsyQuant.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie
-{
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.Contracts;
- using Microsoft.Basetypes;
-
-
- //---------------------------------------------------------------------
- // Quantifiers and general binders
- //---------------------------------------------------------------------
-
- public enum BinderKind {
- Forall,
- Exists,
- Lambda
- }
-
- public abstract class BinderExpr : Expr
- {
- public TypeVariableSeq! TypeParameters;
- public VariableSeq! Dummies;
- public QKeyValue Attributes;
- public Expr! Body;
-
- public BinderExpr(IToken! tok, TypeVariableSeq! typeParameters,
- VariableSeq! dummies, QKeyValue kv, Expr! body)
- requires dummies.Length + typeParameters.Length > 0;
- {
- base(tok);
-
- TypeParameters = typeParameters;
- Dummies = dummies;
- Attributes = kv;
- Body = body;
- }
-
- abstract public BinderKind Kind { get; }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is BinderExpr) ||
- this.Kind != ((BinderExpr)obj).Kind) return false;
-
- BinderExpr other = (BinderExpr)obj;
- // Note, we consider quantifiers equal modulo the Triggers.
- return object.Equals(this.TypeParameters, other.TypeParameters)
- && object.Equals(this.Dummies, other.Dummies)
- && object.Equals(this.Body, other.Body);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- int h = this.Dummies.GetHashCode();
- // Note, we consider quantifiers equal modulo the Triggers.
- h ^= this.Body.GetHashCode();
- h = h*5 + this.TypeParameters.GetHashCode();
- h *= ((int)Kind + 1);
- return h;
- }
-
- protected virtual void EmitTypeHint(TokenTextWriter! stream)
- {
- }
-
- protected virtual void EmitTriggers(TokenTextWriter! stream)
- {
- }
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength, bool fragileContext)
- {
- stream.Write(this, "({0}", Kind.ToString().ToLower());
- this.EmitTypeHint(stream);
- Type.EmitOptionalTypeParams(stream, TypeParameters);
- stream.Write(this, " ");
- this.Dummies.Emit(stream);
- stream.Write(" :: ");
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Emit(stream);
- stream.Write(" ");
- }
- this.EmitTriggers(stream);
-
- this.Body.Emit(stream);
- stream.Write(")");
- }
-
- protected virtual void ResolveTriggers(ResolutionContext! rc)
- {
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
- if (rc.TriggerMode) {
- rc.Error(this, "quantifiers are not allowed in triggers");
- }
-
- int previousTypeBinderState = rc.TypeBinderState;
- try {
- foreach (TypeVariable! v in TypeParameters)
- rc.AddTypeBinder(v);
-
- rc.PushVarContext();
- foreach (Variable! v in Dummies)
- {
- v.Register(rc);
- v.Resolve(rc);
- }
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Resolve(rc);
- }
- this.ResolveTriggers(rc);
- Body.Resolve(rc);
- rc.PopVarContext();
-
- // establish a canonical order of the type parameters
- this.TypeParameters = Type.SortTypeParams(TypeParameters, Dummies.ToTypeSeq, null);
-
- } finally {
- rc.TypeBinderState = previousTypeBinderState;
- }
- }
-
- public override void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- foreach (Variable! v in Dummies) {
- assert !freeVars[v];
- }
- Body.ComputeFreeVariables(freeVars);
- foreach (Variable! v in Dummies) {
- foreach (TypeVariable! w in v.TypedIdent.Type.FreeVariables)
- freeVars.Add(w);
- }
- foreach (Variable! v in Dummies) {
- freeVars.Remove(v);
- }
- foreach (TypeVariable! v in TypeParameters) {
- freeVars.Remove(v);
- }
- }
-
- protected TypeVariableSeq! GetUnmentionedTypeParameters()
- {
- TypeVariableSeq! dummyParameters = Type.FreeVariablesIn(Dummies.ToTypeSeq);
- TypeVariableSeq! unmentionedParameters = new TypeVariableSeq ();
- foreach (TypeVariable! var in TypeParameters)
- if (!dummyParameters.Has(var))
- unmentionedParameters.Add(var);
- return unmentionedParameters;
- }
-
-
- public abstract AI.IFunctionSymbol! FunctionSymbol { get; }
-
- internal sealed class AIQuantifier : AI.IFunApp
- {
- internal readonly AIFunctionRep! arg;
- internal AIQuantifier(BinderExpr! realQuantifier, int dummyIndex)
- : this(new AIFunctionRep(realQuantifier, dummyIndex))
- {
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is AIQuantifier)) return false;
-
- AIQuantifier other = (AIQuantifier)obj;
- return object.Equals(this.arg, other.arg);
- }
- [Pure]
- public override int GetHashCode()
- {
- return this.arg.GetHashCode();
- }
-
- private AIQuantifier(AIFunctionRep! arg)
- {
- this.arg = arg;
- // base();
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunApp(this);
- }
-
- public AI.IFunctionSymbol! FunctionSymbol { get { return arg.RealQuantifier.FunctionSymbol; } }
-
- private IList/*?*/ argCache = null;
- public IList/*<IExpr!>*/! Arguments
- {
- get
- {
- if (argCache == null)
- {
- IList a = new ArrayList(1);
- a.Add(arg);
- argCache = ArrayList.ReadOnly(a);
- }
- return argCache;
- }
- }
-
- public AI.IFunApp! CloneWithArguments(IList/*<IExpr!>*/! args)
- {
- assume args.Count == 1;
-
- AIFunctionRep rep = args[0] as AIFunctionRep;
- if (rep != null)
- return new AIQuantifier(rep);
- else
- throw new System.NotImplementedException();
- }
-
- [Pure]
- public override string! ToString()
- {
- return string.Format("{0}({1})", FunctionSymbol, arg);
- }
- }
-
- internal sealed class AIFunctionRep : AI.IFunction
- {
- internal readonly BinderExpr! RealQuantifier;
- private readonly int dummyIndex;
-
- internal AIFunctionRep(BinderExpr! realQuantifier, int dummyIndex)
- {
- this.RealQuantifier = realQuantifier;
- this.dummyIndex = dummyIndex;
- assert realQuantifier.TypeParameters.Length == 0; // PR: don't know how to handle this yet
- // base();
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj)
- {
- if (obj == null) return false;
- if (!(obj is AIFunctionRep)) return false;
-
- AIFunctionRep other = (AIFunctionRep)obj;
- return object.Equals(this.RealQuantifier, other.RealQuantifier) && this.dummyIndex == other.dummyIndex;
- }
- [Pure]
- public override int GetHashCode()
- {
- return this.RealQuantifier.GetHashCode() ^ dummyIndex;
- }
-
- [Pure]
- public object DoVisit(AI.ExprVisitor! visitor)
- {
- return visitor.VisitFunction(this);
- }
-
- public AI.IVariable! Param
- {
- get { return (!)RealQuantifier.Dummies[dummyIndex]; }
- }
- public AI.AIType! ParamType { get { throw new System.NotImplementedException(); } }
-
- // We lazily convert to 1 dummy per quantifier representation for AIFramework
- private AI.IExpr/*?*/ bodyCache = null;
- public AI.IExpr! Body
- {
- get
- {
- if (bodyCache == null)
- {
- int dummyi = dummyIndex;
- int dummylen = RealQuantifier.Dummies.Length;
- assume dummylen > dummyi;
-
- // return the actual body if there are no more dummies
- if (dummyi + 1 == dummylen)
- bodyCache = RealQuantifier.Body.IExpr;
- else
- {
- AIQuantifier innerquant = new AIQuantifier(RealQuantifier, dummyi + 1);
- bodyCache = innerquant;
- }
- }
- return bodyCache;
- }
- }
- public AI.IFunction! CloneWithBody(AI.IExpr! body)
- {
- BinderExpr realquant;
-
- AIQuantifier innerquant = body as AIQuantifier;
- if (innerquant == null)
- {
- // new quantifier body, clone the real quantifier
- realquant = (BinderExpr)RealQuantifier.Clone();
- realquant.Body = BoogieFactory.IExpr2Expr(body);
- }
- else
- {
- if (innerquant.arg.dummyIndex > 0)
- {
- realquant = innerquant.arg.RealQuantifier;
- }
- else
- {
- realquant = (QuantifierExpr)RealQuantifier.Clone();
- VariableSeq! newdummies = new VariableSeq();
- newdummies.Add(Param);
- newdummies.AddRange(innerquant.arg.RealQuantifier.Dummies);
- realquant.Dummies = newdummies;
- realquant.Body = innerquant.arg.RealQuantifier.Body;
- }
- }
-
- return new AIFunctionRep(realquant, dummyIndex);
- }
- [Pure]
- public override string! ToString()
- {
- return string.Format("\\{0} :: {1}", Param, Body);
- }
- }
-
- private AI.IExpr aiexprCache = null;
- public override AI.IExpr! IExpr {
- get {
- if (TypeParameters.Length > 0)
- return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "anon", Type.Bool));
- if (aiexprCache == null)
- {
- aiexprCache = new AIQuantifier(this, 0);
- }
- return aiexprCache;
- }
- }
- }
-
- public class QKeyValue : Absy {
- public readonly string! Key;
- public readonly List<object!>! Params; // each element is either a string or an Expr
- public QKeyValue Next;
-
- public QKeyValue(IToken! tok, string! key, [Captured] List<object!>! parameters, QKeyValue next)
- {
- base(tok);
- Key = key;
- Params = parameters;
- Next = next;
- }
-
- public void Emit(TokenTextWriter! stream) {
- stream.Write("{:");
- stream.Write(Key);
- string sep = " ";
- foreach (object p in Params) {
- stream.Write(sep); sep = ", ";
- if (p is string) {
- stream.Write("\"");
- stream.Write((string)p);
- stream.Write("\"");
- } else {
- ((Expr)p).Emit(stream);
- }
- }
- stream.Write("}");
- }
-
- public override void Resolve(ResolutionContext! rc) {
- foreach (object p in Params) {
- if (p is Expr) {
- ((Expr)p).Resolve(rc);
- }
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc) {
- foreach (object p in Params) {
- if (p is Expr) {
- ((Expr)p).Typecheck(tc);
- }
- }
- }
- public void AddLast(QKeyValue! other){
- QKeyValue current = this;
- while(current.Next!=null){
- current = current.Next;
- }
- current.Next = other;
- }
- // Look for {:name string} in list of attributes.
- public static string? FindStringAttribute(QKeyValue? kv, string! name)
- {
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is string) {
- return (string)kv.Params[0];
- }
- }
- }
- return null;
- }
- // Look for {:name expr} in list of attributes.
- public static Expr? FindExprAttribute(QKeyValue? kv, string! name)
- {
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- if (kv.Params.Count == 1 && kv.Params[0] is Expr) {
- return (Expr)kv.Params[0];
- }
- }
- }
- return null;
- }
- // Return 'true' if {:name true} or {:name} is an attribute in 'kv'
- public static bool FindBoolAttribute(QKeyValue? kv, string! name)
- {
- for (; kv != null; kv = kv.Next) {
- if (kv.Key == name) {
- return kv.Params.Count == 0 ||
- (kv.Params.Count == 1 && kv.Params[0] is LiteralExpr && ((LiteralExpr)kv.Params[0]).IsTrue);
- }
- }
- return false;
- }
-
- public static int FindIntAttribute(QKeyValue? kv, string! name, int defl)
- {
- Expr? e = FindExprAttribute(kv, name);
- LiteralExpr? l = e as LiteralExpr;
- if (l != null && l.isBigNum)
- return l.asBigNum.ToIntSafe;
- return defl;
- }
- }
-
- public class Trigger : Absy {
- public readonly bool Pos;
- [Rep]
- public ExprSeq! Tr;
- invariant 1 <= Tr.Length;
- invariant !Pos ==> Tr.Length == 1;
- public Trigger Next;
-
- public Trigger(IToken! tok, bool pos, ExprSeq! tr)
- requires 1 <= tr.Length;
- requires !pos ==> tr.Length == 1;
- {
- this(tok, pos, tr, null);
- }
-
- public Trigger(IToken! tok, bool pos, ExprSeq! tr, Trigger next)
- : base(tok)
- requires 1 <= tr.Length;
- requires !pos ==> tr.Length == 1;
- {
- this.Pos = pos;
- this.Tr = tr;
- this.Next = next;
- // base(tok);
- }
-
- public void Emit(TokenTextWriter! stream) {
- stream.SetToken(this);
- assert this.Tr.Length >= 1;
- string! sep = Pos ? "{ " : "{:nopats ";
- foreach (Expr! e in this.Tr) {
- stream.Write(sep);
- sep = ", ";
- e.Emit(stream);
- }
- stream.Write(" }");
- }
- public override void Resolve(ResolutionContext! rc) {
- rc.TriggerMode = true;
- foreach (Expr! e in this.Tr) {
- e.Resolve(rc);
-
- // just a variable by itself is not allowed
- if (e is IdentifierExpr) {
- rc.Error(e, "a matching pattern must be more than just a variable by itself: {0}", e);
- }
-
- // the free-variable check is performed in the surrounding quantifier expression (because that's
- // where the bound variables are known)
- }
- rc.TriggerMode = false;
- }
-
- /// <summary>
- /// Add to "freeVars" the free variables in the triggering expressions.
- /// </summary>
- public void ComputeFreeVariables(Set /*Variable*/! freeVars) {
- foreach (Expr! e in this.Tr) {
- e.ComputeFreeVariables(freeVars);
- }
- }
-
- public override void Typecheck(TypecheckingContext! tc) {
- foreach (Expr! e in this.Tr) {
- e.Typecheck(tc);
- }
- }
-
- public void AddLast(Trigger other){
- Trigger current = this;
- while(current.Next!=null){
- current = current.Next;
- }
- current.Next = other;
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTrigger(this);
- }
- }
-
-
- public class ForallExpr : QuantifierExpr
- {
- public ForallExpr(IToken! tok, TypeVariableSeq! typeParams,
- VariableSeq! dummies, QKeyValue kv, Trigger triggers, Expr! body)
- requires dummies.Length + typeParams.Length > 0;
- {
- base(tok, typeParams, dummies, kv, triggers, body); // here for aesthetic reasons
- }
- public ForallExpr(IToken! tok, VariableSeq! dummies, Trigger triggers, Expr! body)
- requires dummies.Length > 0;
- {
- base(tok, new TypeVariableSeq(), dummies, null, triggers, body); // here for aesthetic reasons
- }
- public ForallExpr(IToken! tok, VariableSeq! dummies, Expr! body)
- requires dummies.Length > 0;
- {
- base(tok, new TypeVariableSeq(), dummies, null, null, body); // here for aesthetic reasons
- }
- public ForallExpr(IToken! tok, TypeVariableSeq! typeParams, VariableSeq! dummies, Expr! body)
- requires dummies.Length + typeParams.Length > 0;
- {
- base(tok, typeParams, dummies, null, null, body); // here for aesthetic reasons
- }
- public override AI.IFunctionSymbol! FunctionSymbol
- {
- get {
- return AI.Prop.Forall;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitForallExpr(this);
- }
-
- public override BinderKind Kind { get { return BinderKind.Forall; } }
- }
-
-
- public class ExistsExpr : QuantifierExpr
- {
- public ExistsExpr(IToken! tok, TypeVariableSeq! typeParams, VariableSeq! dummies,
- QKeyValue kv, Trigger triggers, Expr! body)
- requires dummies.Length + typeParams.Length > 0;
- {
- base(tok, typeParams, dummies, kv, triggers, body); // here for aesthetic reasons
- }
- public ExistsExpr(IToken! tok, VariableSeq! dummies, Trigger triggers, Expr! body)
- requires dummies.Length > 0;
- {
- base(tok, new TypeVariableSeq (), dummies, null, triggers, body); // here for aesthetic reasons
- }
- public ExistsExpr(IToken! tok, VariableSeq! dummies, Expr! body)
- requires dummies.Length > 0;
- {
- base(tok, new TypeVariableSeq(), dummies, null, null, body); // here for aesthetic reasons
- }
- public override AI.IFunctionSymbol! FunctionSymbol
- {
- get {
- return AI.Prop.Exists;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitExistsExpr(this);
- }
-
- public override BinderKind Kind { get { return BinderKind.Exists; } }
- }
-
-
-
- public abstract class QuantifierExpr : BinderExpr
- {
- public Trigger Triggers;
-
- static int SkolemIds = 0;
- public static int GetNextSkolemId()
- {
- SkolemIds++;
- return SkolemIds;
- }
-
- public readonly int SkolemId;
-
- public QuantifierExpr(IToken! tok, TypeVariableSeq! typeParameters,
- VariableSeq! dummies, QKeyValue kv, Trigger triggers, Expr! body)
- requires dummies.Length + typeParameters.Length > 0;
- {
- base(tok, typeParameters, dummies, kv, body);
-
- assert (this is ForallExpr) || (this is ExistsExpr);
-
- Triggers = triggers;
- SkolemId = SkolemIds++;
- }
-
- protected override void EmitTriggers(TokenTextWriter! stream)
- {
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- tr.Emit(stream);
- stream.Write(" ");
- }
- }
-
- // if the user says ( forall x :: forall y :: { f(x,y) } ... ) we transform it to
- // (forall x, y :: { f(x,y) } ... ) otherwise the prover ignores the trigger
- private void MergeAdjecentQuantifier()
- {
- QuantifierExpr qbody = Body as QuantifierExpr;
- if (!(qbody != null && (qbody is ForallExpr) == (this is ForallExpr) && Triggers == null)) {
- return;
- }
- qbody.MergeAdjecentQuantifier();
- if (qbody.Triggers == null) {
- return;
- }
- Body = qbody.Body;
- TypeParameters.AddRange(qbody.TypeParameters);
- Dummies.AddRange(qbody.Dummies);
- Triggers = qbody.Triggers;
- if (qbody.Attributes != null) {
- if (Attributes == null) {
- Attributes = qbody.Attributes;
- } else {
- QKeyValue p = Attributes;
- while (p.Next != null) {
- p = p.Next;
- }
- p.Next = qbody.Attributes;
- }
- }
- }
-
- #region never triggers
- private class NeverTriggerCollector : StandardVisitor
- {
- QuantifierExpr! parent;
- public NeverTriggerCollector(QuantifierExpr! p)
- {
- parent = p;
- }
-
- public override Expr! VisitNAryExpr(NAryExpr! node)
- {
- FunctionCall fn = node.Fun as FunctionCall;
- if (fn != null && ((!)fn.Func).NeverTrigger) {
- parent.Triggers = new Trigger(fn.Func.tok, false, new ExprSeq(node), parent.Triggers);
- }
- return base.VisitNAryExpr(node);
- }
- }
-
- private bool neverTriggerApplied;
- private void ApplyNeverTriggers()
- {
- if (neverTriggerApplied) {
- return;
- }
- neverTriggerApplied = true;
-
- for (Trigger t = Triggers; t != null; t = t.Next) {
- if (t.Pos) { return; }
- }
-
- NeverTriggerCollector visitor = new NeverTriggerCollector(this);
- visitor.VisitExpr(Body);
- }
- #endregion
-
- protected override void ResolveTriggers(ResolutionContext! rc)
- {
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- int prevErrorCount = rc.ErrorCount;
- tr.Resolve(rc);
- if (prevErrorCount == rc.ErrorCount) {
- // for positive triggers, make sure all bound variables are mentioned
- if (tr.Pos) {
- Set /*Variable*/ freeVars = new Set /*Variable*/ ();
- tr.ComputeFreeVariables(freeVars);
- foreach (Variable! v in Dummies) {
- if (!freeVars[v]) {
- rc.Error(tr, "trigger must mention all quantified variables, but does not mention: {0}", v);
- }
- }
- }
- }
- }
- }
-
- public override void Resolve(ResolutionContext! rc)
- {
- int oldErrorCount = rc.ErrorCount;
-
- this.MergeAdjecentQuantifier();
-
- base.Resolve(rc);
-
- if (oldErrorCount == rc.ErrorCount) {
- this.ApplyNeverTriggers();
- }
- }
-
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- tr.Typecheck(tc);
- }
- Body.Typecheck(tc);
- assert Body.Type != null; // follows from postcondition of Expr.Typecheck
- if (!Body.Type.Unify(Type.Bool))
- {
- tc.Error(this, "quantifier body must be of type bool");
- }
- this.Type = Type.Bool;
-
- // Check that type parameters occur in the types of the
- // dummies, or otherwise in the triggers. This can only be
- // done after typechecking
- TypeVariableSeq! unmentionedParameters = GetUnmentionedTypeParameters();
-
- if (unmentionedParameters.Length > 0) {
- // all the type parameters that do not occur in dummy types
- // have to occur in triggers
-
- for (Trigger tr = this.Triggers; tr != null; tr = tr.Next) {
- // for positive triggers, make sure all bound variables are mentioned
- if (tr.Pos) {
- Set /*Variable*/ freeVars = new Set /*Variable*/ ();
- tr.ComputeFreeVariables(freeVars);
- foreach (TypeVariable! v in unmentionedParameters) {
- if (!freeVars[v])
- tc.Error(tr,
- "trigger does not mention {0}, which does not occur in variables types either",
- v);
- }
- }
- }
- }
- }
- public override Type! ShallowType {
- get {
- return Type.Bool;
- }
- }
-
- }
-
-
- public class LambdaExpr : BinderExpr
- {
- public LambdaExpr(IToken! tok, TypeVariableSeq! typeParameters,
- VariableSeq! dummies, QKeyValue kv, Expr! body)
- requires dummies.Length + typeParameters.Length > 0;
- {
- base(tok, typeParameters, dummies, kv, body);
- }
-
- public override BinderKind Kind { get { return BinderKind.Lambda; } }
-
- public override void Resolve(ResolutionContext! rc)
- {
- base.Resolve(rc);
- }
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- for (QKeyValue kv = this.Attributes; kv != null; kv = kv.Next) {
- kv.Typecheck(tc);
- }
- Body.Typecheck(tc);
- assert Body.Type != null; // follows from postcondition of Expr.Typecheck
-
- TypeSeq! argTypes = new TypeSeq();
- foreach (Variable! v in Dummies) {
- argTypes.Add(v.TypedIdent.Type);
- }
- this.Type = new MapType(this.tok, this.TypeParameters, argTypes, Body.Type);
-
- // Check that type parameters occur in the types of the
- // dummies, or otherwise in the triggers. This can only be
- // done after typechecking
- TypeVariableSeq! unmentionedParameters = GetUnmentionedTypeParameters();
-
- if (unmentionedParameters.Length > 0) {
- tc.Error(this, "the type variable {0} does not occur in types of the lambda parameters", unmentionedParameters[0]);
- }
- }
-
- private Type? mapType;
- public override Type! ShallowType {
- get {
- if (mapType == null) {
- TypeSeq! argTypes = new TypeSeq();
- foreach (Variable! v in Dummies) {
- argTypes.Add(v.TypedIdent.Type);
- }
- mapType = new MapType(this.tok, this.TypeParameters, argTypes, Body.ShallowType);
- }
-
- return mapType;
- }
- }
-
- public override AI.IFunctionSymbol! FunctionSymbol
- {
- get {
- return AI.Prop.Lambda;
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitLambdaExpr(this);
- }
-
- }
-
-
-}
-
diff --git a/Source/Core/AbsyType.ssc b/Source/Core/AbsyType.ssc
deleted file mode 100644
index 55b8913f..00000000
--- a/Source/Core/AbsyType.ssc
+++ /dev/null
@@ -1,2857 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Absy.cs
-//---------------------------------------------------------------------------------------------
-
-namespace Microsoft.Boogie
-{
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using Microsoft.Boogie.AbstractInterpretation;
- using AI = Microsoft.AbstractInterpretationFramework;
- using Microsoft.Contracts;
-
- //=====================================================================
- //---------------------------------------------------------------------
- // Types
-
- public abstract class Type : Absy {
- public Type(IToken! token)
- : base(token)
- {
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively. Applying Clone to a type will return
- // a type in which all bound variables have been replaced with new
- // variables, whereas free variables have not changed
-
- public override Absy! Clone() {
- return this.Clone(new Dictionary<TypeVariable!, TypeVariable!> ());
- }
-
- public abstract Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap);
-
- /// <summary>
- /// Clones the type, but only syntactically. Anything resolved in the source
- /// type is left unresolved (that is, with just the name) in the destination type.
- /// </summary>
- public abstract Type! CloneUnresolved();
-
- //----------- Linearisation ----------------------------------
-
- public void Emit(TokenTextWriter! stream) {
- this.Emit(stream, 0);
- }
-
- public abstract void Emit(TokenTextWriter! stream, int contextBindingStrength);
-
- [Pure]
- public override string! ToString() {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false))
- {
- this.Emit(stream);
- }
- return buffer.ToString();
- }
-
- //----------- Equality ----------------------------------
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that)
- {
- if (ReferenceEquals(this, that))
- return true;
- Type thatType = that as Type;
- return thatType != null && this.Equals(thatType,
- new TypeVariableSeq (),
- new TypeVariableSeq ());
- }
-
- [Pure]
- public abstract bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables);
-
- // used to skip leading type annotations (subexpressions of the
- // resulting type might still contain annotations)
- internal virtual Type! Expanded { get {
- return this;
- } }
-
- //----------- Unification of types -----------
-
- /// <summary>
- /// Add a constraint that this==that, if possible, and return true.
- /// If not possible, return false (which may have added some partial constraints).
- /// No error is printed.
- /// </summary>
- public bool Unify(Type! that) {
- return Unify(that, new TypeVariableSeq(), new Dictionary<TypeVariable!, Type!> ());
- }
-
- public abstract bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! unifier);
- requires forall{TypeVariable key in unifier.Keys; unifiableVariables.Has(key)};
- requires IsIdempotent(unifier);
-
- [Pure]
- public static bool IsIdempotent(IDictionary<TypeVariable!, Type!>! unifier) {
- return forall{Type! t in unifier.Values;
- forall{TypeVariable! var in t.FreeVariables;
- !unifier.ContainsKey(var)}};
- }
-
-
-#if OLD_UNIFICATION
- // Compute a most general unification of two types. null is returned if
- // no such unifier exists. The unifier is not allowed to subtitute any
- // type variables other than the ones in "unifiableVariables"
- public IDictionary<TypeVariable!, Type!> Unify(Type! that,
- TypeVariableSeq! unifiableVariables) {
- Dictionary<TypeVariable!, Type!>! result = new Dictionary<TypeVariable!, Type!> ();
- try {
- this.Unify(that, unifiableVariables,
- new TypeVariableSeq (), new TypeVariableSeq (), result);
- } catch (UnificationFailedException) {
- return null;
- }
- return result;
- }
-
- // Compute an idempotent most general unifier and add the result to the argument
- // unifier. The result is true iff the unification succeeded
- public bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- // given mappings that need to be taken into account
- // the old unifier has to be idempotent as well
- IDictionary<TypeVariable!, Type!>! unifier)
- requires forall{TypeVariable key in unifier.Keys; unifiableVariables.Has(key)};
- requires IsIdempotent(unifier);
- {
- try {
- this.Unify(that, unifiableVariables,
- new TypeVariableSeq (), new TypeVariableSeq (), unifier);
- } catch (UnificationFailedException) {
- return false;
- }
- return true;
- }
-
- public abstract void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! result);
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public abstract Type! Substitute(IDictionary<TypeVariable!, Type!>! subst);
-
- //----------- Hashcodes ----------------------------------
-
- // Hack to be able to access the hashcode of superclasses further up
- // (from the subclasses of this class)
- [Pure]
- protected int GetBaseHashCode() {
- return base.GetHashCode();
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return this.GetHashCode(new TypeVariableSeq ());
- }
-
- [Pure]
- public abstract int GetHashCode(TypeVariableSeq! boundVariables);
-
- //----------- Resolution ----------------------------------
-
- public override void Resolve(ResolutionContext! rc)
- {
- System.Diagnostics.Debug.Fail("Type.Resolve should never be called." +
- " Use Type.ResolveType instead");
- }
-
- public abstract Type! ResolveType(ResolutionContext! rc);
-
- public override void Typecheck(TypecheckingContext! tc)
- {
- System.Diagnostics.Debug.Fail("Type.Typecheck should never be called");
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public abstract TypeVariableSeq! FreeVariables { get; }
-
- // determine the free type proxies in a type, in the order in which they occur
- public abstract List<TypeProxy!>! FreeProxies { get; }
-
- protected static void AppendWithoutDups<A>(List<A>! a, List<A>! b) {
- foreach (A x in b)
- if (!a.Contains(x))
- a.Add(x);
- }
-
- public bool IsClosed { get {
- return FreeVariables.Length == 0;
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- // the following methods should be used instead of simple casts or the
- // C# "is" operator, because they handle type synonym annotations and
- // type proxies correctly
-
- public virtual bool IsBasic { get { return false; } }
- public virtual bool IsInt { get { return false; } }
- public virtual bool IsBool { get { return false; } }
-
- public virtual bool IsVariable { get { return false; } }
- public virtual TypeVariable! AsVariable { get {
- assert false; // Type.AsVariable should never be called
- } }
- public virtual bool IsCtor { get { return false; } }
- public virtual CtorType! AsCtor { get {
- assert false; // Type.AsCtor should never be called
- } }
- public virtual bool IsMap { get { return false; } }
- public virtual MapType! AsMap { get {
- assert false; // Type.AsMap should never be called
- } }
- public virtual int MapArity { get {
- assert false; // Type.MapArity should never be called
- } }
- public virtual bool IsUnresolved { get { return false; } }
- public virtual UnresolvedTypeIdentifier! AsUnresolved { get {
- assert false; // Type.AsUnresolved should never be called
- } }
-
- public virtual bool IsBv { get { return false; } }
- public virtual int BvBits { get {
- assert false; // Type.BvBits should never be called
- } }
-
- public static readonly Type! Int = new BasicType(SimpleType.Int);
- public static readonly Type! Bool = new BasicType(SimpleType.Bool);
- private static BvType[] bvtypeCache;
-
- static public BvType! GetBvType(int sz)
- requires 0 <= sz;
- {
- if (bvtypeCache == null) {
- bvtypeCache = new BvType[128];
- }
- if (sz < bvtypeCache.Length) {
- BvType t = bvtypeCache[sz];
- if (t == null) {
- t = new BvType(sz);
- bvtypeCache[sz] = t;
- }
- return t;
- } else {
- return new BvType(sz);
- }
- }
-
- //------------ Match formal argument types on actual argument types
- //------------ and return the resulting substitution of type variables
-
-#if OLD_UNIFICATION
- public static IDictionary<TypeVariable!, Type!>!
- MatchArgumentTypes(TypeVariableSeq! typeParams,
- TypeSeq! formalArgs,
- ExprSeq! actualArgs,
- TypeSeq formalOuts,
- IdentifierExprSeq actualOuts,
- string! opName,
- TypecheckingContext! tc)
- requires formalArgs.Length == actualArgs.Length;
- requires formalOuts == null <==> actualOuts == null;
- requires formalOuts != null ==> formalOuts.Length == actualOuts.Length;
- {
- TypeVariableSeq! boundVarSeq0 = new TypeVariableSeq ();
- TypeVariableSeq! boundVarSeq1 = new TypeVariableSeq ();
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
-
- for (int i = 0; i < formalArgs.Length; ++i) {
- try {
- Type! actualType = (!)((!)actualArgs[i]).Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- assert forall{TypeVariable! var in typeParams;
- !actualType.FreeVariables.Has(var)};
- formalArgs[i].Unify(actualType,
- typeParams,
- boundVarSeq0, boundVarSeq1,
- subst);
- } catch (UnificationFailedException) {
- tc.Error(actualArgs[i],
- "invalid type for argument {0} in {1}: {2} (expected: {3})",
- i, opName, actualArgs[i].Type,
- // we insert the type parameters that have already been
- // chosen to get a more precise error message
- formalArgs[i].Substitute(subst));
- // the bound variable sequences should be empty ...
- // so that we can continue with the unification
- assert boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0;
- }
- }
-
- if (formalOuts != null) {
- for (int i = 0; i < formalOuts.Length; ++i) {
- try {
- Type! actualType = (!)((!)actualOuts[i]).Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- assert forall{TypeVariable! var in typeParams;
- !actualType.FreeVariables.Has(var)};
- formalOuts[i].Unify(actualType,
- typeParams,
- boundVarSeq0, boundVarSeq1,
- subst);
- } catch (UnificationFailedException) {
- tc.Error(actualOuts[i],
- "invalid type for result {0} in {1}: {2} (expected: {3})",
- i, opName, actualOuts[i].Type,
- // we insert the type parameters that have already been
- // chosen to get a more precise error message
- formalOuts[i].Substitute(subst));
- // the bound variable sequences should be empty ...
- // so that we can continue with the unification
- assert boundVarSeq0.Length == 0 && boundVarSeq1.Length == 0;
- }
- }
- }
-
- // we only allow type parameters to be substituted
- assert forall{TypeVariable! var in subst.Keys; typeParams.Has(var)};
-
- return subst;
- }
-#else
- public static IDictionary<TypeVariable!, Type!>!
- MatchArgumentTypes(TypeVariableSeq! typeParams,
- TypeSeq! formalArgs,
- ExprSeq! actualArgs,
- TypeSeq formalOuts,
- IdentifierExprSeq actualOuts,
- string! opName,
- TypecheckingContext! tc)
- requires formalArgs.Length == actualArgs.Length;
- requires formalOuts == null <==> actualOuts == null;
- requires formalOuts != null ==> formalOuts.Length == ((!)actualOuts).Length;
- requires tc != null ==> opName != null;
- // requires "actualArgs" and "actualOuts" to have been type checked
- {
- Dictionary<TypeVariable!, Type!> subst = new Dictionary<TypeVariable!, Type!>();
- foreach (TypeVariable! tv in typeParams) {
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- subst.Add(tv, proxy);
- }
-
- for (int i = 0; i < formalArgs.Length; i++) {
- Type formal = formalArgs[i].Substitute(subst);
- Type actual = (!)((!)actualArgs[i]).Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
-
- if (!formal.Unify(actual)) {
- assume tc != null; // caller expected no errors
- assert opName != null; // follows from precondition
- tc.Error((!)actualArgs[i],
- "invalid type for argument {0} in {1}: {2} (expected: {3})",
- i, opName, actual, formalArgs[i]);
- }
- }
-
- if (formalOuts != null) {
- for (int i = 0; i < formalOuts.Length; ++i) {
- Type formal = formalOuts[i].Substitute(subst);
- Type actual = (!)((!)actualOuts)[i].Type;
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
-
- if (!formal.Unify(actual)) {
- assume tc != null; // caller expected no errors
- assert opName != null; // follows from precondition
- tc.Error(actualOuts[i],
- "invalid type for out-parameter {0} in {1}: {2} (expected: {3})",
- i, opName, actual, formal);
- }
- }
- }
-
- return subst;
- }
-#endif
-
- //------------ Match formal argument types of a function or map
- //------------ on concrete types, substitute the result into the
- //------------ result type. Null is returned for type errors
-
- public static TypeSeq CheckArgumentTypes(TypeVariableSeq! typeParams,
- out List<Type!>! actualTypeParams,
- TypeSeq! formalIns,
- ExprSeq! actualIns,
- TypeSeq! formalOuts,
- IdentifierExprSeq actualOuts,
- IToken! typeCheckingSubject,
- string! opName,
- TypecheckingContext! tc)
- // requires "actualIns" and "actualOuts" to have been type checked
- {
- actualTypeParams = new List<Type!> ();
-
- if (formalIns.Length != actualIns.Length) {
- tc.Error(typeCheckingSubject, "wrong number of arguments in {0}: {1}",
- opName, actualIns.Length);
- // if there are no type parameters, we can still return the result
- // type and hope that the type checking proceeds
- return typeParams.Length == 0 ? formalOuts : null;
- } else if (actualOuts != null && formalOuts.Length != actualOuts.Length) {
- tc.Error(typeCheckingSubject, "wrong number of result variables in {0}: {1}",
- opName, actualOuts.Length);
- // if there are no type parameters, we can still return the result
- // type and hope that the type checking proceeds
- actualTypeParams = new List<Type!> ();
- return typeParams.Length == 0 ? formalOuts : null;
- }
-
- int previousErrorCount = tc.ErrorCount;
- IDictionary<TypeVariable!, Type!> subst =
- MatchArgumentTypes(typeParams, formalIns, actualIns,
- actualOuts != null ? formalOuts : null, actualOuts, opName, tc);
-
- foreach (TypeVariable! var in typeParams)
- actualTypeParams.Add(subst[var]);
-
- TypeSeq! actualResults = new TypeSeq ();
- foreach (Type! t in formalOuts) {
- actualResults.Add(t.Substitute(subst));
- }
- TypeVariableSeq resultFreeVars = FreeVariablesIn(actualResults);
- if (previousErrorCount != tc.ErrorCount) {
- // errors occured when matching the formal arguments
- // in case we have been able to substitute all type parameters,
- // we can still return the result type and hope that the
- // type checking proceeds in a meaningful manner
- if (forall{TypeVariable! var in typeParams; !resultFreeVars.Has(var)})
- return actualResults;
- else
- // otherwise there is no point in returning the result type,
- // type checking would only get confused even further
- return null;
- }
-
- assert forall{TypeVariable! var in typeParams; !resultFreeVars.Has(var)};
- return actualResults;
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- // about the same as Type.CheckArgumentTypes, but without
- // detailed error reports
- public static Type! InferValueType(TypeVariableSeq! typeParams,
- TypeSeq! formalArgs,
- Type! formalResult,
- TypeSeq! actualArgs) {
- IDictionary<TypeVariable!, Type!>! subst =
- InferTypeParameters(typeParams, formalArgs, actualArgs);
-
- Type! res = formalResult.Substitute(subst);
- // all type parameters have to be substituted with concrete types
- TypeVariableSeq! resFreeVars = res.FreeVariables;
- assert forall{TypeVariable! var in typeParams; !resFreeVars.Has(var)};
- return res;
- }
-
-#if OLD_UNIFICATION
- public static IDictionary<TypeVariable!, Type!>!
- InferTypeParameters(TypeVariableSeq! typeParams,
- TypeSeq! formalArgs,
- TypeSeq! actualArgs)
- requires formalArgs.Length == actualArgs.Length; {
-
- TypeVariableSeq! boundVarSeq0 = new TypeVariableSeq ();
- TypeVariableSeq! boundVarSeq1 = new TypeVariableSeq ();
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
-
- for (int i = 0; i < formalArgs.Length; ++i) {
- try {
- assert forall{TypeVariable! var in typeParams;
- !actualArgs[i].FreeVariables.Has(var)};
- formalArgs[i].Unify(actualArgs[i], typeParams,
- boundVarSeq0, boundVarSeq1, subst);
- } catch (UnificationFailedException) {
- System.Diagnostics.Debug.Fail("Type unification failed: " +
- formalArgs[i] + " vs " + actualArgs[i]);
- }
- }
-
- // we only allow type parameters to be substituted
- assert forall{TypeVariable! var in subst.Keys; typeParams.Has(var)};
- return subst;
- }
-#else
- /// <summary>
- /// like Type.CheckArgumentTypes, but assumes no errors
- /// (and only does arguments, not results; and takes actuals as TypeSeq, not ExprSeq)
- /// </summary>
- public static IDictionary<TypeVariable!, Type!>!
- InferTypeParameters(TypeVariableSeq! typeParams,
- TypeSeq! formalArgs,
- TypeSeq! actualArgs)
- requires formalArgs.Length == actualArgs.Length;
- {
- TypeSeq proxies = new TypeSeq();
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
- foreach (TypeVariable! tv in typeParams) {
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- proxies.Add(proxy);
- subst.Add(tv, proxy);
- }
-
- for (int i = 0; i < formalArgs.Length; i++) {
- Type formal = formalArgs[i].Substitute(subst);
- Type actual = actualArgs[i];
- // if the type variables to be matched occur in the actual
- // argument types, something has gone very wrong
- assert forall{TypeVariable! var in typeParams; !actual.FreeVariables.Has(var)};
-
- if (!formal.Unify(actual)) {
- assume false; // caller expected no errors
- }
- }
-
- return subst;
- }
-#endif
-
- //----------- Helper methods to deal with bound type variables ---------------
-
- public static void EmitOptionalTypeParams(TokenTextWriter! stream, TypeVariableSeq! typeParams) {
- if (typeParams.Length > 0) {
- stream.Write("<");
- typeParams.Emit(stream, ","); // default binding strength of 0 is ok
- stream.Write(">");
- }
- }
-
- // Sort the type parameters according to the order of occurrence in the argument types
- public static TypeVariableSeq! SortTypeParams(TypeVariableSeq! typeParams,
- TypeSeq! argumentTypes, Type resultType)
- ensures result.Length == typeParams.Length; {
- if (typeParams.Length == 0) {
- return typeParams;
- }
-
- TypeVariableSeq freeVarsInUse = FreeVariablesIn(argumentTypes);
- if (resultType != null) {
- freeVarsInUse.AppendWithoutDups(resultType.FreeVariables);
- }
- // "freeVarsInUse" is already sorted, but it may contain type variables not in "typeParams".
- // So, project "freeVarsInUse" onto "typeParams":
- TypeVariableSeq! sortedTypeParams = new TypeVariableSeq ();
- foreach (TypeVariable! var in freeVarsInUse) {
- if (typeParams.Has(var)) {
- sortedTypeParams.Add(var);
- }
- }
-
- if (sortedTypeParams.Length < typeParams.Length)
- // add the type parameters not mentioned in "argumentTypes" in
- // the end of the list (this can happen for quantifiers)
- sortedTypeParams.AppendWithoutDups(typeParams);
-
- return sortedTypeParams;
- }
-
- // Check that each of the type parameters occurs in at least one argument type.
- // Return true if some type parameters appear only among "moreArgumentTypes" and
- // not in "argumentTypes".
- [Pure]
- public static bool CheckBoundVariableOccurrences(TypeVariableSeq! typeParams,
- TypeSeq! argumentTypes,
- TypeSeq moreArgumentTypes,
- IToken! resolutionSubject,
- string! subjectName,
- ResolutionContext! rc) {
- TypeVariableSeq freeVarsInArgs = FreeVariablesIn(argumentTypes);
- TypeVariableSeq moFreeVarsInArgs = moreArgumentTypes == null ? null : FreeVariablesIn(moreArgumentTypes);
- bool someTypeParamsAppearOnlyAmongMo = false;
- foreach (TypeVariable! var in typeParams) {
- if (rc.LookUpTypeBinder(var.Name) == var) // avoid to complain twice about variables that are bound multiple times
- {
- if (freeVarsInArgs.Has(var)) {
- // cool
- } else if (moFreeVarsInArgs != null && moFreeVarsInArgs.Has(var)) {
- someTypeParamsAppearOnlyAmongMo = true;
- } else {
- rc.Error(resolutionSubject,
- "type variable must occur in {0}: {1}",
- subjectName, var);
- }
- }
- }
- return someTypeParamsAppearOnlyAmongMo;
- }
-
- [Pure]
- public static TypeVariableSeq! FreeVariablesIn(TypeSeq! arguments) {
- TypeVariableSeq! res = new TypeVariableSeq ();
- foreach (Type! t in arguments)
- res.AppendWithoutDups(t.FreeVariables);
- return res;
- }
- }
-
- //=====================================================================
-
- public class BasicType : Type
- {
- public readonly SimpleType T;
- public BasicType(IToken! token, SimpleType t)
- : base(token)
- {
- T = t;
- // base(token);
- }
- public BasicType(SimpleType t)
- : base(Token.NoToken)
- {
- T = t;
- // base(Token.NoToken);
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively.
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- // BasicTypes are immutable anyway, we do not clone
- return this;
- }
-
- public override Type! CloneUnresolved() {
- return this;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- // no parentheses are necessary for basic types
- stream.SetToken(this);
- stream.Write("{0}", this);
- }
-
- [Pure]
- public override string! ToString()
- {
- switch (T)
- {
- case SimpleType.Int: return "int";
- case SimpleType.Bool: return "bool";
- }
- Debug.Assert(false, "bad type " + T);
- assert false; // make compiler happy
- }
-
- //----------- Equality ----------------------------------
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- // shortcut
- Type thatType = that as Type;
- if (thatType == null)
- return false;
- BasicType thatBasicType = TypeProxy.FollowProxy(thatType.Expanded) as BasicType;
- return thatBasicType != null && this.T == thatBasicType.T;
- }
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- return this.Equals(that);
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! unifier) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable) {
- return that.Unify(this, unifiableVariables, unifier);
- } else {
- return this.Equals(that);
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- } else {
- if (!this.Equals(that))
- throw UNIFICATION_FAILED;
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- return this;
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables)
- {
- return this.T.GetHashCode();
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- // nothing to resolve
- return this;
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public override TypeVariableSeq! FreeVariables {
- get {
- return new TypeVariableSeq (); // basic type are closed
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- return new List<TypeProxy!> ();
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic { get { return true; } }
- public override bool IsInt { get { return this.T == SimpleType.Int; } }
- public override bool IsBool { get { return this.T == SimpleType.Bool; } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBasicType(this);
- }
- }
-
- //=====================================================================
-
- public class BvType : Type
- {
- public readonly int Bits;
-
- public BvType(IToken! token, int bits)
- : base(token)
- {
- Bits = bits;
- }
-
- public BvType(int bits)
- : base(Token.NoToken)
- {
- Bits = bits;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively.
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- // BvTypes are immutable anyway, we do not clone
- return this;
- }
-
- public override Type! CloneUnresolved() {
- return this;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- // no parentheses are necessary for bitvector-types
- stream.SetToken(this);
- stream.Write("{0}", this);
- }
-
- [Pure]
- public override string! ToString()
- {
- return "bv" + Bits;
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- BvType thatBvType = TypeProxy.FollowProxy(that.Expanded) as BvType;
- return thatBvType != null && this.Bits == thatBvType.Bits;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! unifier) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable) {
- return that.Unify(this, unifiableVariables, unifier);
- } else {
- return this.Equals(that);
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- } else {
- if (!this.Equals(that))
- throw UNIFICATION_FAILED;
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- return this;
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables)
- {
- return this.Bits.GetHashCode();
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- // nothing to resolve
- return this;
- }
-
- // determine the free variables in a type, in the order in which the variables occur
- public override TypeVariableSeq! FreeVariables {
- get {
- return new TypeVariableSeq (); // bitvector-type are closed
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- return new List<TypeProxy!> ();
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBv { get { return true; } }
- public override int BvBits { get {
- return Bits;
- } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBvType(this);
- }
- }
-
- //=====================================================================
-
- // An AST node containing an identifier and a sequence of type arguments, which
- // will be turned either into a TypeVariable, into a CtorType or into a BvType
- // during the resolution phase
- public class UnresolvedTypeIdentifier : Type {
- public readonly string! Name;
- public readonly TypeSeq! Arguments;
-
- public UnresolvedTypeIdentifier(IToken! token, string! name) {
- this(token, name, new TypeSeq ());
- }
-
- public UnresolvedTypeIdentifier(IToken! token, string! name, TypeSeq! arguments)
- : base(token)
- {
- this.Name = name;
- this.Arguments = arguments;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.Clone(varMap));
- return new UnresolvedTypeIdentifier(tok, Name, newArgs);
- }
-
- public override Type! CloneUnresolved() {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.CloneUnresolved());
- return new UnresolvedTypeIdentifier(tok, Name, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Equals should never be called");
- return false; // to make the compiler happy
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- assert false; // UnresolvedTypeIdentifier.Unify should never be called
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- System.Diagnostics.Debug.Fail("UnresolvedTypeIdentifier.Unify should never be called");
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- assert false; // UnresolvedTypeIdentifier.Substitute should never be called
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- assert false; // UnresolvedTypeIdentifier.GetHashCode should never be called
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- // first case: the type name denotes a bitvector-type
- if (Name.StartsWith("bv") && Name.Length > 2) {
- bool is_bv = true;
- for (int i = 2; i < Name.Length; ++i) {
- if (!char.IsDigit(Name[i])) {
- is_bv = false;
- break;
- }
- }
- if (is_bv) {
- if (Arguments.Length > 0) {
- rc.Error(this,
- "bitvector types must not be applied to arguments: {0}",
- Name);
- }
- return new BvType(tok, int.Parse(Name.Substring(2)));
- }
- }
-
- // second case: the identifier is resolved to a type variable
- TypeVariable var = rc.LookUpTypeBinder(Name);
- if (var != null) {
- if (Arguments.Length > 0) {
- rc.Error(this,
- "type variables must not be applied to arguments: {0}",
- var);
- }
- return var;
- }
-
- // third case: the identifier denotes a type constructor and we
- // recursively resolve the arguments
- TypeCtorDecl ctorDecl = rc.LookUpType(Name);
- if (ctorDecl != null) {
- if (Arguments.Length != ctorDecl.Arity) {
- rc.Error(this,
- "type constructor received wrong number of arguments: {0}",
- ctorDecl);
- return this;
- }
- return new CtorType (tok, ctorDecl, ResolveArguments(rc));
- }
-
- // fourth case: the identifier denotes a type synonym
- TypeSynonymDecl synDecl = rc.LookUpTypeSynonym(Name);
- if (synDecl != null) {
- if (Arguments.Length != synDecl.TypeParameters.Length) {
- rc.Error(this,
- "type synonym received wrong number of arguments: {0}",
- synDecl);
- return this;
- }
- TypeSeq! resolvedArgs = ResolveArguments(rc);
-
-
- return new TypeSynonymAnnotation(this.tok, synDecl, resolvedArgs);
-
- }
-
- // otherwise: this name is not declared anywhere
- rc.Error(this, "undeclared type: {0}", Name);
- return this;
- }
-
- private TypeSeq! ResolveArguments(ResolutionContext! rc) {
- TypeSeq! resolvedArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- resolvedArgs.Add(t.ResolveType(rc));
- return resolvedArgs;
- }
-
- public override TypeVariableSeq! FreeVariables {
- get {
- return new TypeVariableSeq ();
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- return new List<TypeProxy!> ();
- } }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- stream.SetToken(this);
- // PR: should unresolved types be syntactically distinguished from resolved types?
- CtorType.EmitCtorType(this.Name, Arguments, stream, contextBindingStrength);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsUnresolved { get { return true; } }
- public override UnresolvedTypeIdentifier! AsUnresolved { get { return this; } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitUnresolvedTypeIdentifier(this);
- }
- }
-
- //=====================================================================
-
- public class TypeVariable : Type {
- public readonly string! Name;
-
- public TypeVariable(IToken! token, string! name)
- : base(token)
- {
- this.Name = name;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- // if this variable is mapped to some new variable, we take the new one
- // otherwise, return this
- TypeVariable res;
- varMap.TryGetValue(this, out res);
- if (res == null)
- return this;
- else
- return res;
- }
-
- public override Type! CloneUnresolved() {
- return this;
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- TypeVariable thatAsTypeVar = TypeProxy.FollowProxy(that.Expanded) as TypeVariable;
-
- if (thatAsTypeVar == null)
- return false;
-
- int thisIndex = thisBoundVariables.LastIndexOf(this);
- int thatIndex = thatBoundVariables.LastIndexOf(thatAsTypeVar);
- return (thisIndex >= 0 && thisIndex == thatIndex) ||
- (thisIndex == -1 && thatIndex == -1 &&
- Object.ReferenceEquals(this, thatAsTypeVar));
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- // an idempotent substitution that describes the
- // unification result up to a certain point
- IDictionary<TypeVariable!, Type!>! unifier) {
- that = that.Expanded;
- if (that is TypeProxy && !(that is ConstrainedProxy))
- return that.Unify(this, unifiableVariables, unifier);
-
- if (this.Equals(that))
- return true;
-
- if (unifiableVariables.Has(this)) {
- Type previousSubst;
- unifier.TryGetValue(this, out previousSubst);
- if (previousSubst == null) {
- return addSubstitution(unifier, that);
- } else {
- // we have to unify the old instantiation with the new one
- return previousSubst.Unify(that, unifiableVariables, unifier);
- }
- }
-
- // this cannot be instantiated with anything
- // but that possibly can ...
-
- TypeVariable tv = that as TypeVariable;
-
- return tv != null &&
- unifiableVariables.Has(tv) &&
- that.Unify(this, unifiableVariables, unifier);
- }
-
- // TODO: the following might cause problems, because when applying substitutions
- // to type proxies the substitutions are not propagated to the proxy
- // constraints (right now at least)
- private bool addSubstitution(IDictionary<TypeVariable!, Type!>! oldSolution,
- // the type that "this" is instantiated with
- Type! newSubst)
- requires !oldSolution.ContainsKey(this); {
-
- Dictionary<TypeVariable!, Type!>! newMapping = new Dictionary<TypeVariable!, Type!> ();
- // apply the old (idempotent) substitution to the new instantiation
- Type! substSubst = newSubst.Substitute(oldSolution);
- // occurs check
- if (substSubst.FreeVariables.Has(this))
- return false;
- newMapping.Add(this, substSubst);
-
- // apply the new substitution to the old ones to ensure idempotence
- List<TypeVariable!>! keys = new List<TypeVariable!> ();
- keys.AddRange(oldSolution.Keys);
- foreach (TypeVariable! var in keys)
- oldSolution[var] = oldSolution[var].Substitute(newMapping);
- oldSolution.Add(this, substSubst);
-
- assert IsIdempotent(oldSolution);
- return true;
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- int thisIndex = thisBoundVariables.LastIndexOf(this);
- if (thisIndex == -1) {
- // this is not a bound variable and can possibly be matched on that
- // that must not contain any bound variables
- TypeVariableSeq! thatFreeVars = that.FreeVariables;
- if (exists{TypeVariable! var in thatBoundVariables; thatFreeVars.Has(var)})
- throw UNIFICATION_FAILED;
-
- // otherwise, in case that is a typevariable it cannot be bound and
- // we can just check for equality
- if (this.Equals(that))
- return;
-
- if (!unifiableVariables.Has(this)) {
- // this cannot be instantiated with anything
- // but that possibly can ...
- if ((that is TypeVariable) &&
- unifiableVariables.Has(that as TypeVariable)) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- } else {
- throw UNIFICATION_FAILED;
- }
- }
-
- Type previousSubst;
- result.TryGetValue(this, out previousSubst);
- if (previousSubst == null) {
- addSubstitution(result, that);
- } else {
- // we have to unify the old instantiation with the new one
- previousSubst.Unify(that, unifiableVariables, thisBoundVariables, thatBoundVariables, result);
- }
- } else {
- // this is a bound variable, that also has to be one (with the same index)
- if (!(that is TypeVariable) ||
- thatBoundVariables.LastIndexOf(that) != thisIndex)
- throw UNIFICATION_FAILED;
- }
- }
-
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- Type res;
- if (subst.TryGetValue(this, out res)) {
- assert res != null;
- return res;
- } else {
- return this;
- }
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- int thisIndex = boundVariables.LastIndexOf(this);
- if (thisIndex == -1)
- return GetBaseHashCode();
- return thisIndex * 27473671;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- // never put parentheses around variables
- stream.SetToken(this);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- // nothing to resolve
- return this;
- }
-
- public override TypeVariableSeq! FreeVariables {
- get { return new TypeVariableSeq(this); }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- return new List<TypeProxy!> ();
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsVariable { get { return true; } }
- public override TypeVariable! AsVariable { get { return this; } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypeVariable(this);
- }
- }
-
- //=====================================================================
-
- public class TypeProxy : Type {
- static int proxies = 0;
- protected readonly string! Name;
-
- public TypeProxy(IToken! token, string! givenName)
- {
- this(token, givenName, "proxy");
- }
-
- protected TypeProxy(IToken! token, string! givenName, string! kind)
- {
- Name = givenName + "$" + kind + "#" + proxies;
- proxies++;
- base(token);
- }
-
- private Type proxyFor;
- public Type ProxyFor {
- // apply path shortening, and then return the value of proxyFor
- get {
- TypeProxy anotherProxy = proxyFor as TypeProxy;
- if (anotherProxy != null && anotherProxy.proxyFor != null) {
- // apply path shortening by bypassing "anotherProxy" (and possibly others)
- proxyFor = anotherProxy.ProxyFor;
- assert proxyFor != null;
- }
- return proxyFor;
- }
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Everything)]
- public static Type! FollowProxy(Type! t)
- ensures result is TypeProxy ==> ((TypeProxy)result).proxyFor == null;
- {
- if (t is TypeProxy) {
- Type p = ((TypeProxy)t).ProxyFor;
- if (p != null) {
- return p;
- }
- }
- return t;
- }
-
- protected void DefineProxy(Type! ty)
- requires ProxyFor == null;
- {
- // follow ty down to the leaf level, so that we can avoid creating a cycle
- ty = FollowProxy(ty);
- if (!object.ReferenceEquals(this, ty)) {
- proxyFor = ty;
- }
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
- }
- }
-
- public override Type! CloneUnresolved() {
- return new TypeProxy(this.tok, this.Name); // the clone will have a name that ends with $proxy<n>$proxy<m>
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- if (object.ReferenceEquals(this, that)) {
- return true;
- }
- Type p = ProxyFor;
- if (p != null) {
- return p.Equals(that, thisBoundVariables, thatBoundVariables);
- } else {
- // This proxy could be made to be equal to anything, so what to return?
- return false;
- }
- }
-
- //----------- Unification of types -----------
-
- // determine whether the occurs check fails: this is a strict subtype of that
- protected bool ReallyOccursIn(Type! that) {
- that = FollowProxy(that.Expanded);
- return that.FreeProxies.Contains(this) &&
- (that.IsCtor || that.IsMap && this != that && this.ProxyFor != that);
- }
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- } else {
- // unify this with that
- if (this.ReallyOccursIn(that))
- return false;
- DefineProxy(that.Expanded);
- return true;
- }
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Substitute(subst);
- } else {
- return this;
- }
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- Type p = ProxyFor;
- if (p != null) {
- return p.GetHashCode(boundVariables);
- } else {
- return GetBaseHashCode();
- }
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- Type p = ProxyFor;
- if (p != null) {
- p.Emit(stream, contextBindingStrength);
- } else {
- // no need for parentheses
- stream.SetToken(this);
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
- }
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- Type p = ProxyFor;
- if (p != null) {
- return p.ResolveType(rc);
- } else {
- return this;
- }
- }
-
- public override TypeVariableSeq! FreeVariables {
- get {
- Type p = ProxyFor;
- if (p != null) {
- return p.FreeVariables;
- } else {
- return new TypeVariableSeq();
- }
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- Type p = ProxyFor;
- if (p != null) {
- return p.FreeProxies;
- } else {
- List<TypeProxy!>! res = new List<TypeProxy!> ();
- res.Add(this);
- return res;
- }
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic { get {
- Type p = ProxyFor;
- return p != null && p.IsBasic;
- } }
- public override bool IsInt { get {
- Type p = ProxyFor;
- return p != null && p.IsInt;
- } }
- public override bool IsBool { get {
- Type p = ProxyFor;
- return p != null && p.IsBool;
- } }
-
- public override bool IsVariable { get {
- Type p = ProxyFor;
- return p != null && p.IsVariable;
- } }
- public override TypeVariable! AsVariable { get {
- Type p = ProxyFor;
- assume p != null;
- return p.AsVariable;
- } }
-
- public override bool IsCtor { get {
- Type p = ProxyFor;
- return p != null && p.IsCtor;
- } }
- public override CtorType! AsCtor { get {
- Type p = ProxyFor;
- assume p != null;
- return p.AsCtor;
- } }
- public override bool IsMap { get {
- Type p = ProxyFor;
- return p != null && p.IsMap;
- } }
- public override MapType! AsMap { get {
- Type p = ProxyFor;
- assume p != null;
- return p.AsMap;
- } }
- public override int MapArity { get {
- Type p = ProxyFor;
- assume p != null;
- return p.MapArity;
- } }
- public override bool IsUnresolved { get {
- Type p = ProxyFor;
- return p != null && p.IsUnresolved;
- } }
- public override UnresolvedTypeIdentifier! AsUnresolved { get {
- Type p = ProxyFor;
- assume p != null;
- return p.AsUnresolved;
- } }
-
- public override bool IsBv { get {
- Type p = ProxyFor;
- return p != null && p.IsBv;
- } }
- public override int BvBits { get {
- Type p = ProxyFor;
- assume p != null;
- return p.BvBits;
- } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypeProxy(this);
- }
- }
-
- public abstract class ConstrainedProxy : TypeProxy {
- protected ConstrainedProxy(IToken! token, string! givenName, string! kind) {
- base(token, givenName, kind);
- }
- }
-
- /// <summary>
- /// Each instance of this class represents a set of bitvector types. In particular, it represents
- /// a bitvector type bvN iff
- /// minBits ATMOST N and
- /// foreach constraint (t0,t1), the types represented by t0 and t1 are bitvector types whose
- /// number of bits add up to N.
- /// This means that the size of a BvTypeProxy p is constrained not only by p.minBits, but also
- /// by the size of various t0 and t1 types that are transitively part of BvTypeProxy constraints.
- /// If such a t0 or t1 were to get its ProxyFor field defined, then p would have to be further
- /// constrained too. This doesn't seem like it would ever occur in a Boogie 2 program, because:
- /// the only place where a BvTypeProxy with constraints can occur is as the type of a
- /// BvConcatExpr, and
- /// the types of all local variables are explicitly declared, which means that the types of
- /// subexpressions of a BvConcatExpr are not going to change other than via the type of the
- /// BvConcatExpr.
- /// So, this implementation of BvTypeProxy does not keep track of where a BvTypeProxy may occur
- /// transitively in some other BvTypeProxy's constraints.
- /// </summary>
- public class BvTypeProxy : ConstrainedProxy {
- public int MinBits;
- List<BvTypeConstraint!> constraints;
- class BvTypeConstraint {
- public Type! T0;
- public Type! T1;
- public BvTypeConstraint(Type! t0, Type! t1)
- requires t0.IsBv && t1.IsBv;
- {
- T0 = t0;
- T1 = t1;
- }
- }
-
- public BvTypeProxy(IToken! token, string! name, int minBits)
- {
- base(token, name, "bv" + minBits + "proxy");
- this.MinBits = minBits;
- }
-
- /// <summary>
- /// Requires that any further constraints to be placed on t0 and t1 go via the object to
- /// be constructed.
- /// </summary>
- public BvTypeProxy(IToken! token, string! name, Type! t0, Type! t1)
- requires t0.IsBv && t1.IsBv;
- {
- base(token, name, "bvproxy");
- t0 = FollowProxy(t0);
- t1 = FollowProxy(t1);
- this.MinBits = MinBitsFor(t0) + MinBitsFor(t1);
- List<BvTypeConstraint!> list = new List<BvTypeConstraint!>();
- list.Add(new BvTypeConstraint(t0, t1));
- this.constraints = list;
- }
-
- /// <summary>
- /// Construct a BvTypeProxy like p, but with minBits.
- /// </summary>
- private BvTypeProxy(BvTypeProxy! p, int minBits)
- {
- base(p.tok, p.Name, "");
- this.MinBits = minBits;
- this.constraints = p.constraints;
- }
-
- private BvTypeProxy(IToken! token, string! name, int minBits, List<BvTypeConstraint!> constraints) {
- base(token, name, "");
- this.MinBits = minBits;
- this.constraints = constraints;
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Everything)]
- private static int MinBitsFor(Type! t)
- requires t.IsBv;
- ensures 0 <= result;
- {
- if (t is BvType) {
- return t.BvBits;
- } else {
- return ((BvTypeProxy)t).MinBits;
- }
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
- }
- }
-
- public override Type! CloneUnresolved() {
- return new BvTypeProxy(this.tok, this.Name, this.MinBits, this.constraints); // the clone will have a name that ends with $bvproxy<n>$bvproxy<m>
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- }
-
- // unify this with that, if possible
- that = that.Expanded;
- that = FollowProxy(that);
-
- if (this.ReallyOccursIn(that))
- return false;
-
- TypeVariable tv = that as TypeVariable;
-
- if (tv != null && unifiableVariables.Has(tv))
- return that.Unify(this, unifiableVariables, result);
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- } else if (that is BvType) {
- if (MinBits <= that.BvBits) {
- if (constraints != null) {
- foreach (BvTypeConstraint btc in constraints) {
- int minT1 = MinBitsFor(btc.T1);
- int left = IncreaseBits(btc.T0, that.BvBits - minT1);
- left = IncreaseBits(btc.T1, minT1 + left);
- assert left == 0; // because it should always be possible to increase the total size of a BvTypeConstraint pair (t0,t1) arbitrarily
- }
- }
- DefineProxy(that);
- return true;
- }
- } else if (that is BvTypeProxy) {
- BvTypeProxy bt = (BvTypeProxy)that;
- // keep the proxy with the stronger constraint (that is, the higher minBits), but if either
- // has a constraints list, then concatenate both constraints lists and define the previous
- // proxies to the new one
- if (this.constraints != null || bt.constraints != null) {
- List<BvTypeConstraint!> list = new List<BvTypeConstraint!>();
- if (this.constraints != null) { list.AddRange(this.constraints); }
- if (bt.constraints != null) { list.AddRange(bt.constraints); }
- BvTypeProxy np = new BvTypeProxy(this.tok, this.Name, max{this.MinBits, bt.MinBits}, list);
- this.DefineProxy(np);
- bt.DefineProxy(np);
- } else if (this.MinBits <= bt.MinBits) {
- this.DefineProxy(bt);
- } else {
- bt.DefineProxy(this);
- }
- return true;
- } else if (that is ConstrainedProxy) {
- // only bitvector proxies can be unified with this BvTypeProxy
- return false;
- } else if (that is TypeProxy) {
- // define: that.ProxyFor := this;
- return that.Unify(this, unifiableVariables, result);
- }
- return false;
- }
-
- private static int IncreaseBits(Type! t, int to)
- requires t.IsBv && 0 <= to && MinBitsFor(t) <= to;
- ensures 0 <= result && result <= to;
- {
- t = FollowProxy(t);
- if (t is BvType) {
- return to - t.BvBits;
- } else {
- BvTypeProxy p = (BvTypeProxy)t;
- assert p.MinBits <= to;
- if (p.MinBits < to) {
- BvTypeProxy q = new BvTypeProxy(p, to);
- p.DefineProxy(q);
- }
- return 0; // we were able to satisfy the request completely
- }
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- if (this.ProxyFor == null) {
- // check that the constraints are clean and do not contain any
- // of the substituted variables (otherwise, we are in big trouble)
- assert forall{BvTypeConstraint! c in constraints;
- forall{TypeVariable! var in subst.Keys;
- !c.T0.FreeVariables.Has(var) && !c.T1.FreeVariables.Has(var)}};
- }
- return base.Substitute(subst);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBv { get {
- return true;
- } }
- public override int BvBits { get {
- // This method is supposed to return the number of bits supplied, but unless the proxy has been resolved,
- // we only have a lower bound on the number of bits supplied. But this method is not supposed to be
- // called until type checking has finished, at which time the minBits is stable.
- Type p = ProxyFor;
- if (p != null) {
- return p.BvBits;
- } else {
- return MinBits;
- }
- } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitBvTypeProxy(this);
- }
- }
-
- // Proxy representing map types with a certain arity. Apart from the arity,
- // a number of constraints on the index and value type of the map type may
- // be known (such constraints result from applied select and store operations).
- // Because map type can be polymorphic (in the most general case, each index or
- // value type is described by a separate type parameter) any combination of
- // constraints can be satisfied.
- public class MapTypeProxy : ConstrainedProxy {
- public readonly int Arity;
- private readonly List<Constraint>! constraints = new List<Constraint> ();
-
- // each constraint specifies that the given combination of argument/result
- // types must be a possible instance of the formal map argument/result types
- private struct Constraint {
- public readonly TypeSeq! Arguments;
- public readonly Type! Result;
-
- public Constraint(TypeSeq! arguments, Type! result) {
- Arguments = arguments;
- Result = result;
- }
-
- public Constraint Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- TypeSeq! args = new TypeSeq ();
- foreach (Type! t in Arguments)
- args.Add(t.Clone(varMap));
- Type! res = Result.Clone(varMap);
- return new Constraint(args, res);
- }
-
- public bool Unify(MapType! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result)
- requires Arguments.Length == that.Arguments.Length; {
- Dictionary<TypeVariable!, Type!>! subst = new Dictionary<TypeVariable!, Type!>();
- foreach (TypeVariable! tv in that.TypeParameters) {
- TypeProxy proxy = new TypeProxy(Token.NoToken, tv.Name);
- subst.Add(tv, proxy);
- }
-
- bool good = true;
- for (int i = 0; i < that.Arguments.Length; i++) {
- Type t0 = that.Arguments[i].Substitute(subst);
- Type t1 = this.Arguments[i];
- good &= t0.Unify(t1, unifiableVariables, result);
- }
- good &= that.Result.Substitute(subst).Unify(this.Result, unifiableVariables, result);
- return good;
- }
- }
-
- public MapTypeProxy(IToken! token, string! name, int arity)
- requires 0 <= arity; {
- base(token, name, "mapproxy");
- this.Arity = arity;
- }
-
- private void AddConstraint(Constraint c)
- requires c.Arguments.Length == Arity; {
-
- Type f = ProxyFor;
- MapType mf = f as MapType;
- if (mf != null) {
- bool success = c.Unify(mf, new TypeVariableSeq(), new Dictionary<TypeVariable!, Type!> ());
- assert success;
- return;
- }
-
- MapTypeProxy mpf = f as MapTypeProxy;
- if (mpf != null) {
- mpf.AddConstraint(c);
- return;
- }
-
- assert f == null; // no other types should occur as specialisations of this proxy
-
- constraints.Add(c);
- }
-
- public Type CheckArgumentTypes(ExprSeq! actualArgs,
- out TypeParamInstantiation! tpInstantiation,
- IToken! typeCheckingSubject,
- string! opName,
- TypecheckingContext! tc)
- {
- Type f = ProxyFor;
- MapType mf = f as MapType;
- if (mf != null)
- return mf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
-
- MapTypeProxy mpf = f as MapTypeProxy;
- if (mpf != null)
- return mpf.CheckArgumentTypes(actualArgs, out tpInstantiation, typeCheckingSubject, opName, tc);
-
- assert f == null; // no other types should occur as specialisations of this proxy
-
- // otherwise, we just record the constraints given by this usage of the map type
- TypeSeq! arguments = new TypeSeq ();
- foreach (Expr! e in actualArgs)
- arguments.Add(e.Type);
- Type! result = new TypeProxy (tok, "result");
- AddConstraint(new Constraint (arguments, result));
-
- TypeSeq! argumentsResult = new TypeSeq ();
- foreach (Expr! e in actualArgs)
- argumentsResult.Add(e.Type);
- argumentsResult.Add(result);
-
- tpInstantiation = new MapTypeProxyParamInstantiation(this, argumentsResult);
- return result;
- }
-
- //----------- Cloning ----------------------------------
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Clone(varMap);
- } else {
- MapTypeProxy p2 = new MapTypeProxy(tok, Name, Arity);
- foreach (Constraint c in constraints)
- p2.AddConstraint(c.Clone(varMap));
- return p2; // the clone will have a name that ends with $mapproxy<n>$mapproxy<m> (hopefully)
- }
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- Type p = ProxyFor;
- if (p != null) {
- p.Emit(stream, contextBindingStrength);
- } else {
- stream.Write("[");
- string! sep = "";
- for (int i = 0; i < Arity; ++i) {
- stream.Write(sep);
- sep = ", ";
- stream.Write("?");
- }
- stream.Write("]?");
- }
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- Type p = ProxyFor;
- if (p != null) {
- return p.Unify(that, unifiableVariables, result);
- }
-
- // unify this with that, if possible
- that = that.Expanded;
- that = FollowProxy(that);
-
- if (this.ReallyOccursIn(that))
- return false;
-
- TypeVariable tv = that as TypeVariable;
-
- if (tv != null && unifiableVariables.Has(tv))
- return that.Unify(this, unifiableVariables, result);
-
- if (object.ReferenceEquals(this, that)) {
- return true;
- } else if (that is MapType) {
- MapType mapType = (MapType)that;
- if (mapType.Arguments.Length == Arity) {
- bool good = true;
- foreach (Constraint c in constraints)
- good &= c.Unify(mapType, unifiableVariables, result);
- if (good) {
- DefineProxy(mapType);
- return true;
- }
- }
- } else if (that is MapTypeProxy) {
- MapTypeProxy mt = (MapTypeProxy)that;
- if (mt.Arity == this.Arity) {
- // we propagate the constraints of this proxy to the more specific one
- foreach (Constraint c in constraints)
- mt.AddConstraint(c);
- DefineProxy(mt);
- return true;
- }
- } else if (that is ConstrainedProxy) {
- // only map-type proxies can be unified with this MapTypeProxy
- return false;
- } else if (that is TypeProxy) {
- // define: that.ProxyFor := this;
- return that.Unify(this, unifiableVariables, result);
- }
- return false;
- }
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- if (this.ProxyFor == null) {
- // check that the constraints are clean and do not contain any
- // of the substituted variables (otherwise, we are in big trouble)
- assert forall{Constraint c in constraints;
- forall{TypeVariable! var in subst.Keys;
- forall{Type! t in c.Arguments; !t.FreeVariables.Has(var)} &&
- !c.Result.FreeVariables.Has(var)}};
- }
- return base.Substitute(subst);
- }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsMap { get { return true; } }
- public override MapType! AsMap { get {
- Type p = ProxyFor;
- if (p != null) {
- return p.AsMap;
- } else {
- assert false; // what to do now?
- }
- } }
- public override int MapArity { get {
- return Arity;
- } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitMapTypeProxy(this);
- }
- }
-
- //=====================================================================
-
- // Used to annotate types with type synoyms that were used in the
- // original unresolved types. Such types should be considered as
- // equivalent to ExpandedType, the annotations are only used to enable
- // better pretty-printing
- public class TypeSynonymAnnotation : Type {
- public Type! ExpandedType;
-
- public readonly TypeSeq! Arguments;
- // is set during resolution and determines whether the right number of arguments is given
- public readonly TypeSynonymDecl! Decl;
-
- public TypeSynonymAnnotation(IToken! token, TypeSynonymDecl! decl, TypeSeq! arguments)
- : base(token)
- requires arguments.Length == decl.TypeParameters.Length;
- {
- this.Decl = decl;
- this.Arguments = arguments;
-
- // build a substitution that can be applied to the definition of
- // the type synonym
- IDictionary<TypeVariable!, Type!>! subst =
- new Dictionary<TypeVariable!, Type!> ();
- for (int i = 0; i < arguments.Length; ++i)
- subst.Add(decl.TypeParameters[i], arguments[i]);
-
- ExpandedType = decl.Body.Substitute(subst);
- }
-
- private TypeSynonymAnnotation(IToken! token, TypeSynonymDecl! decl, TypeSeq! arguments,
- Type! expandedType)
- : base(token) {
- this.Decl = decl;
- this.Arguments = arguments;
- this.ExpandedType = expandedType;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.Clone(varMap));
- Type! newExpandedType = ExpandedType.Clone(varMap);
- return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
- }
-
- public override Type! CloneUnresolved() {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.CloneUnresolved());
- return new TypeSynonymAnnotation(tok, Decl, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- return ExpandedType.Equals(that, thisBoundVariables, thatBoundVariables);
- }
-
- // used to skip leading type annotations
- internal override Type! Expanded { get {
- return ExpandedType.Expanded;
- } }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- return ExpandedType.Unify(that, unifiableVariables, result);
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- ExpandedType.Unify(that, unifiableVariables,
- thisBoundVariables, thatBoundVariables, result);
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- if (subst.Count == 0)
- return this;
- TypeSeq newArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- newArgs.Add(t.Substitute(subst));
- Type! newExpandedType = ExpandedType.Substitute(subst);
- return new TypeSynonymAnnotation(tok, Decl, newArgs, newExpandedType);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- return ExpandedType.GetHashCode(boundVariables);
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- stream.SetToken(this);
- CtorType.EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- TypeSeq resolvedArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- resolvedArgs.Add(t.ResolveType(rc));
- return new TypeSynonymAnnotation(tok, Decl, resolvedArgs);
- }
-
- public override TypeVariableSeq! FreeVariables { get {
- return ExpandedType.FreeVariables;
- } }
-
- public override List<TypeProxy!>! FreeProxies { get {
- return ExpandedType.FreeProxies;
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsBasic { get { return ExpandedType.IsBasic; } }
- public override bool IsInt { get { return ExpandedType.IsInt; } }
- public override bool IsBool { get { return ExpandedType.IsBool; } }
-
- public override bool IsVariable { get { return ExpandedType.IsVariable; } }
- public override TypeVariable! AsVariable { get { return ExpandedType.AsVariable; } }
- public override bool IsCtor { get { return ExpandedType.IsCtor; } }
- public override CtorType! AsCtor { get { return ExpandedType.AsCtor; } }
- public override bool IsMap { get { return ExpandedType.IsMap; } }
- public override MapType! AsMap { get { return ExpandedType.AsMap; } }
- public override bool IsUnresolved { get { return ExpandedType.IsUnresolved; } }
- public override UnresolvedTypeIdentifier! AsUnresolved { get {
- return ExpandedType.AsUnresolved; } }
-
- public override bool IsBv { get { return ExpandedType.IsBv; } }
- public override int BvBits { get { return ExpandedType.BvBits; } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitTypeSynonymAnnotation(this);
- }
- }
-
- //=====================================================================
-
- public class CtorType : Type {
- public readonly TypeSeq! Arguments;
- // is set during resolution and determines whether the right number of arguments is given
- public readonly TypeCtorDecl! Decl;
-
- public CtorType(IToken! token, TypeCtorDecl! decl, TypeSeq! arguments)
- : base(token)
- requires arguments.Length == decl.Arity;
- {
- this.Decl = decl;
- this.Arguments = arguments;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.Clone(varMap));
- return new CtorType(tok, Decl, newArgs);
- }
-
- public override Type! CloneUnresolved() {
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.CloneUnresolved());
- return new CtorType(tok, Decl, newArgs);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object that) {
- Type thatType = that as Type;
- if (thatType == null)
- return false;
- thatType = TypeProxy.FollowProxy(thatType.Expanded);
- // shortcut
- CtorType thatCtorType = thatType as CtorType;
- if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
- return false;
- if (Arguments.Length == 0)
- return true;
- return base.Equals(thatType);
- }
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- that = TypeProxy.FollowProxy(that.Expanded);
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !this.Decl.Equals(thatCtorType.Decl))
- return false;
- for (int i = 0; i < Arguments.Length; ++i) {
- if (!Arguments[i].Equals(thatCtorType.Arguments[i],
- thisBoundVariables, thatBoundVariables))
- return false;
- }
- return true;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable)
- return that.Unify(this, unifiableVariables, result);
-
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl)) {
- return false;
- } else {
- bool good = true;
- for (int i = 0; i < Arguments.Length; ++i)
- good &= Arguments[i].Unify(thatCtorType.Arguments[i], unifiableVariables, result);
- return good;
- }
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- }
-
- CtorType thatCtorType = that as CtorType;
- if (thatCtorType == null || !thatCtorType.Decl.Equals(Decl))
- throw UNIFICATION_FAILED;
- for (int i = 0; i < Arguments.Length; ++i)
- Arguments[i].Unify(thatCtorType.Arguments[i],
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- if (subst.Count == 0)
- return this;
- TypeSeq newArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- newArgs.Add(t.Substitute(subst));
- return new CtorType(tok, Decl, newArgs);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- int res = 1637643879 * Decl.GetHashCode();
- foreach (Type! t in Arguments)
- res = res * 3 + t.GetHashCode(boundVariables);
- return res;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- stream.SetToken(this);
- EmitCtorType(this.Decl.Name, Arguments, stream, contextBindingStrength);
- }
-
- internal static void EmitCtorType(string! name, TypeSeq! args, TokenTextWriter! stream, int contextBindingStrength) {
- int opBindingStrength = args.Length > 0 ? 0 : 2;
- if (opBindingStrength < contextBindingStrength)
- stream.Write("(");
-
- stream.Write("{0}", TokenTextWriter.SanitizeIdentifier(name));
- int i = args.Length;
- foreach (Type! t in args) {
- stream.Write(" ");
- // use a lower binding strength for the last argument
- // to allow map-types without parentheses
- t.Emit(stream, i == 1 ? 1 : 2);
- i = i - 1;
- }
-
- if (opBindingStrength < contextBindingStrength)
- stream.Write(")");
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- TypeSeq resolvedArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- resolvedArgs.Add(t.ResolveType(rc));
- return new CtorType(tok, Decl, resolvedArgs);
- }
-
- public override TypeVariableSeq! FreeVariables {
- get {
- TypeVariableSeq! res = new TypeVariableSeq ();
- foreach (Type! t in Arguments)
- res.AppendWithoutDups(t.FreeVariables);
- return res;
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- List<TypeProxy!>! res = new List<TypeProxy!> ();
- foreach (Type! t in Arguments)
- AppendWithoutDups(res, t.FreeProxies);
- return res;
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsCtor { get { return true; } }
- public override CtorType! AsCtor { get { return this; } }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitCtorType(this);
- }
- }
-
- //=====================================================================
-
- public class MapType : Type {
- // an invariant is that each of the type parameters has to occur as
- // free variable in at least one of the arguments
- public readonly TypeVariableSeq! TypeParameters;
- public readonly TypeSeq! Arguments;
- public Type! Result;
-
- public MapType(IToken! token, TypeVariableSeq! typeParameters, TypeSeq! arguments, Type! result)
- : base(token)
- {
- this.TypeParameters = typeParameters;
- this.Result = result;
- this.Arguments = arguments;
- }
-
- //----------- Cloning ----------------------------------
- // We implement our own clone-method, because bound type variables
- // have to be created in the right way. It is /not/ ok to just clone
- // everything recursively
-
- public override Type! Clone(IDictionary<TypeVariable!, TypeVariable!>! varMap) {
- IDictionary<TypeVariable!, TypeVariable!>! newVarMap =
- new Dictionary<TypeVariable!, TypeVariable!>();
- foreach (KeyValuePair<TypeVariable!, TypeVariable!> p in varMap) {
- if (!TypeParameters.Has(p.Key))
- newVarMap.Add(p);
- }
-
- TypeVariableSeq! newTypeParams = new TypeVariableSeq ();
- foreach (TypeVariable! var in TypeParameters) {
- TypeVariable! newVar = new TypeVariable (var.tok, var.Name);
- newVarMap.Add(var, newVar);
- newTypeParams.Add(newVar);
- }
-
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.Clone(newVarMap));
- Type! newResult = Result.Clone(newVarMap);
-
- return new MapType (this.tok, newTypeParams, newArgs, newResult);
- }
-
- public override Type! CloneUnresolved() {
- TypeVariableSeq! newTypeParams = new TypeVariableSeq ();
- foreach (TypeVariable! var in TypeParameters) {
- TypeVariable! newVar = new TypeVariable (var.tok, var.Name);
- newTypeParams.Add(newVar);
- }
-
- TypeSeq! newArgs = new TypeSeq ();
- foreach(Type! t in Arguments)
- newArgs.Add(t.CloneUnresolved());
- Type! newResult = Result.CloneUnresolved();
-
- return new MapType (this.tok, newTypeParams, newArgs, newResult);
- }
-
- //----------- Equality ----------------------------------
-
- [Pure]
- public override bool Equals(Type! that,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables) {
- that = TypeProxy.FollowProxy(that.Expanded);
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
- this.Arguments.Length != thatMapType.Arguments.Length)
- return false;
-
- foreach (TypeVariable! var in this.TypeParameters)
- thisBoundVariables.Add(var);
- foreach (TypeVariable! var in thatMapType.TypeParameters)
- thatBoundVariables.Add(var);
-
- try {
-
- for (int i = 0; i < Arguments.Length; ++i) {
- if (!Arguments[i].Equals(thatMapType.Arguments[i],
- thisBoundVariables, thatBoundVariables))
- return false;
- }
- if (!this.Result.Equals(thatMapType.Result,
- thisBoundVariables, thatBoundVariables))
- return false;
-
- } finally {
- // make sure that the bound variables are removed again
- for (int i = 0; i < this.TypeParameters.Length; ++i) {
- thisBoundVariables.Remove();
- thatBoundVariables.Remove();
- }
- }
-
- return true;
- }
-
- //----------- Unification of types -----------
-
- public override bool Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeProxy || that is TypeVariable)
- return that.Unify(this, unifiableVariables, result);
-
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
- this.Arguments.Length != thatMapType.Arguments.Length)
- return false;
-
- // treat the bound variables of the two map types as equal...
- Dictionary<TypeVariable!, Type!>! subst0 = new Dictionary<TypeVariable!, Type!>();
- Dictionary<TypeVariable!, Type!>! subst1 = new Dictionary<TypeVariable!, Type!>();
- TypeVariableSeq freshies = new TypeVariableSeq();
- for (int i = 0; i < this.TypeParameters.Length; i++) {
- TypeVariable tp0 = this.TypeParameters[i];
- TypeVariable tp1 = thatMapType.TypeParameters[i];
- TypeVariable freshVar = new TypeVariable(tp0.tok, tp0.Name);
- freshies.Add(freshVar);
- subst0.Add(tp0, freshVar);
- subst1.Add(tp1, freshVar);
- }
- // ... and then unify the domain and range types
- bool good = true;
- for (int i = 0; i < this.Arguments.Length; i++) {
- Type t0 = this.Arguments[i].Substitute(subst0);
- Type t1 = thatMapType.Arguments[i].Substitute(subst1);
- good &= t0.Unify(t1, unifiableVariables, result);
- }
- Type r0 = this.Result.Substitute(subst0);
- Type r1 = thatMapType.Result.Substitute(subst1);
- good &= r0.Unify(r1, unifiableVariables, result);
-
- // Finally, check that none of the bound variables has escaped
- if (good && freshies.Length != 0) {
- // This is done by looking for occurrences of the fresh variables in the
- // non-substituted types ...
- TypeVariableSeq freeVars = this.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Has(fr)) { return false; } // fresh variable escaped
- freeVars = thatMapType.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Has(fr)) { return false; } // fresh variable escaped
-
- // ... and in the resulting unifier of type variables
- foreach (KeyValuePair<TypeVariable!, Type!> pair in result) {
- freeVars = pair.Value.FreeVariables;
- foreach (TypeVariable fr in freshies)
- if (freeVars.Has(fr)) { return false; } // fresh variable escaped
- }
- }
-
- return good;
- }
-
-#if OLD_UNIFICATION
- public override void Unify(Type! that,
- TypeVariableSeq! unifiableVariables,
- TypeVariableSeq! thisBoundVariables,
- TypeVariableSeq! thatBoundVariables,
- IDictionary<TypeVariable!, Type!>! result) {
- that = that.Expanded;
- if (that is TypeVariable) {
- that.Unify(this, unifiableVariables, thatBoundVariables, thisBoundVariables, result);
- return;
- }
-
- MapType thatMapType = that as MapType;
- if (thatMapType == null ||
- this.TypeParameters.Length != thatMapType.TypeParameters.Length ||
- this.Arguments.Length != thatMapType.Arguments.Length)
- throw UNIFICATION_FAILED;
-
- // ensure that no collisions occur
- if (this.collisionsPossible(result)) {
- ((MapType)this.Clone())
- .Unify(that, unifiableVariables,
- thisBoundVariables, thatBoundVariables, result);
- return;
- }
- if (thatMapType.collisionsPossible(result))
- thatMapType = (MapType)that.Clone();
-
- foreach (TypeVariable! var in this.TypeParameters)
- thisBoundVariables.Add(var);
- foreach (TypeVariable! var in thatMapType.TypeParameters)
- thatBoundVariables.Add(var);
-
- try {
-
- for (int i = 0; i < Arguments.Length; ++i)
- Arguments[i].Unify(thatMapType.Arguments[i],
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
- Result.Unify(thatMapType.Result,
- unifiableVariables,
- thisBoundVariables, thatBoundVariables,
- result);
-
- } finally {
- // make sure that the bound variables are removed again
- for (int i = 0; i < this.TypeParameters.Length; ++i) {
- thisBoundVariables.Remove();
- thatBoundVariables.Remove();
- }
- }
- }
-#endif
-
- //----------- Substitution of free variables with types not containing bound variables -----------------
-
- [Pure]
- private bool collisionsPossible(IDictionary<TypeVariable!, Type!>! subst) {
- // PR: could be written more efficiently
- return exists{TypeVariable! var in TypeParameters;
- subst.ContainsKey(var) ||
- exists{Type! t in subst.Values; t.FreeVariables.Has(var)}};
- }
-
- public override Type! Substitute(IDictionary<TypeVariable!, Type!>! subst) {
- if (subst.Count == 0)
- return this;
-
- // there are two cases in which we have to be careful:
- // * a variable to be substituted is shadowed by a variable binder
- // * a substituted term contains variables that are bound in the
- // type (variable capture)
- //
- // in both cases, we first clone the type to ensure that bound
- // variables are fresh
-
- if (collisionsPossible(subst)) {
- MapType! newType = (MapType)this.Clone();
- assert newType.Equals(this) && !newType.collisionsPossible(subst);
- return newType.Substitute(subst);
- }
-
- TypeSeq newArgs = new TypeSeq ();
- foreach (Type! t in Arguments)
- newArgs.Add(t.Substitute(subst));
- Type! newResult = Result.Substitute(subst);
-
- return new MapType(tok, TypeParameters, newArgs, newResult);
- }
-
- //----------- Hashcodes ----------------------------------
-
- [Pure]
- public override int GetHashCode(TypeVariableSeq! boundVariables) {
- int res = 7643761 * TypeParameters.Length + 65121 * Arguments.Length;
-
- foreach (TypeVariable! var in this.TypeParameters)
- boundVariables.Add(var);
-
- foreach (Type! t in Arguments)
- res = res * 5 + t.GetHashCode(boundVariables);
- res = res * 7 + Result.GetHashCode(boundVariables);
-
- for (int i = 0; i < this.TypeParameters.Length; ++i)
- boundVariables.Remove();
-
- return res;
- }
-
- //----------- Linearisation ----------------------------------
-
- public override void Emit(TokenTextWriter! stream, int contextBindingStrength)
- {
- stream.SetToken(this);
-
- const int opBindingStrength = 1;
- if (opBindingStrength < contextBindingStrength)
- stream.Write("(");
-
- EmitOptionalTypeParams(stream, TypeParameters);
-
- stream.Write("[");
- Arguments.Emit(stream, ","); // default binding strength of 0 is ok
- stream.Write("]");
- Result.Emit(stream); // default binding strength of 0 is ok
-
- if (opBindingStrength < contextBindingStrength)
- stream.Write(")");
- }
-
- //----------- Resolution ----------------------------------
-
- public override Type! ResolveType(ResolutionContext! rc) {
- int previousState = rc.TypeBinderState;
- try {
- foreach (TypeVariable! v in TypeParameters) {
- rc.AddTypeBinder(v);
- }
-
- TypeSeq resolvedArgs = new TypeSeq ();
- foreach (Type! ty in Arguments) {
- resolvedArgs.Add(ty.ResolveType(rc));
- }
-
- Type resolvedResult = Result.ResolveType(rc);
-
- CheckBoundVariableOccurrences(TypeParameters,
- resolvedArgs, new TypeSeq(resolvedResult),
- this.tok, "map arguments",
- rc);
-
- // sort the type parameters so that they are bound in the order of occurrence
- TypeVariableSeq! sortedTypeParams = SortTypeParams(TypeParameters, resolvedArgs, resolvedResult);
- return new MapType(tok, sortedTypeParams, resolvedArgs, resolvedResult);
- } finally {
- rc.TypeBinderState = previousState;
- }
- }
-
- public override TypeVariableSeq! FreeVariables {
- get {
- TypeVariableSeq! res = FreeVariablesIn(Arguments);
- res.AppendWithoutDups(Result.FreeVariables);
- foreach (TypeVariable! v in TypeParameters)
- res.Remove(v);
- return res;
- }
- }
-
- public override List<TypeProxy!>! FreeProxies { get {
- List<TypeProxy!>! res = new List<TypeProxy!> ();
- foreach (Type! t in Arguments)
- AppendWithoutDups(res, t.FreeProxies);
- AppendWithoutDups(res, Result.FreeProxies);
- return res;
- } }
-
- //----------- Getters/Issers ----------------------------------
-
- public override bool IsMap { get { return true; } }
- public override MapType! AsMap { get { return this; } }
- public override int MapArity { get {
- return Arguments.Length;
- } }
-
- //------------ Match formal argument types of the map
- //------------ on concrete types, substitute the result into the
- //------------ result type. Null is returned if so many type checking
- //------------ errors occur that the situation is hopeless
-
- public Type CheckArgumentTypes(ExprSeq! actualArgs,
- out TypeParamInstantiation! tpInstantiation,
- IToken! typeCheckingSubject,
- string! opName,
- TypecheckingContext! tc) {
- List<Type!>! actualTypeParams;
- TypeSeq actualResult =
- Type.CheckArgumentTypes(TypeParameters, out actualTypeParams, Arguments, actualArgs,
- new TypeSeq (Result), null, typeCheckingSubject, opName, tc);
- if (actualResult == null) {
- tpInstantiation = SimpleTypeParamInstantiation.EMPTY;
- return null;
- } else {
- assert actualResult.Length == 1;
- tpInstantiation = SimpleTypeParamInstantiation.From(TypeParameters, actualTypeParams);
- return actualResult[0];
- }
- }
-
- public override Absy! StdDispatch(StandardVisitor! visitor)
- {
- return visitor.VisitMapType(this);
- }
- }
-
- //---------------------------------------------------------------------
-
- public enum SimpleType { Int, Bool };
-
-
- //=====================================================================
-
- // Interface for representing the instantiations of type parameters of
- // polymorphic functions or maps. We introduce an own interface for this
- // instead of using a simple list or dictionary, because in some cases
- // (due to the type proxies for map types) the actual number and instantiation
- // of type parameters can only be determined very late.
- public interface TypeParamInstantiation {
- // return what formal type parameters there are
- List<TypeVariable!>! FormalTypeParams { get; }
- // given a formal type parameter, return the actual instantiation
- Type! this[TypeVariable! var] { get; }
- }
-
- public class SimpleTypeParamInstantiation : TypeParamInstantiation {
- private readonly List<TypeVariable!>! TypeParams;
- private readonly IDictionary<TypeVariable!, Type!>! Instantiations;
-
- public SimpleTypeParamInstantiation(List<TypeVariable!>! typeParams,
- IDictionary<TypeVariable!, Type!>! instantiations) {
- this.TypeParams = typeParams;
- this.Instantiations = instantiations;
- }
-
- public static TypeParamInstantiation!
- From(TypeVariableSeq! typeParams, List<Type!>! actualTypeParams)
- requires typeParams.Length == actualTypeParams.Count; {
- if (typeParams.Length == 0)
- return EMPTY;
-
- List<TypeVariable!>! typeParamList = new List<TypeVariable!> ();
- IDictionary<TypeVariable!, Type!>! dict = new Dictionary<TypeVariable!, Type!> ();
- for (int i = 0; i < typeParams.Length; ++i) {
- typeParamList.Add(typeParams[i]);
- dict.Add(typeParams[i], actualTypeParams[i]);
- }
- return new SimpleTypeParamInstantiation(typeParamList, dict);
- }
-
- public static readonly TypeParamInstantiation! EMPTY =
- new SimpleTypeParamInstantiation (new List<TypeVariable!> (),
- new Dictionary<TypeVariable!, Type!> ());
-
- // return what formal type parameters there are
- public List<TypeVariable!>! FormalTypeParams { get {
- return TypeParams;
- } }
- // given a formal type parameter, return the actual instantiation
- public Type! this[TypeVariable! var] { get {
- return Instantiations[var];
- } }
- }
-
- // Implementation of TypeParamInstantiation that refers to the current
- // value of a MapTypeProxy. This means that the values return by the
- // methods of this implementation can change in case the MapTypeProxy
- // receives further unifications.
- class MapTypeProxyParamInstantiation : TypeParamInstantiation {
- private readonly MapTypeProxy! Proxy;
-
- // the argument and result type of this particular usage of the map
- // type. these are necessary to derive the values of the type parameters
- private readonly TypeSeq! ArgumentsResult;
-
- // field that is initialised once all necessary information is available
- // (the MapTypeProxy is instantiated to an actual type) and the instantiation
- // of a type parameter is queried
- private IDictionary<TypeVariable!, Type!> Instantiations = null;
-
- public MapTypeProxyParamInstantiation(MapTypeProxy! proxy,
- TypeSeq! argumentsResult) {
- this.Proxy = proxy;
- this.ArgumentsResult = argumentsResult;
- }
-
- // return what formal type parameters there are
- public List<TypeVariable!>! FormalTypeParams { get {
- MapType realType = Proxy.ProxyFor as MapType;
- if (realType == null)
- // no instantiation of the map type is known, which means
- // that the map type is assumed to be monomorphic
- return new List<TypeVariable!> ();
- else
- return realType.TypeParameters.ToList();
- } }
-
- // given a formal type parameter, return the actual instantiation
- public Type! this[TypeVariable! var] { get {
- // then there has to be an instantiation that is a polymorphic map type
- if (Instantiations == null) {
- MapType realType = Proxy.ProxyFor as MapType;
- assert realType != null;
- TypeSeq! formalArgs = new TypeSeq ();
- foreach (Type! t in realType.Arguments)
- formalArgs.Add(t);
- formalArgs.Add(realType.Result);
- Instantiations =
- Type.InferTypeParameters(realType.TypeParameters, formalArgs, ArgumentsResult);
- }
- return Instantiations[var];
- } }
- }
-
-}
diff --git a/Source/Core/AssemblyInfo.ssc b/Source/Core/AssemblyInfo.ssc
deleted file mode 100644
index 6ed99a25..00000000
--- a/Source/Core/AssemblyInfo.ssc
+++ /dev/null
@@ -1,4 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-[assembly: AssemblyKeyFile("..\\InterimKey.snk")]
diff --git a/Source/Core/CommandLineOptions.ssc b/Source/Core/CommandLineOptions.ssc
deleted file mode 100644
index 6808be61..00000000
--- a/Source/Core/CommandLineOptions.ssc
+++ /dev/null
@@ -1,2109 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.IO;
-using System.Diagnostics;
-using Microsoft.Contracts;
-using Cci = System.Compiler;
-
-namespace Microsoft.Boogie
-{
- public class CommandLineOptions
- {
- public static string! VersionNumber { get { return (!)((!)System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location)).FileVersion; } }
- public const string ToolNameBoogie = "Boogie program verifier";
- public const string ToolNameSpecSharp = "Spec# program verifier";
- public const string ToolNameDafny = "Dafny program verifier";
- public static string! VersionSuffix { get { return " version " + VersionNumber + ", Copyright (c) 2003-2010, Microsoft."; } }
- public string! InputFileExtension {
- set
- modifies _toolname, _version;
- {
- switch (value) {
- case ".bpl": _toolname = ToolNameBoogie; break;
- case ".dfy": _toolname = ToolNameDafny; break;
- default: _toolname = ToolNameSpecSharp; break;
- }
- _version = _toolname + VersionSuffix;
- }
- }
- string! _toolname = ToolNameBoogie;
- string! _version = ToolNameBoogie + VersionSuffix;
- public string! ToolName { get { return _toolname; } }
- public string! Version { get { return _version; } }
-
- public static CommandLineOptions! Clo = new CommandLineOptions(); // singleton to access all global data
-
- public string! Environment = "";
- public string! FileName = "unknown";
-
- public const long Megabyte = 1048576;
-
- // Flags and arguments
-
- public bool RunningBoogieFromCommandLine = false; // "false" means running Boogie from the plug-in
- public bool RunningBoogieOnSsc = true; // "true" means running Boogie on ssc input while false means running it on bpl input
-
- public bool AttrHelpRequested = false;
-
- [Peer] public List<string!>! Files = new List<string!>();
- public List<string!>! ContractAssemblies = new List<string!>();
-
- public string! FileTimestamp = ((!)DateTime.Now.ToString("o")).Replace(':', '.');
- public void ExpandFilename(ref string pattern)
- {
- if (pattern != null) {
- pattern = pattern.Replace("@PREFIX@", LogPrefix).Replace("@TIME@", FileTimestamp);
- string fn = Files.Count == 0 ? "" : Files[Files.Count-1];
- fn = fn.Replace('/', '-').Replace('\\', '-');
- pattern = pattern.Replace("@FILE@", fn);
- }
- }
-
- public string PrintFile = null;
- public int PrintUnstructured = 0;
- invariant 0 <= PrintUnstructured && PrintUnstructured < 3; // 0 = print only structured, 1 = both structured and unstructured, 2 = only unstructured
- public bool PrintDesugarings = false;
- public string SimplifyLogFilePath = null;
- public string SMTLibOutputPath = "boogie-vc-@PROC@.smt";
- public string! LogPrefix = "";
- public bool PrintInstrumented = false;
- public bool InstrumentWithAsserts = false;
- public enum InstrumentationPlaces { LoopHeaders, Everywhere }
- public InstrumentationPlaces InstrumentInfer = InstrumentationPlaces.LoopHeaders;
- public bool PrintWithUniqueASTIds = false;
- private string XmlSinkFilename = null;
- [Peer] public XmlSink XmlSink = null;
- public bool Wait = false;
- public bool Trace = false;
- public bool TraceTimes = false;
- public bool NoResolve = false;
- public bool NoTypecheck = false;
- public bool OverlookBoogieTypeErrors = false;
- public bool Verify = true;
- public bool TraceVerify = false;
- public int /*(0:3)*/ ErrorTrace = 1;
- public bool IntraproceduralInfer = true;
- public bool ContractInfer = false;
- public bool UseUncheckedContracts = false;
- public bool SimplifyLogFileAppend = false;
- public bool SoundnessSmokeTest = false;
-
- private bool noConsistencyChecks = false;
- public bool NoConsistencyChecks {
- get {return !Verify ? true : noConsistencyChecks;}
- set
- modifies noConsistencyChecks;
- {noConsistencyChecks = value;}
- }
-
- public string DafnyPrintFile = null;
- public bool Compile = true;
-
- public enum ProverWarnings { None, Stdout, Stderr }
- public ProverWarnings PrintProverWarnings = ProverWarnings.None;
- public int ProverShutdownLimit = 0;
-
- public enum SubsumptionOption { Never, NotForQuantifiers, Always }
- public SubsumptionOption UseSubsumption = SubsumptionOption.Always;
-
- public bool AlwaysAssumeFreeLoopInvariants = false;
-
- public enum ShowEnvironment { Never, DuringPrint, Always }
- public ShowEnvironment ShowEnv = ShowEnvironment.DuringPrint;
- public bool DontShowLogo = false;
-
- public int CheckingLevel = 2;
- invariant 0 <= CheckingLevel && CheckingLevel < 3;
- public enum Methodology { Boogie, VisibleState }
- public Methodology MethodologySelection = Methodology.Boogie;
- public int OrderStrength = 0;
- invariant 0 <= OrderStrength && OrderStrength < 2;
- public bool UseArithDistributionAxioms = false;
- public int SummationAxiomStrength = 1;
- invariant 0 <= SummationAxiomStrength && SummationAxiomStrength < 2;
- public int InductiveMinMax = 0;
- invariant 0 <= InductiveMinMax && InductiveMinMax < 6;
- public int FCOStrength = 5;
- invariant 0 <= FCOStrength && FCOStrength < 6;
- public int LoopUnrollCount = -1; // -1 means don't unroll loops
- public int LoopFrameConditions = -1; // -1 means not specified -- this will be replaced by the "implications" section below
- invariant -1 <= LoopFrameConditions && LoopFrameConditions < 3;
- public int ModifiesDefault = 5;
- invariant 0 <= ModifiesDefault && ModifiesDefault < 7;
- public bool LocalModifiesChecks = true;
- public bool NoVerifyByDefault = false;
- public enum OwnershipModelOption { Standard, Experimental, Trivial }
- public OwnershipModelOption OwnershipModelEncoding = OwnershipModelOption.Standard;
- public int PrintErrorModel = 0;
- public string PrintErrorModelFile = null;
- invariant (0 <= PrintErrorModel && PrintErrorModel <= 2) || PrintErrorModel == 4;
- public bool CEVPrint = false;
- public int EnhancedErrorMessages = 0;
- invariant 0 <= EnhancedErrorMessages && EnhancedErrorMessages < 2;
- public bool ForceBplErrors = false; // if true, boogie error is shown even if "msg" attribute is present
-
- public enum BvHandling { None, Z3Native, ToInt }
- public BvHandling Bitvectors = BvHandling.Z3Native;
-
- public bool UseArrayTheory = false;
- public bool MonomorphicArrays { get { return UseArrayTheory || TypeEncodingMethod == TypeEncoding.Monomorphic; } }
- public bool ExpandLambdas = true; // not useful from command line, only to be set to false programatically
-
- public bool DoModSetAnalysis = false;
- public bool UseAbstractInterpretation = true; // true iff the user want to use abstract interpretation
- public int /*0..9*/StepsBeforeWidening = 0; // The number of steps that must be done before applying a widen operator
- invariant 0 <= StepsBeforeWidening && StepsBeforeWidening <= 9;
-
- public enum VCVariety { Structured, Block, Local, BlockNested, BlockReach, BlockNestedReach, Dag, Doomed, Unspecified }
- public VCVariety vcVariety = VCVariety.Unspecified; // will not be Unspecified after command line has been parsed
- public bool useDoomDebug = false; // Will use doomed analysis to search for errors if set
-
- public bool RemoveEmptyBlocks = true;
- public bool CoalesceBlocks = true;
-
- [Rep] public ProverFactory TheProverFactory;
- public string ProverName;
- [Peer] public List<string!>! ProverOptions = new List<string!>();
-
- public int BracketIdsInVC = -1; // -1 - not specified, 0 - no, 1 - yes
- public bool CausalImplies = false;
- invariant -1 <= BracketIdsInVC && BracketIdsInVC <= 1;
- public int SimplifyProverMatchDepth = -1; // -1 means not specified
- public int ProverKillTime = -1; // -1 means not specified
- public int SmokeTimeout = 10; // default to 10s
- public int ProverCCLimit = 5;
- public bool z3AtFlag = true;
- public bool RestartProverPerVC = false;
-
- public double VcsMaxCost = 1.0;
- public double VcsPathJoinMult = 0.8;
- public double VcsPathCostMult = 1.0;
- public double VcsAssumeMult = 0.01;
- public double VcsPathSplitMult = 0.5; // 0.5-always, 2-rarely do path splitting
- public int VcsMaxSplits = 1;
- public int VcsMaxKeepGoingSplits = 1;
- public int VcsFinalAssertTimeout = 30;
- public int VcsKeepGoingTimeout = 1;
- public int VcsCores = 1;
- public bool VcsDumpSplits = false;
-
- public bool houdiniEnabled = false;
- public bool DebugRefuted = false;
-
- public XmlSink XmlRefuted
- {
- get { if (DebugRefuted) return XmlSink; else return null; }
- }
-
- [Peer] public List<string!>! Z3Options = new List<string!>();
- public bool Z3types = false;
- public int Z3lets = 3; // 0 - none, 1 - only LET TERM, 2 - only LET FORMULA, 3 - (default) any
- invariant 0 <= Z3lets && Z3lets < 4;
-
- // Maximum amount of virtual memory (in bytes) for the prover to use
- //
- // Non-positive number indicates unbounded.
- public long MaxProverMemory = 100 * Megabyte;
-
- // Minimum number of prover calls before restart
- public int MinNumOfProverCalls = 5;
-
- public enum PlatformType{notSpecified, v1, v11, v2, cli1}
- public PlatformType TargetPlatform;
- public string TargetPlatformLocation;
- public string StandardLibraryLocation;
-
- // whether procedure inlining is enabled at call sites.
- public enum Inlining { None, Assert, Assume, Spec };
- public Inlining ProcedureInlining = Inlining.Assume;
- public bool PrintInlined = false;
- public bool ExtractLoops = false;
- public int LazyInlining = 0;
- public int StratifiedInlining = 0;
- public int StratifiedInliningOption = 0;
- public int RecursionBound = 500;
- public string CoverageReporterPath = null;
-
- public enum TypeEncoding { None, Predicates, Arguments, Monomorphic };
- public TypeEncoding TypeEncodingMethod = TypeEncoding.Predicates;
-
- public bool Monomorphize = false;
-
- public bool ReflectAdd = false;
-
- public int LiveVariableAnalysis = 1;
-
- // Static constructor
- static CommandLineOptions()
- {
- if (System.Type.GetType("Mono.Runtime") == null) { // MONO
- TraceListenerCollection! dbl = Debug.Listeners;
- assume dbl.IsPeerConsistent; // hangs off static field
-#if WHIDBEY
- dbl.Add(new ConsoleTraceListener());
-#else
- dpl.Add(new DefaultTraceListener());
-#endif
- }
- }
-
- private string methodToLog = null;
- private string methodToBreakOn = null;
-
- [Rep] private List<string!> procsToCheck = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateSubstring = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateMethod = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateMethodQualified = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateClass = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateClassQualified = null; // null means "no restriction"
- [Rep] private List<string!> methodsToTranslateFile = null; // null means "no restriction"
- [Rep] private List<string!>! methodsToTranslateExclude = new List<string!>();
-
- public class AiFlags
- {
- public bool Intervals = false;
- public bool Constant = false;
- public bool DynamicType = false;
- public bool Nullness = false;
- public bool Polyhedra = false;
- public bool DebugStatistics = false;
-
- public bool AnySet
- {
- get
- {
- return Intervals
- || Constant
- || DynamicType
- || Nullness
- || Polyhedra;
- }
- }
- }
- public AiFlags! Ai = new AiFlags();
-
- public class HoudiniFlags {
- public bool continueAtError = false;
- public bool incremental = false;
- }
-
- public HoudiniFlags! houdiniFlags = new HoudiniFlags();
-
- [Verify(false)]
- public CommandLineOptions() {
- // this is just to suppress verification.
- }
-
-
- /// <summary>
- /// Parses the command-line arguments "args" into the global flag variables. The possible result
- /// values are:
- /// -2: an error occurred and help was requested
- /// -1: no error occurred and help was requested
- /// 1: no error occurred and help was not requested
- /// 2: an error occurred and help was not requested
- /// </summary>
- /// <param name="args">Consumed ("captured" and possibly modified) by the method.</param>
- [Verify(false)]
- public int Parse([Captured] string[]! args)
- requires forall{int i in (0:args.Length); args[i] != null};
- ensures TheProverFactory != null;
- ensures vcVariety != VCVariety.Unspecified;
- ensures -2 <= result && result <= 2 && result != 0;
- {
- // save the command line options for the log files
- Environment += "Command Line Options:";
- foreach (string s in args)
- Environment += " " + s;
- args = (string[]!)args.Clone(); // the operations performed may mutate the array, so make a copy
- CommandLineParseState! ps = new CommandLineParseState(args);
- int res = 1; // the result value
-
- while (ps.i < args.Length)
- invariant ps.IsPeerConsistent;
- invariant ps.args == args;
- {
- ps.s = args[ps.i];
- assert ps.s != null;
- ps.s = ps.s.Trim();
-
- int colonIndex = ps.s.IndexOf(':');
- if (colonIndex >= 0 && (ps.s.StartsWith("-") || ps.s.StartsWith("/")))
- {
- ps.hasColonArgument = true;
- args[ps.i] = ps.s.Substring(colonIndex+1);
- ps.s = ps.s.Substring(0, colonIndex);
- }
- else
- {
- expose(ps) {
- ps.i++;
- }
- ps.hasColonArgument = false;
- }
- ps.nextIndex = ps.i;
-
-
- switch (ps.s)
- {
- case "-help":
- case "/help":
- case "-?":
- case "/?":
- if (ps.ConfirmArgumentCount(0)) {
- res = -1; // help requested
- }
- break;
-
- case "-attrHelp":
- case "/attrHelp":
- if (ps.ConfirmArgumentCount(0)) {
- AttrHelpRequested = true;
- }
- break;
-
- case "-infer":
- case "/infer":
- if (ps.ConfirmArgumentCount(1)) {
- foreach (char c in (!)args[ps.i])
- {
- switch (c)
- {
- case 'i': Ai.Intervals = true; UseAbstractInterpretation = true; break;
- case 'c': Ai.Constant = true; UseAbstractInterpretation = true; break;
- case 'd': Ai.DynamicType = true; UseAbstractInterpretation = true; break;
- case 'n': Ai.Nullness = true; UseAbstractInterpretation = true; break;
- case 'p': Ai.Polyhedra = true; UseAbstractInterpretation = true; break;
- case 's': Ai.DebugStatistics = true; UseAbstractInterpretation = true; break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- StepsBeforeWidening = (int) char.GetNumericValue(c); break;
- default:
- ps.Error("Invalid argument '{0}' to option {1}", c.ToString(), ps.s);
- break;
- }
- }
- }
- break;
-
- case "-noinfer":
- case "/noinfer":
- if (ps.ConfirmArgumentCount(0)) {
- UseAbstractInterpretation = false;
- }
- break;
-
- case "-log":
- case "/log":
- if (ps.hasColonArgument) {
- methodToLog = args[ps.i];
- ps.nextIndex = ps.i + 1;
- } else {
- methodToLog = "*";
- }
- break;
-
- case "-logInfer":
- case "/logInfer":
- Microsoft.AbstractInterpretationFramework.Lattice.LogSwitch = true;
- break;
-
- case "-break":
- case "/break":
- if (ps.hasColonArgument)
- {
- methodToBreakOn = args[ps.i];
- ps.nextIndex = ps.i + 1;
- }
- else
- {
- System.Diagnostics.Debugger.Break();
- }
- break;
-
- case "-launch":
- case "/launch":
- System.Diagnostics.Debugger.Launch();
- break;
-
- case "-proc":
- case "/proc":
- if (procsToCheck == null) {
- procsToCheck = new List<string!>();
- }
- if (ps.ConfirmArgumentCount(1)) {
- procsToCheck.Add((!)args[ps.i]);
- }
- break;
-
- case "-translate":
- case "/translate":
- if (methodsToTranslateSubstring == null) {
- methodsToTranslateSubstring = new List<string!>();
- }
- if (ps.ConfirmArgumentCount(1)) {
- methodsToTranslateSubstring.Add((!)args[ps.i]);
- }
- break;
-
- case "-trMethod":
- case "/trMethod":
- if (ps.ConfirmArgumentCount(1)) {
- string m = (!)args[ps.i];
- if (0 <= m.IndexOf('.')) {
- if (methodsToTranslateMethodQualified == null) {
- methodsToTranslateMethodQualified = new List<string!>();
- }
- methodsToTranslateMethodQualified.Add(m);
- } else {
- if (methodsToTranslateMethod == null) {
- methodsToTranslateMethod = new List<string!>();
- }
- methodsToTranslateMethod.Add(m);
- }
- }
- break;
-
- case "-trClass":
- case "/trClass":
- if (ps.ConfirmArgumentCount(1)) {
- string m = (!)args[ps.i];
- if (0 <= m.IndexOf('.')) {
- if (methodsToTranslateClassQualified == null) {
- methodsToTranslateClassQualified = new List<string!>();
- }
- methodsToTranslateClassQualified.Add(m);
- } else {
- if (methodsToTranslateClass == null) {
- methodsToTranslateClass = new List<string!>();
- }
- methodsToTranslateClass.Add(m);
- }
- }
- break;
-
- case "-trFile":
- case "/trFile":
- if (methodsToTranslateFile == null) {
- methodsToTranslateFile = new List<string!>();
- }
- if (ps.ConfirmArgumentCount(1)) {
- methodsToTranslateFile.Add((!)args[ps.i]);
- }
- break;
-
- case "-trExclude":
- case "/trExclude":
- if (ps.ConfirmArgumentCount(1)) {
- methodsToTranslateExclude.Add((!)args[ps.i]);
- }
- break;
-
- case "-xml":
- case "/xml":
- if (ps.ConfirmArgumentCount(1))
- {
- XmlSinkFilename = args[ps.i];
- }
- break;
-
- case "-print":
- case "/print":
- if (ps.ConfirmArgumentCount(1))
- {
- PrintFile = args[ps.i];
- }
- break;
-
- case "-dprint":
- case "/dprint":
- if (ps.ConfirmArgumentCount(1))
- {
- DafnyPrintFile = args[ps.i];
- }
- break;
-
- case "-compile":
- case "/compile": {
- int compile = 0;
- if (ps.GetNumericArgument(ref compile, 2)) {
- Compile = compile == 1;
- }
- break;
- }
-
- case "-contracts":
- case "/contracts":
- case "-c":
- case "/c":
- if (ps.ConfirmArgumentCount(1))
- {
- ContractAssemblies.Add((!)args[ps.i]);
- }
- break;
-
- case "-proverLog":
- case "/proverLog":
- if (ps.ConfirmArgumentCount(1))
- {
- SimplifyLogFilePath = args[ps.i];
- }
- break;
-
- case "-logPrefix":
- case "/logPrefix":
- if (ps.ConfirmArgumentCount(1))
- {
- string s = (!)args[ps.i];
- LogPrefix += s.Replace('/', '-').Replace('\\', '-');
- }
- break;
-
- case "-proverShutdownLimit":
- case "/proverShutdownLimit":
- ps.GetNumericArgument(ref ProverShutdownLimit);
- break;
-
- case "-smtOutput":
- case "/smtOutput":
- if (ps.ConfirmArgumentCount(1))
- {
- SMTLibOutputPath = args[ps.i];
- }
- break;
-
- case "-errorTrace":
- case "/errorTrace":
- ps.GetNumericArgument(ref ErrorTrace, 3);
- break;
-
- case "-level":
- case "/level":
- ps.GetNumericArgument(ref CheckingLevel, 3);
- break;
-
- case "-methodology":
- case "/methodology":
- if (ps.ConfirmArgumentCount(1))
- {
- switch (args[ps.i])
- {
- case "b":
- case "Boogie":
- case "boogie":
- MethodologySelection = Methodology.Boogie;
- break;
- case "vs":
- case "visible-state":
- MethodologySelection = Methodology.VisibleState;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-proverWarnings":
- case "/proverWarnings": {
- int pw = 0;
- if (ps.GetNumericArgument(ref pw, 3)) {
- switch (pw) {
- case 0:
- PrintProverWarnings = ProverWarnings.None;
- break;
- case 1:
- PrintProverWarnings = ProverWarnings.Stdout;
- break;
- case 2:
- PrintProverWarnings = ProverWarnings.Stderr;
- break;
- default:
- assert false; // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- break;
- }
-
- case "-env":
- case "/env": {
- int e = 0;
- if (ps.GetNumericArgument(ref e, 3)) {
- switch (e) {
- case 0:
- ShowEnv = ShowEnvironment.Never;
- break;
- case 1:
- ShowEnv = ShowEnvironment.DuringPrint;
- break;
- case 2:
- ShowEnv = ShowEnvironment.Always;
- break;
- default:
- assert false; // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- break;
- }
-
- case "-loopUnroll":
- case "/loopUnroll":
- ps.GetNumericArgument(ref LoopUnrollCount);
- break;
-
- case "-modifiesOnLoop":
- case "/modifiesOnLoop":
- ps.GetNumericArgument(ref LoopFrameConditions, 3);
- break;
-
- case "-modifiesDefault":
- case "/modifiesDefault":
- ps.GetNumericArgument(ref ModifiesDefault, 7);
- break;
-
- case "-localModifiesChecks":
- case "/localModifiesChecks":
- {
- int localChecks = 0;
- ps.GetNumericArgument(ref localChecks, 2);
- LocalModifiesChecks = (localChecks != 0);
- }
- break;
-
- case "-orderStrength":
- case "/orderStrength":
- ps.GetNumericArgument(ref OrderStrength, 2);
- break;
-
- case "-summationStrength":
- case "/summationStrength":
- ps.GetNumericArgument(ref SummationAxiomStrength, 2);
- break;
-
- case "-inductiveMinMax":
- case "/inductiveMinMax":
- ps.GetNumericArgument(ref InductiveMinMax, 6);
- break;
-
- case "-fcoStrength":
- case "/fcoStrength":
- ps.GetNumericArgument(ref FCOStrength, 6);
- break;
-
- case "-ownerModelEncoding":
- case "/ownerModelEncoding":
- if (ps.ConfirmArgumentCount(1))
- {
- switch (args[ps.i])
- {
- case "s":
- case "standard":
- OwnershipModelEncoding = OwnershipModelOption.Standard;
- break;
- case "e":
- case "experimental":
- OwnershipModelEncoding = OwnershipModelOption.Experimental;
- break;
- case "t":
- case "trivial":
- OwnershipModelEncoding = OwnershipModelOption.Trivial;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-printModel":
- case "/printModel":
- if (ps.ConfirmArgumentCount(1))
- {
- switch (args[ps.i])
- {
- case "0":
- PrintErrorModel = 0;
- break;
- case "1":
- PrintErrorModel = 1;
- break;
- case "2":
- PrintErrorModel = 2;
- break;
- case "4":
- PrintErrorModel = 4;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
-
- case "-cev":
- case "/cev":
- if (ps.ConfirmArgumentCount(1))
- {
- PrintErrorModelFile = args[ps.i];
- }
- CEVPrint = true;
- break;
-
- case "-printModelToFile":
- case "/printModelToFile":
- if (ps.ConfirmArgumentCount(1))
- {
- PrintErrorModelFile = args[ps.i];
- }
- break;
-
-
- case "-enhancedErrorMessages":
- case "/enhancedErrorMessages":
- ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
- break;
-
- case "-forceBplErrors":
- case "/forceBplErrors":
- ForceBplErrors = true;
- break;
-
- case "-bv":
- case "/bv":
- if (ps.ConfirmArgumentCount(1))
- {
- if (TheProverFactory == null) {
- TheProverFactory = ProverFactory.Load("Z3");
- ProverName = "Z3".ToUpper();
- }
-
- switch (args[ps.i])
- {
- case "n":
- Bitvectors = BvHandling.None;
- break;
- case "z":
- Bitvectors = BvHandling.Z3Native;
- break;
- case "i":
- Bitvectors = BvHandling.ToInt;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-contractInfer":
- case "/contractInfer":
- ContractInfer = true;
- TheProverFactory = ProverFactory.Load("ContractInference");
- ProverName = "ContractInference".ToUpper();
- break;
-
- case "-subsumption":
- case "/subsumption": {
- int s = 0;
- if (ps.GetNumericArgument(ref s, 3)) {
- switch (s) {
- case 0:
- UseSubsumption = SubsumptionOption.Never;
- break;
- case 1:
- UseSubsumption = SubsumptionOption.NotForQuantifiers;
- break;
- case 2:
- UseSubsumption = SubsumptionOption.Always;
- break;
- default:
- assert false; // postcondition of GetNumericArgument guarantees that we don't get here
- }
- }
- break;
- }
-
- case "-liveVariableAnalysis":
- case "/liveVariableAnalysis": {
- int lva = 0;
- if (ps.GetNumericArgument(ref lva, 3)) {
- LiveVariableAnalysis = lva;
- }
- break;
- }
-
- case "-removeEmptyBlocks":
- case "/removeEmptyBlocks": {
- int reb = 0;
- if (ps.GetNumericArgument(ref reb, 2)) {
- RemoveEmptyBlocks = reb == 1;
- }
- break;
- }
-
- case "-coalesceBlocks":
- case "/coalesceBlocks": {
- int cb = 0;
- if (ps.GetNumericArgument(ref cb, 2)) {
- CoalesceBlocks = cb == 1;
- }
- break;
- }
-
- case "/DoomDebug":
- vcVariety = VCVariety.Doomed;
- useDoomDebug = true;
- break;
-
- case "-vc":
- case "/vc":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "s":
- case "structured":
- vcVariety = VCVariety.Structured;
- break;
- case "b":
- case "block":
- vcVariety = VCVariety.Block;
- break;
- case "l":
- case "local":
- vcVariety = VCVariety.Local;
- break;
- case "n":
- case "nested":
- vcVariety = VCVariety.BlockNested;
- break;
- case "m":
- vcVariety = VCVariety.BlockNestedReach;
- break;
- case "r":
- vcVariety = VCVariety.BlockReach;
- break;
- case "d":
- case "dag":
- vcVariety = VCVariety.Dag;
- break;
- case "doomed":
- vcVariety = VCVariety.Doomed;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-prover":
- case "/prover":
- if (ps.ConfirmArgumentCount(1)) {
- TheProverFactory = ProverFactory.Load((!)args[ps.i]);
- ProverName = ((!)args[ps.i]).ToUpper();
- }
- break;
-
- case "-proverOpt":
- case "/proverOpt":
- if (ps.ConfirmArgumentCount(1)) {
- ProverOptions.Add((!)args[ps.i]);
- }
- break;
-
- case "-extractLoops":
- case "/extractLoops":
- if (ps.ConfirmArgumentCount(0)) {
- ExtractLoops = true;
- }
- break;
- case "-inline":
- case "/inline":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "none":
- ProcedureInlining = Inlining.None;
- break;
- case "assert":
- ProcedureInlining = Inlining.Assert;
- break;
- case "assume":
- ProcedureInlining = Inlining.Assume;
- break;
- case "spec":
- ProcedureInlining = Inlining.Spec;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
- case "-lazyInline":
- case "/lazyInline":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "0":
- LazyInlining = 0;
- break;
- case "1":
- LazyInlining = 1;
- break;
- case "2":
- LazyInlining = 2;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
- case "-stratifiedInline":
- case "/stratifiedInline":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "0":
- StratifiedInlining = 0;
- break;
- case "1":
- StratifiedInlining = 1;
- break;
- default:
- StratifiedInlining = Int32.Parse((!)args[ps.i]);
- //ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
- case "-recursionBound":
- case "/recursionBound":
- if (ps.ConfirmArgumentCount(1)) {
- RecursionBound = Int32.Parse((!)args[ps.i]);
- }
- break;
- case "-coverageReporter":
- case "/coverageReporter":
- if (ps.ConfirmArgumentCount(1)) {
- CoverageReporterPath = args[ps.i];
- }
- break;
- case "-stratifiedInlineOption":
- case "/stratifiedInlineOption":
- if (ps.ConfirmArgumentCount(1)) {
- StratifiedInliningOption = Int32.Parse((!)args[ps.i]);
- }
- break;
- case "-typeEncoding":
- case "/typeEncoding":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "n":
- case "none":
- TypeEncodingMethod = TypeEncoding.None;
- break;
- case "p":
- case "predicates":
- TypeEncodingMethod = TypeEncoding.Predicates;
- break;
- case "a":
- case "arguments":
- TypeEncodingMethod = TypeEncoding.Arguments;
- break;
- case "m":
- case "monomorphic":
- TypeEncodingMethod = TypeEncoding.Monomorphic;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-instrumentInfer":
- case "/instrumentInfer":
- if (ps.ConfirmArgumentCount(1)) {
- switch (args[ps.i])
- {
- case "e":
- InstrumentInfer = InstrumentationPlaces.Everywhere;
- break;
- case "h":
- InstrumentInfer = InstrumentationPlaces.LoopHeaders;
- break;
- default:
- ps.Error("Invalid argument \"{0}\" to option {1}", args[ps.i], ps.s);
- break;
- }
- }
- break;
-
- case "-vcBrackets":
- case "/vcBrackets":
- ps.GetNumericArgument(ref BracketIdsInVC, 2);
- break;
-
- case "-proverMemoryLimit":
- case "/proverMemoryLimit":
- {
- int d = 0;
- if (ps.GetNumericArgument(ref d)) {
- MaxProverMemory = d * Megabyte;
- }
- break;
- }
-
- case "-vcsMaxCost":
- case "/vcsMaxCost":
- ps.GetNumericArgument(ref VcsMaxCost);
- break;
-
- case "-vcsPathJoinMult":
- case "/vcsPathJoinMult":
- ps.GetNumericArgument(ref VcsPathJoinMult);
- break;
-
- case "-vcsPathCostMult":
- case "/vcsPathCostMult":
- ps.GetNumericArgument(ref VcsPathCostMult);
- break;
-
- case "-vcsAssumeMult":
- case "/vcsAssumeMult":
- ps.GetNumericArgument(ref VcsAssumeMult);
- break;
-
- case "-vcsPathSplitMult":
- case "/vcsPathSplitMult":
- ps.GetNumericArgument(ref VcsPathSplitMult);
- break;
-
- case "-vcsMaxSplits":
- case "/vcsMaxSplits":
- ps.GetNumericArgument(ref VcsMaxSplits);
- break;
-
- case "-vcsMaxKeepGoingSplits":
- case "/vcsMaxKeepGoingSplits":
- ps.GetNumericArgument(ref VcsMaxKeepGoingSplits);
- break;
-
- case "-vcsFinalAssertTimeout":
- case "/vcsFinalAssertTimeout":
- ps.GetNumericArgument(ref VcsFinalAssertTimeout);
- break;
-
- case "-vcsKeepGoingTimeout":
- case "/vcsKeepGoingTimeout":
- ps.GetNumericArgument(ref VcsKeepGoingTimeout);
- break;
-
- case "-vcsCores":
- case "/vcsCores":
- ps.GetNumericArgument(ref VcsCores);
- break;
-
- case "-simplifyMatchDepth":
- case "/simplifyMatchDepth":
- ps.GetNumericArgument(ref SimplifyProverMatchDepth);
- break;
-
- case "-timeLimit":
- case "/timeLimit":
- ps.GetNumericArgument(ref ProverKillTime);
- break;
-
- case "-smokeTimeout":
- case "/smokeTimeout":
- ps.GetNumericArgument(ref SmokeTimeout);
- break;
-
- case "-errorLimit":
- case "/errorLimit":
- ps.GetNumericArgument(ref ProverCCLimit);
- break;
-
- case "-z3opt":
- case "/z3opt":
- if (ps.ConfirmArgumentCount(1))
- {
- Z3Options.Add((!)args[ps.i]);
- }
- break;
-
- case "-z3lets":
- case "/z3lets":
- ps.GetNumericArgument(ref Z3lets, 4);
- break;
-
- case "-platform":
- case "/platform":
- if (ps.ConfirmArgumentCount(1))
- {
- StringCollection platformOptions = this.ParseNamedArgumentList(args[ps.i]);
- if (platformOptions != null && platformOptions.Count > 0){
- try{
- this.TargetPlatform = (PlatformType)(!)Enum.Parse(typeof(PlatformType), (!)platformOptions[0]);
- }
- catch {
- ps.Error("Bad /platform type '{0}'", platformOptions[0]);
- break;
- }
- if (platformOptions.Count > 1){
- this.TargetPlatformLocation = platformOptions[1];
- if (!Directory.Exists(platformOptions[1])) {
- ps.Error("/platform directory '{0}' does not exist", platformOptions[1]);
- break;
- }
- }
- }
- }
- break;
-
- case "-stdlib":
- case "/stdlib":
- if (ps.ConfirmArgumentCount(1))
- {
- this.StandardLibraryLocation = args[ps.i];
- }
- break;
-
- case "-Houdini":
- case "/Houdini":
- this.houdiniEnabled=true;
- if (ps.hasColonArgument) {
- if (ps.ConfirmArgumentCount(1)) {
- foreach (char c in (!)args[ps.i])
- {
- switch (c)
- {
- case 'c': houdiniFlags.continueAtError = true; break;
- case 'i': houdiniFlags.incremental = true; break;
- default : ps.Error("Unknown houdini flag: " + c + "\n"); break;
- }
- }
- }
- }
- break;
-
- default:
- assume true;
- bool option = false;
- if (ps.CheckBooleanFlag("printUnstructured", ref option)) {
- expose(this) {
- PrintUnstructured = option ? 1 : 0;
- }
- } else if (
- ps.CheckBooleanFlag("printDesugared", ref PrintDesugarings) ||
- ps.CheckBooleanFlag("printInstrumented", ref PrintInstrumented) ||
- ps.CheckBooleanFlag("printWithUniqueIds", ref PrintWithUniqueASTIds) ||
- ps.CheckBooleanFlag("wait", ref Wait) ||
- ps.CheckBooleanFlag("trace", ref Trace) ||
- ps.CheckBooleanFlag("traceTimes", ref TraceTimes) ||
- ps.CheckBooleanFlag("noResolve", ref NoResolve) ||
- ps.CheckBooleanFlag("noTypecheck", ref NoTypecheck) ||
- ps.CheckBooleanFlag("overlookTypeErrors", ref OverlookBoogieTypeErrors) ||
- ps.CheckBooleanFlag("noVerify", ref Verify, false) ||
- ps.CheckBooleanFlag("traceverify", ref TraceVerify) ||
- ps.CheckBooleanFlag("noConsistencyChecks", ref NoConsistencyChecks, true) ||
- ps.CheckBooleanFlag("alwaysAssumeFreeLoopInvariants", ref AlwaysAssumeFreeLoopInvariants, true) ||
- ps.CheckBooleanFlag("nologo", ref DontShowLogo) ||
- ps.CheckBooleanFlag("noVerifyByDefault", ref NoVerifyByDefault) ||
- ps.CheckBooleanFlag("useUncheckedContracts", ref UseUncheckedContracts) ||
- ps.CheckBooleanFlag("proverLogAppend", ref SimplifyLogFileAppend) ||
- ps.CheckBooleanFlag("checkInfer", ref InstrumentWithAsserts) ||
- ps.CheckBooleanFlag("interprocInfer", ref IntraproceduralInfer, false) ||
- ps.CheckBooleanFlag("restartProver", ref RestartProverPerVC) ||
- ps.CheckBooleanFlag("printInlined", ref PrintInlined) ||
- ps.CheckBooleanFlag("arithDistributionAxioms", ref UseArithDistributionAxioms) ||
- ps.CheckBooleanFlag("smoke", ref SoundnessSmokeTest) ||
- ps.CheckBooleanFlag("vcsDumpSplits", ref VcsDumpSplits) ||
- ps.CheckBooleanFlag("dbgRefuted", ref DebugRefuted) ||
- ps.CheckBooleanFlag("causalImplies", ref CausalImplies) ||
- ps.CheckBooleanFlag("reflectAdd", ref ReflectAdd) ||
- ps.CheckBooleanFlag("z3types", ref Z3types) ||
- ps.CheckBooleanFlag("z3multipleErrors", ref z3AtFlag, false) ||
- ps.CheckBooleanFlag("monomorphize", ref Monomorphize) ||
- ps.CheckBooleanFlag("useArrayTheory", ref UseArrayTheory) ||
- ps.CheckBooleanFlag("doModSetAnalysis", ref DoModSetAnalysis)
- )
- {
- // one of the boolean flags matched
- }
- else if (ps.s.StartsWith("-") || ps.s.StartsWith("/"))
- {
- ps.Error("unknown switch: {0}", ps.s);
- }
- else if (ps.ConfirmArgumentCount(0))
- {
- string filename = ps.s;
- string extension = Path.GetExtension(filename);
- if (extension != null) {
- InputFileExtension = extension.ToLower();
- }
- Files.Add(filename);
- FileName = filename;
- }
- break;
- }
- expose(ps) ps.i = ps.nextIndex;
- }
-
- assume true;
- if (ps.encounteredErrors) res *= 2;
- if (res < 0) { // help requested
- Usage();
- } else if (AttrHelpRequested) {
- AttributeUsage();
- } else if (ps.encounteredErrors) {
- Console.WriteLine("Use /help for available options");
- }
-
- SetProverOptions();
-
- if (Trace) { BoogieDebug.DoPrinting = true; } // reuse the -trace option for debug printing
- return res;
- }
-
- private void SetProverOptions()
- modifies this.*;
- ensures TheProverFactory != null;
- ensures vcVariety != VCVariety.Unspecified;
- {
- // expand macros in filenames, now that LogPrefix is fully determined
- ExpandFilename(ref XmlSinkFilename);
- ExpandFilename(ref PrintFile);
- ExpandFilename(ref DafnyPrintFile);
- ExpandFilename(ref SimplifyLogFilePath);
- ExpandFilename(ref SMTLibOutputPath);
- ExpandFilename(ref PrintErrorModelFile);
-
- assume XmlSink == null; // XmlSink is to be set here
- if (XmlSinkFilename != null) {
- XmlSink = new XmlSink(XmlSinkFilename);
- }
-
- if (TheProverFactory == null) {
- expose(this) {
- TheProverFactory = ProverFactory.Load("Z3");
- ProverName = "Z3".ToUpper();
- }
- }
-
- if (vcVariety == VCVariety.Unspecified) {
- vcVariety = TheProverFactory.DefaultVCVariety;
- }
-
- if (LoopFrameConditions == -1) {
- // /modifiesOnLoop not specified. Set its default depending on /localModifiesChecks
- if (LocalModifiesChecks) {
- LoopFrameConditions = 1;
- } else {
- LoopFrameConditions = 2;
- }
- }
-
- if (CEVPrint && PrintErrorModel == 0) {
- PrintErrorModel = 1;
- }
-
- switch (InductiveMinMax) {
- case 1: case 2: case 4: case 5:
- ReflectAdd = true; // these InductiveMinMax modes imply ReflectAdd
- break;
- default:
- break;
- }
-
- if (MethodologySelection == Methodology.VisibleState) {
- OwnershipModelEncoding = OwnershipModelOption.Trivial;
- }
-
- if (UseArrayTheory) {
- Monomorphize = true;
- }
-
- if (LazyInlining > 0) {
- TypeEncodingMethod = TypeEncoding.Monomorphic;
- UseArrayTheory = true;
- UseAbstractInterpretation = false;
- }
-
- if (StratifiedInlining > 0) {
- TypeEncodingMethod = TypeEncoding.Monomorphic;
- UseArrayTheory = true;
- UseAbstractInterpretation = false;
- }
- }
-
-
-
- public bool UserWantsMethodLogging (string! methodFullName)
- {
- if (methodToLog == null) { return false; }
- return methodToLog == "*" || methodFullName.IndexOf(methodToLog) >= 0;
- }
-
- public bool UserWantsToBreak (string! methodFullName)
- {
- if (methodToBreakOn == null) { return false; }
- return methodFullName.IndexOf(methodToBreakOn) >= 0;
- }
-
- public bool UserWantsToCheckRoutine(string! methodFullname)
- {
- if (procsToCheck == null) {
- // no preference
- return true;
- }
- return exists{string s in procsToCheck; 0 <= methodFullname.IndexOf(s)};
- }
-
- public bool UserWantsToTranslateRoutine(Cci.Method! method, string! methodFullname) {
- return UserWantsToTranslateRoutineInclude(method, methodFullname) &&
- !exists{string s in methodsToTranslateExclude; 0 <= methodFullname.IndexOf(s)};
- }
-
- public bool UserWantsToTranslateRoutineInclude(Cci.Method! method, string! methodFullname)
- {
- if (methodsToTranslateSubstring == null &&
- methodsToTranslateClass == null &&
- methodsToTranslateClassQualified == null &&
- methodsToTranslateFile == null &&
- methodsToTranslateMethod == null &&
- methodsToTranslateMethodQualified == null) {
- // no preference
- return true;
- }
- if (methodsToTranslateSubstring != null) {
- if (exists{string s in methodsToTranslateSubstring; 0 <= methodFullname.IndexOf(s)}) {
- return true;
- }
- }
- if (methodsToTranslateMethod != null) {
- string methodName = method.Name.Name;
- assert methodsToTranslateMethod != null;
- if (methodsToTranslateMethod.Contains(methodName)) {
- return true;
- }
- }
- if (methodsToTranslateMethodQualified != null && method.DeclaringType != null) {
- string methodName = method.DeclaringType.Name.Name + "." + method.Name.Name;
- assert methodsToTranslateMethodQualified != null;
- if (methodsToTranslateMethodQualified.Contains(methodName)) {
- return true;
- }
- }
- if (method.DeclaringType != null) {
- if (methodsToTranslateClass != null) {
- string className = method.DeclaringType.Name.Name;
- if (methodsToTranslateClass.Contains(className)) {
- return true;
- }
- }
- if (methodsToTranslateClassQualified != null) {
- string className = method.DeclaringType.FullName;
- if (className != null) {
- className = className.Replace('+', '.');
- if (methodsToTranslateClassQualified.Contains(className)) {
- return true;
- }
- }
- }
- }
- if (methodsToTranslateFile != null) {
- string methodFilename = GetSourceDocument(method);
- if (methodFilename != null) {
- string path = methodFilename;
- if (path != null) {
- string filename = Path.GetFileName(path);
- if (methodsToTranslateFile.Contains(filename)) {
- return true;
- }
- }
- }
- }
- // the method is not among the desired routines
- return false;
- }
-
- /// <summary>
- /// Returns the file containing "method". Returns null f that information is not available.
- /// </summary>
- static string GetSourceDocument(Cci.Method! method) {
- // Start by looking for a source context in the method itself. However, if the program
- // was read from a binary, then there is no source location for the method. If so, there
- // some other ways we might find a source location.
- if (method.SourceContext.Document != null) {
- return method.SourceContext.Document.Name;
- }
- // Try to find a source location in the method's contract
- if (method.Contract != null) {
- if (method.Contract.Requires != null) {
- foreach (Cci.Requires c in method.Contract.Requires) {
- if (c != null && c.SourceContext.Document != null) {
- return c.SourceContext.Document.Name;
- }
- }
- }
- if (method.Contract.Modifies != null) {
- foreach (Cci.Expression c in method.Contract.Modifies) {
- if (c != null && c.SourceContext.Document != null) {
- return c.SourceContext.Document.Name;
- }
- }
- }
- if (method.Contract.Ensures != null) {
- foreach (Cci.Ensures c in method.Contract.Ensures) {
- if (c != null && c.SourceContext.Document != null) {
- return c.SourceContext.Document.Name;
- }
- }
- }
- }
- // As a last attempt, look for a source location among the statements
- if (method.Body != null) {
- return GetSourceDocumentFromStatements(method.Body.Statements);
- }
- return null; // no source location found
- }
-
- [Pure] static string GetSourceDocumentFromStatements(Cci.StatementList list) {
- if (list != null) {
- foreach (Cci.Statement c in list) {
- if (c != null && c.SourceContext.Document != null) {
- return c.SourceContext.Document.Name;
- }
- if (c is Cci.Block) {
- Cci.Block b = (Cci.Block)c;
- string n = GetSourceDocumentFromStatements(b.Statements);
- if (n != null) {
- return n;
- }
- }
- }
- }
- return null;
- }
-
- class CommandLineParseState
- {
- public string s;
- public bool hasColonArgument;
- public readonly string[]! args;
- public int i;
- public int nextIndex;
- public bool encounteredErrors;
-
- invariant 0 <= i && i <= args.Length;
- invariant 0 <= nextIndex && nextIndex <= args.Length;
-
- public CommandLineParseState(string[]! args)
- requires forall{int i in (0:args.Length); args[i] != null};
- ensures this.args == args;
- {
- this.s = null; // set later by client
- this.hasColonArgument = false; // set later by client
- this.args = args;
- this.i = 0;
- this.nextIndex = 0; // set later by client
- this.encounteredErrors = false;
- }
-
- public bool CheckBooleanFlag(string! flagName, ref bool flag, bool valueWhenPresent)
- modifies nextIndex, encounteredErrors, Console.Error.*;
- {
- bool flagPresent = false;
-
- if ((s == "/"+flagName || s == "-"+flagName) && ConfirmArgumentCount(0))
- {
- flag = valueWhenPresent;
- flagPresent = true;
- }
- return flagPresent;
- }
-
- public bool CheckBooleanFlag(string! flagName, ref bool flag)
- modifies nextIndex, encounteredErrors, Console.Error.*;
- {
- return CheckBooleanFlag(flagName, ref flag, true);
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative integer, then set "arg" to that number and return "true".
- /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref int arg)
- modifies nextIndex, encounteredErrors, Console.Error.*;
- {
- if (this.ConfirmArgumentCount(1))
- {
- try {
- assume args[i] != null;
- assert args[i] is string; // needed to prove args[i].IsPeerConsistent
- int d = Convert.ToInt32(this.args[this.i]);
- if (0 <= d) {
- arg = d;
- return true;
- }
- } catch (System.FormatException) {
- } catch (System.OverflowException) {
- }
- } else {
- return false;
- }
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative integer less than "limit",
- /// then set "arg" to that number and return "true".
- /// Otherwise, emit error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref int arg, int limit)
- requires this.i < args.Length;
- modifies nextIndex, encounteredErrors, Console.Error.*;
- {
- int a = arg;
- if (!GetNumericArgument(ref a)) {
- return false;
- } else if (a < limit) {
- arg = a;
- return true;
- } else {
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
- }
-
- /// <summary>
- /// If there is one argument and it is a non-negative real, then set "arg" to that number and return "true".
- /// Otherwise, emit an error message, leave "arg" unchanged, and return "false".
- /// </summary>
- public bool GetNumericArgument(ref double arg)
- modifies nextIndex, encounteredErrors, Console.Error.*;
- {
- if (this.ConfirmArgumentCount(1))
- {
- try {
- assume args[i] != null;
- assert args[i] is string; // needed to prove args[i].IsPeerConsistent
- double d = Convert.ToDouble(this.args[this.i]);
- if (0 <= d) {
- arg = d;
- return true;
- }
- } catch (System.FormatException) {
- } catch (System.OverflowException) {
- }
- } else {
- return false;
- }
- Error("Invalid argument \"{0}\" to option {1}", args[this.i], this.s);
- return false;
- }
-
- public bool ConfirmArgumentCount(int argCount)
- requires 0 <= argCount;
- modifies nextIndex, encounteredErrors, Console.Error.*;
- ensures result == ( !(hasColonArgument && argCount != 1) && !(args.Length < i + argCount) );
- {
- if (hasColonArgument && argCount != 1)
- {
- Error("\"{0}\" cannot take a colon argument", s);
- nextIndex = args.Length;
- return false;
- }
- else if (args.Length < i + argCount)
- {
- Error("\"{0}\" expects {1} argument{2}", s, argCount.ToString(), (string)(argCount == 1 ? "" : "s"));
- nextIndex = args.Length;
- return false;
- }
- else
- {
- nextIndex = i + argCount;
- return true;
- }
- }
-
- public void Error(string! message, params string[]! args)
- modifies encounteredErrors, Console.Error.*;
- {
- Console.Error.WriteLine("Boogie: Error: " + String.Format(message, args));
- encounteredErrors = true;
- }
- }
-
- public virtual StringCollection ParseNamedArgumentList(string argList){
- if (argList == null || argList.Length == 0) return null;
- StringCollection result = new StringCollection();
- int i = 0;
- for (int n = argList.Length; i < n;)
- invariant 0 <= i;
- {
- int separatorIndex = this.GetArgumentSeparatorIndex(argList, i);
- if (separatorIndex > i){
- result.Add(argList.Substring(i, separatorIndex-i));
- i = separatorIndex+1;
- continue;
- }
- result.Add(argList.Substring(i));
- break;
- }
- return result;
- }
- public int GetArgumentSeparatorIndex(string! argList, int startIndex)
- requires 0 <= startIndex && startIndex <= argList.Length;
- ensures result < argList.Length;
- {
- int commaIndex = argList.IndexOf(",", startIndex);
- int semicolonIndex = argList.IndexOf(";", startIndex);
- if (commaIndex == -1) return semicolonIndex;
- if (semicolonIndex == -1) return commaIndex;
- if (commaIndex < semicolonIndex) return commaIndex;
- return semicolonIndex;
- }
-
- public static void AttributeUsage()
- {
- Console.WriteLine(
-@"Boogie: The following attributes are supported by this implementation.
-
- ---- On axioms -------------------------------------------------------------
-
- {:inline true}
- Works on axiom of the form:
- (forall VARS :: f(VARS) = expr(VARS))
- Makes Boogie replace f(VARS) with expr(VARS) everywhere just before
- doing VC generation.
-
- {:ignore ""p,q..""}
- Exclude the axiom when generating VC for a prover supporting any
- of the features 'p', 'q', ...
- All the provers support the feature 'all'.
- Simplify supports 'simplify' and 'simplifyLike'.
- Z3 supports 'z3', 'simplifyLike' and either 'bvInt' (if the /bv:i
- option is passed) or 'bvDefSem' (for /bv:z).
-
- ---- On implementations and procedures -------------------------------------
-
- {:inline N}
- Inline given procedure (can be also used on implementation).
- N should be a non-negative number and represents the inlining depth.
- With /inline:assume call is replaced with ""assume false"" once inlining depth is reached.
- With /inline:assert call is replaced with ""assert false"" once inlining depth is reached.
- With /inline:spec call is left as is once inlining depth is reached.
- With the above three options, methods with the attribute {:inline N} are not verified.
- With /inline:none the entire attribute is ignored.
-
- {:verify false}
- Skip verification of an implementation.
-
- {:forceBvZ3Native true}
- Verify the given implementation with the native Z3 bitvector
- handling. Only works if /bv:i (or /bv:z, but then it does not do
- anything) is given on the command line.
-
- {:forceBvInt true}
- Use int translation for the given implementation. Only work with
- /bv:z (or /bv:i).
-
- {:vcs_max_cost N}
- {:vcs_max_splits N}
- {:vcs_max_keep_going_splits N}
- Per-implementation versions of
- /vcsMaxCost, /vcsMaxSplits and /vcsMaxKeepGoingSplits.
-
- ---- On functions ----------------------------------------------------------
-
- {:bvbuiltin ""spec""}
- Z3 specific, used only with /bv:z.
-
- {:bvint ""fn""}
- With /bv:i rewrite the function to function symbol 'fn', except if
- the 'fn' is 'id', in which case just strip the function altogether.
-
- {:never_pattern true}
- Terms starting with this function symbol will never be
- automatically selected as patterns. It does not prevent them
- from being used inside the triggers, and does not affect explicit
- trigger annotations. Internally it works by adding {:nopats ...}
- annotations to quantifiers.
-
- ---- On variables ----------------------------------------------------------
-
- {:existential true}
- Marks a global Boolean variable as existentially quantified. If
- used in combination with option /contractInfer Boogie will check
- whether there exists a Boolean assignment to the existentials
- that makes all verification conditions valid. Without option
- /contractInfer the attribute is ignored.
-
- ---- On assert statements --------------------------------------------------
-
- {:subsumption n}
- Overrides the /subsumption command-line setting for this assertion.
-
- ---- The end ---------------------------------------------------------------
-");
- }
-
- private static bool printedHelp = false;
-
- public static void Usage()
- {
- // Ensure that we only print the help message once,
- // no matter how many enabling conditions for printing
- // help were triggered.
- if (printedHelp) { return; }
- printedHelp = true;
-
- Console.WriteLine(@"Boogie: usage: Boogie [ option ... ] [ filename ... ]
- where <option> is one of
-
- ---- General options -------------------------------------------------------
-
- /help : this message
- /attrHelp : print a message about declaration attributes supported by
- this implementation
- /nologo : suppress printing of version number, copyright message
- /env:<n> : print command line arguments
- 0 - never, 1 (default) - during BPL print and prover log,
- 2 - like 1 and also to standard output
- /wait : await Enter from keyboard before terminating program
- /xml:<file> : also produce output in XML format to <file>
-
- ---- Spec# options ---------------------------------------------------------
-
- If any of the following switches is included, only those methods specified
- by some switch are translated into Boogie. Furthermore, a method is
- not translated if a [Verify(false)] attribute applies to it or if the
- flag /trExclude applies (see below).
- /translate:<str> : include method if its full name contains substring <str>
- /trMethod:<method> : include method if its name is <method>
- Format: Name or Class.Name
- /trClass:<class> : include method if the enclosing class is <class>
- Format: Name or Qualification.Name
- /trFile:<filename> : include method if it is contained in file <filename>
- Format: Filename.ssc
-
- /trExclude:<str> : exclude method it its full name contains substring <str>
-
- /c[ontracts]:<file>
- : apply the contracts from <file> to
- the referenced assemblies of the input assembly.
- Note: the contracts for Xyz must be in Xyz.Contracts
- /methodology:<m> : selects the specification and verification methodology
- b = boogie (default)
- vs = visible-state
- /level:<n> : 0 - reduced checks,
- 1 - no modifies checking, 2 - full (default)
- /useUncheckedContracts : generate purity axioms even when the postconditions
- could not be checked to be sound (this option only for
- experts and dare devils)
- /modifiesDefault:<n> :
- 0 - just what is declared
- 1 - what is declared plus E.snapshot for every top-level
- E.f, E.*, E.**, E[i], or E[*] in the modifies clause
- 2 - (1) but also for nested E's
- 3 - (1) plus this.snapshot
- 4 - (2) plus this.snapshot
- 5 - (default) (1) plus p.* for receiver parameter p not
- occurring at the top-level of modifies clause as
- p.f, p.*, p.**, p[i], p[*], or p.0
- 6 - (5) but for every parameter p
- /modifiesOnLoop:<n> : 0 - never, 1 - assume only (default),
- 2 - assume and check (default with
- /localModifiesChecks:0)
- /localModifiesChecks: 0 - check modifies-clause as post-condition of a
- procedure
- 1 - check violations of modifies-clause at each
- assignment and method call (default)
- /loopUnroll:<n> : unroll loops, following up to n back edges (and then some)
- /noVerifyByDefault : change the default to [Verify(false)]
- /orderStrength:<n> : 0 (default) - only few properties of subtyping
- axiomatized,
- 1 - full strength
- /summationStrength:<n> : 0 - less applicable triggers in the axioms
- 1 - (default) default set of axioms for summation-
- like quantifiers;
- /arithDistributionAxioms : emit +/* distribution axioms
- /inductiveMinMax:<n> : 0 (default) - extreme axioms for min/max;
- 1 - inductive axioms for min/max;
- 2 - both extreme and inductive axioms for min/max
- 3,4,5 - like 0,1,2 but adding the plus-over-min/max
- distribution axiom
- Modes 1,2,4,5 imply /reflectAdd.
- /fcoStrength:<n> : adjusts the amount of information encoded about 'first
- consistent owners'
- 0 - no FCO axiom, 1 - cheaper but weaker FCO axiom,
- 2 - pure-method FCO axiom,
- 3, 4, 5 (default) - like 0,1,2 plus more specific
- FCO information on pure-method return
- /ownerModelEncoding:<enc> : s = standard (default)
- e = experimental
- t = trivial (implied by /methodology:vs)
- /printModel:<n> : 0 (default) - do not print Z3's error model
- 1 - print Z3's error model (default with /cev)
- 2 - print Z3's error model plus reverse mappings
- 4 - print Z3's error model in a more human readable way
- /printModelToFile:<file> : print model to <file> instead of console
- /cev:<file> Print Z3's error model to <file> and include error message
- /enhancedErrorMessages:<n> : 0 (default) - no enhanced error messages
- 1 - Z3 error model enhanced error messages
-
- ---- Dafny options ---------------------------------------------------------
-
- Multiple .dfy files supplied on the command line are concatenated into one
- Dafny program.
-
- /dprint:<file> : print Dafny program after parsing it
- (use - as <file> to print to console)
- /compile:<n> : 0 - do not compile Dafny program
- 1 (default) - upon successful verification of the Dafny
- program, compile Dafny program to C# program out.cs
-
- ---- Boogie options --------------------------------------------------------
-
- Multiple .bpl files supplied on the command line are concatenated into one
- Boogie program.
-
- /proc:<p> : limits which procedures to check
- /noResolve : parse only
- /noTypecheck : parse and resolve only
-
- /print:<file> : print Boogie program after parsing it
- (use - as <file> to print to console)
- /printWithUniqueIds : print augmented information that uniquely
- identifies variables
- /printUnstructured : with /print option, desugars all structured statements
- /printDesugared : with /print option, desugars calls
-
- /overlookTypeErrors : skip any implementation with resolution or type
- checking errors
-
- ---- Inference options -----------------------------------------------------
-
- /infer:<flags> : use abstract interpretation to infer invariants
- The default is /infer:i" // This is not 100% true, as the /infer ALWAYS creates
- // a multilattice, whereas if nothing is specified then
- // intervals are isntantiated WITHOUT being embedded in
- // a multilattice
- + @"
- <flags> are as follows (missing <flags> means all)
- i = intervals
- c = constant propagation
- d = dynamic type
- n = nullness
- p = polyhedra for linear inequalities
- s = debug statistics
- 0..9 = number of iterations before applying a widen (default=0)
- /noinfer : turn off the default inference, and overrides the /infer
- switch on its left
- /checkInfer : instrument inferred invariants as asserts to be checked by
- theorem prover
- /interprocInfer : perform interprocedural inference (deprecated, not
- supported)
- /contractInfer : perform procedure contract inference
- /logInfer : print debug output during inference
- /instrumentInfer : h - instrument inferred invariants only at beginning of
- loop headers (default)
- e - instrument inferred invariants at beginning and end
- of every block
- /printInstrumented : print Boogie program after it has been
- instrumented with invariants
- /Houdini[:<flags>] : perform procedure Houdini
- c = continue when an error found
- i = use incremental queries
- /dbgRefuted : log refuted Houdini candidates to XmlSink
-
- ---- Debugging and general tracing options ---------------------------------
-
- /trace : blurt out various debug trace information
- /traceTimes : output timing information at certain points in the pipeline
- /log[:method] : Print debug output during translation
-
- /break[:method] : break into debugger
-
- ---- Verification-condition generation options -----------------------------
-
- /liveVariableAnalysis:<c> : 0 = do not perform live variable analysis
- 1 = perform live variable analysis (default)
- 2 = perform interprocedural live variable analysis
- /noVerify : skip VC generation and invocation of the theorem prover
- /removeEmptyBlocks:<c> : 0 - do not remove empty blocks during VC generation
- 1 - remove empty blocks (default)
- /coalesceBlocks:<c> : 0 = do not coalesce blocks
- 1 = coalesce blocks (default)
- /vc:<variety> : n = nested block (default for non-/prover:z3),
- m = nested block reach,
- b = flat block, r = flat block reach,
- s = structured, l = local, d = dag (default with /prover:z3)
- doomed = doomed
- /DoomDebug : Use Doom detection to debug (experimental)
- /traceverify : print debug output during verification condition generation
- /subsumption:<c> : apply subsumption to asserted conditions:
- 0 - never, 1 - not for quantifiers, 2 (default) - always
- /alwaysAssumeFreeLoopInvariants : usually, a free loop invariant (or assume
- statement in that position) is ignored in checking contexts
- (like other free things); this option includes these free
- loop invariants as assumes in both contexts
- /bv:<bv> : bitvector handling
- n = none
- z = native Z3 bitvectors (default)
- i = unsoundly translate bitvectors to integers
- /inline:<i> : use inlining strategy <i> for procedures with the :inline
- attribute, see /attrHelp for details:
- none
- assume (default)
- assert
- spec
- /printInlined : print the implementation after inlining calls to
- procedures with the :inline attribute (works with /inline)
- /smoke : Soundness Smoke Test: try to stick assert false; in some
- places in the BPL and see if we can still prove it
- /smokeTimeout:<n> : Timeout, in seconds, for a single theorem prover
- invocation during smoke test, defaults to 10.
- /causalImplies : Translate Boogie's A ==> B into prover's A ==> A && B.
- /typeEncoding:<m> : how to encode types when sending VC to theorem prover
- n = none (unsound)
- p = predicates (default)
- a = arguments
- /monomorphize Do not abstract map types in the encoding (this is an
- experimental feature that will not do the right thing if
- the program uses polymorphism)
- /reflectAdd In the VC, generate an auxiliary symbol, elsewhere defined
- to be +, instead of +.
-
- ---- Verification-condition splitting --------------------------------------
-
- /vcsMaxCost:<f> : VC will not be split unless the cost of a VC exceeds this
- number, defaults to 2000.0. This does NOT apply in the
- keep-going mode after first round of splitting.
- /vcsMaxSplits:<n> : Maximal number of VC generated per method. In keep
- going mode only applies to the first round.
- Defaults to 1.
- /vcsMaxKeepGoingSplits:<n> : If set to more than 1, activates the keep
- going mode, where after the first round of splitting,
- VCs that timed out are split into <n> pieces and retried
- until we succeed proving them, or there is only one
- assertion on a single path and it timeouts (in which
- case error is reported for that assertion).
- Defaults to 1.
- /vcsKeepGoingTimeout:<n> : Timeout in seconds for a single theorem prover
- invocation in keep going mode, except for the final
- single-assertion case. Defaults to 1s.
- /vcsFinalAssertTimeout:<n> : Timeout in seconds for the single last
- assertion in the keep going mode. Defaults to 30s.
- /vcsPathJoinMult:<f> : If more than one path join at a block, by how much
- multiply the number of paths in that block, to accomodate
- for the fact that the prover will learn something on one
- paths, before proceeding to another. Defaults to 0.8.
- /vcsPathCostMult:<f1>
- /vcsAssumeMult:<f2> : The cost of a block is
- (<assert-cost> + <f2>*<assume-cost>)*(1.0 + <f1>*<entering-paths>)
- <f1> defaults to 1.0, <f2> defaults to 0.01.
- The cost of a single assertion or assumption is
- currently always 1.0.
- /vcsPathSplitMult:<f> : If the best path split of a VC of cost A is into
- VCs of cost B and C, then the split is applied if
- A >= <f>*(B+C), otherwise assertion splitting will be
- applied. Defaults to 0.5 (always do path splitting if
- possible), set to more to do less path splitting
- and more assertion splitting.
- /vcsDumpSplits For split #n dump split.n.dot and split.n.bpl.
- Warning: Affects error reporting.
- /vcsCores:<n> : Try to verify <n> VCs at once. Defaults to 1.
-
- ---- Prover options --------------------------------------------------------
-
- /errorLimit:<num> : Limit the number of errors produced for each procedure
- (default is 5, some provers may support only 1)
- /timeLimit:<num> : Limit the number of seconds spent trying to verify
- each procedure
- /errorTrace:<n> : 0 - no Trace labels in the error output,
- 1 (default) - include useful Trace labels in error output,
- 2 - include all Trace labels in the error output
- /vcBrackets:<b> : bracket odd-charactered identifier names with |'s. <b> is:
- 0 - no (default with /prover:Z3),
- 1 - yes (default with /prover:Simplify)
- /prover:<tp> : use theorem prover <tp>, where <tp> is either the name of
- a DLL containing the prover interface located in the
- Boogie directory, or a full path to a DLL containing such
- an interface. The standard interfaces shipped include:
- Z3 (default)
- Simplify
- SMTLib (only writes to a file)
- ContractInference (uses Z3)
- Z3api (Z3 using Managed .NET API)
- /proverOpt:KEY[=VALUE] : Provide a prover-specific option.
- /proverLog:<file> : Log input for the theorem prover. Like filenames
- supplied as arguments to other options, <file> can use the
- following macros:
- @TIME@' expands to the current time
- @PREFIX@ expands to the concatenation of strings given
- by /logPrefix options
- @FILE@ expands to the last filename specified on the
- command line
- In addition, /proverLog can also use the macro '@PROC@',
- which causes there to be one prover log file per
- verification condition, and the macro then expands to the
- name of the procedure that the verification condition is
- for.
- /logPrefix:<str> : Defines the expansion of the macro '@PREFIX@', which can
- be used in various filenames specified by other options.
- /proverLogAppend : Append (not overwrite) the specified prover log file
- /proverWarnings : 0 (default) - don't print, 1 - print to stdout,
- 2 - print to stderr
- /proverMemoryLimit:<num> : Limit on the virtual memory for prover before
- restart in MB (default:100MB)
- /restartProver : Restart the prover after each query
- /proverShutdownLimit<num> : Time between closing the stream to the prover and
- killing the prover process (default: 0s)
- /platform:<ptype>,<location>
- : ptype = v11,v2,cli1
- : location = platform libraries directory
-
- Simplify specific options:
- /simplifyMatchDepth:<num> : Set Simplify prover's matching depth limit
-
- Z3 specific options:
- /z3opt:<arg> : specify additional Z3 options
- /z3multipleErrors : report multiple counterexamples for each error
- /useArrayTheory : use Z3's native theory (as opposed to axioms). Currently
- implies /monomorphize.
-
- SMT-Lib specific options:
- /smtOutput:<file> : Path and basename to which the prover output is
- written (default: boogie-vc-@PROC@.smt). The same
- macros as in /proverLog can be used.
-
- /z3types : generate multi-sorted VC that make use of Z3 types
- /z3lets:<n> : 0 - no LETs, 1 - only LET TERM, 2 - only LET FORMULA,
- 3 - (default) any
-");
- }
- }
-}
diff --git a/Source/Core/Core.sscproj b/Source/Core/Core.sscproj
deleted file mode 100644
index 4929e1c7..00000000
--- a/Source/Core/Core.sscproj
+++ /dev/null
@@ -1,232 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<VisualStudioProject>
- <XEN ProjectType="Local"
- SchemaVersion="1.0"
- Name="Core"
- ProjectGuid="47bc34f1-a173-40be-84c2-9332b4418387"
- >
- <Build>
- <Settings ApplicationIcon=""
- AssemblyName="Core"
- OutputType="Library"
- RootNamespace="Core"
- StartupObject=""
- TargetPlatform="v2"
- TargetPlatformLocation=""
- ShadowedAssembly=""
- StandardLibraryLocation=""
- >
- <Config Name="Debug"
- AllowUnsafeBlocks="False"
- BaseAddress="285212672"
- CheckForOverflowUnderflow="False"
- ConfigurationOverrideFile=""
- DefineConstants="DEBUG;TRACE;WHIDBEY"
- DocumentationFile=""
- DebugSymbols="True"
- FileAlignment="4096"
- IncrementalBuild="True"
- Optimize="False"
- OutputPath="bin\Debug"
- RegisterForComInterop="False"
- RemoveIntegerChecks="false"
- TreatWarningsAsErrors="False"
- WarningLevel="4"
- RunProgramVerifier="False"
- ProgramVerifierCommandLineOptions=""
- ReferenceTypesAreNonNullByDefault="False"
- RunProgramVerifierWhileEditing="False"
- AllowPointersToManagedStructures="False"
- CheckContractAdmissibility="True"
- CheckPurity="False"
- DisableAssumeChecks="False"
- DisableDefensiveChecks="False"
- DisableGuardedClassesChecks="False"
- DisableInternalChecks="False"
- DisableInternalContractsMetadata="False"
- DisablePublicContractsMetadata="False"
- DebugMode="Project"
- StartProgram=""
- StartURL=""
- StartPage=""
- UseIE="False"
- EnableRemoteDebugging="False"
- RemoteDebugMachine=""
- />
- <Config Name="Release"
- AllowUnsafeBlocks="false"
- BaseAddress="285212672"
- CheckForOverflowUnderflow="false"
- ConfigurationOverrideFile=""
- DefineConstants="TRACE;WHIDBEY"
- DocumentationFile=""
- DebugSymbols="false"
- FileAlignment="4096"
- IncrementalBuild="false"
- Optimize="true"
- OutputPath="bin\release"
- RegisterForComInterop="false"
- RemoveIntegerChecks="false"
- TreatWarningsAsErrors="True"
- WarningLevel="4"
- />
- </Settings>
- <References>
- <Reference Name="Mscorlib.Contracts"
- AssemblyName="Mscorlib.Contracts"
- Private="false"
- HintPath="../../Binaries/Mscorlib.Contracts.dll"
- />
- <Reference Name="System"
- AssemblyName="System"
- Private="false"
- />
- <Reference Name="System.Compiler.Framework"
- AssemblyName="System.Compiler.Framework"
- Private="true"
- HintPath="../../Binaries/System.Compiler.Framework.dll"
- />
- <Reference Name="AIFramework"
- Project="{24B55172-AD8B-47D1-8952-5A95CFDB9B31}"
- Private="true"
- />
- <Reference Name="System.Compiler"
- AssemblyName="System.Compiler"
- Private="true"
- HintPath="../../Binaries/System.Compiler.dll"
- />
- <Reference Name="System.Compiler.Contracts"
- AssemblyName="System.Compiler.Contracts"
- Private="false"
- HintPath="../../Binaries/System.Compiler.Contracts.dll"
- />
- <Reference Name="Graph"
- Project="{4C28FB90-630E-4B55-A937-11A011B79765}"
- Private="true"
- />
- <Reference Name="System.XML"
- AssemblyName="System.XML"
- Private="false"
- />
- <Reference Name="System.Xml.Contracts"
- AssemblyName="System.Xml.Contracts"
- Private="false"
- HintPath="../../Binaries/System.Xml.Contracts.dll"
- />
- <Reference Name="FSharp.Core"
- AssemblyName="FSharp.Core"
- Private="false"
- HintPath="../../Binaries/FSharp.Core.dll"
- />
- <Reference Name="Basetypes"
- Project="{0C692837-77EC-415F-BF04-395E3ED06E9A}"
- Private="true"
- />
- </References>
- </Build>
- <Files>
- <Include>
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Absy.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="..\version.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Duplicator.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="OOLongUtil.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="PureCollections.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="ResolutionContext.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="StandardVisitor.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Util.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="CommandLineOptions.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="scanner.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="parser.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="ParserHelper.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="GraphAlgorithms.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AbsyType.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AbsyCmd.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AbsyExpr.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AbsyQuant.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Xml.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="Inline.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="LambdaHelper.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="LoopUnroll.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="VCExp.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="TypeAmbiguitySeeker.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="AssemblyInfo.ssc"
- />
- <File BuildAction="Compile"
- SubType="Code"
- RelPath="DeadVarElim.ssc"
- />
- </Include>
- </Files>
- </XEN>
-</VisualStudioProject>
diff --git a/Source/Core/DeadVarElim.ssc b/Source/Core/DeadVarElim.ssc
deleted file mode 100644
index 1a5d0b30..00000000
--- a/Source/Core/DeadVarElim.ssc
+++ /dev/null
@@ -1,1234 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Graphing;
-using PureCollections;
-using Microsoft.Contracts;
-
-namespace Microsoft.Boogie
-{
- public class UnusedVarEliminator : VariableCollector {
- public static void Eliminate(Program! program) {
- UnusedVarEliminator elim = new UnusedVarEliminator();
- elim.Visit(program);
- }
-
- private UnusedVarEliminator() {
- base();
- }
-
- public override Implementation! VisitImplementation(Implementation! node) {
- //Console.WriteLine("Procedure {0}", node.Name);
- Implementation! impl = base.VisitImplementation(node);
- //Console.WriteLine("Old number of local variables = {0}", impl.LocVars.Length);
- Microsoft.Boogie.VariableSeq! vars = new Microsoft.Boogie.VariableSeq();
- foreach (Variable! var in impl.LocVars) {
- if (usedVars.Contains(var))
- vars.Add(var);
- }
- impl.LocVars = vars;
- //Console.WriteLine("New number of local variables = {0}", impl.LocVars.Length);
- //Console.WriteLine("---------------------------------");
- usedVars.Clear();
- return impl;
- }
- }
-
- public class ModSetCollector : StandardVisitor {
- static Procedure proc;
- static Dictionary<Procedure!, Set<Variable!>!>! modSets;
- static bool moreProcessingRequired;
-
- public static void DoModSetAnalysis(Program! program) {
- int procCount = 0;
- foreach (Declaration! decl in program.TopLevelDeclarations) {
- if (decl is Procedure)
- procCount++;
- }
- Console.WriteLine("Number of procedures = {0}", procCount);
-
- modSets = new Dictionary<Procedure!, Set<Variable!>!>();
-
- Set<Procedure!> implementedProcs = new Set<Procedure!> ();
- foreach (Declaration! decl in program.TopLevelDeclarations) {
- if (decl is Implementation) {
- Implementation impl = (Implementation) decl;
- if (impl.Proc != null)
- implementedProcs.Add(impl.Proc);
- }
- }
- foreach (Declaration! decl in program.TopLevelDeclarations) {
- if (decl is Procedure && !implementedProcs.Contains((Procedure!) decl)) {
- proc = (Procedure) decl;
- foreach (IdentifierExpr! expr in proc.Modifies) {
- ProcessVariable(expr.Decl);
- }
- proc = null;
- }
- }
-
- moreProcessingRequired = true;
- while (moreProcessingRequired) {
- moreProcessingRequired = false;
- ModSetCollector modSetCollector = new ModSetCollector();
- modSetCollector.Visit(program);
- }
-
- procCount = 0;
- foreach (Procedure! x in modSets.Keys) {
- procCount++;
- Console.Write("{0} : ", x.Name);
- foreach (Variable! y in modSets[x]) {
- Console.Write("{0}, ", y.Name);
- }
- Console.WriteLine("");
- }
- Console.WriteLine("Number of procedures with nonempty modsets = {0}", procCount);
- }
-
- public override Implementation! VisitImplementation(Implementation! node) {
- proc = node.Proc;
- Implementation! ret = base.VisitImplementation(node);
- proc = null;
-
- return ret;
- }
- public override Cmd! VisitAssignCmd(AssignCmd! assignCmd) {
- Cmd ret = base.VisitAssignCmd(assignCmd);
- foreach (AssignLhs! lhs in assignCmd.Lhss) {
- ProcessVariable(lhs.DeepAssignedVariable);
- }
- return ret;
- }
- public override Cmd! VisitHavocCmd(HavocCmd! havocCmd) {
- Cmd ret = base.VisitHavocCmd(havocCmd);
- foreach (IdentifierExpr! expr in havocCmd.Vars) {
- ProcessVariable(expr.Decl);
- }
- return ret;
- }
- public override Cmd! VisitCallCmd(CallCmd! callCmd) {
- Cmd ret = base.VisitCallCmd(callCmd);
- Procedure callee = callCmd.Proc;
- if (callee != null && modSets.ContainsKey(callee)) {
- foreach (Variable var in modSets[callee]) {
- ProcessVariable(var);
- }
- }
- return ret;
- }
- private static void ProcessVariable(Variable var) {
- Procedure! localProc = (!)proc;
- if (var == null) return;
- if (!(var is GlobalVariable)) return;
- if (var.Name == "alloc") return;
- if (!modSets.ContainsKey(localProc)) {
- modSets[localProc] = new Set<Variable!> ();
- }
- if (modSets[localProc].Contains(var)) return;
- moreProcessingRequired = true;
- modSets[localProc].Add(var);
- }
- }
-
- public class VariableCollector : StandardVisitor {
- public System.Collections.Generic.Set<Variable!>! usedVars;
- public System.Collections.Generic.Set<Variable!>! oldVarsUsed;
- int insideOldExpr;
-
- public VariableCollector() {
- usedVars = new System.Collections.Generic.Set<Variable!>();
- oldVarsUsed = new System.Collections.Generic.Set<Variable!>();
- insideOldExpr = 0;
- }
-
- public override Expr! VisitOldExpr(OldExpr! node)
- {
- insideOldExpr ++;
- node.Expr = this.VisitExpr(node.Expr);
- insideOldExpr --;
- return node;
- }
-
- public override Expr! VisitIdentifierExpr(IdentifierExpr! node) {
- if (node.Decl != null) {
- usedVars.Add(node.Decl);
- if(insideOldExpr > 0) {
- oldVarsUsed.Add(node.Decl);
- }
- }
- return node;
- }
- }
-
- public class BlockCoalescer : StandardVisitor {
- public static void CoalesceBlocks(Program! program) {
- BlockCoalescer blockCoalescer = new BlockCoalescer();
- blockCoalescer.Visit(program);
- }
-
- private static Set<Block!>! ComputeMultiPredecessorBlocks(Implementation !impl) {
- Set<Block!> visitedBlocks = new Set<Block!>();
- Set<Block!> multiPredBlocks = new Set<Block!>();
- Stack<Block!> dfsStack = new Stack<Block!>();
- dfsStack.Push(impl.Blocks[0]);
- while (dfsStack.Count > 0) {
- Block! b = dfsStack.Pop();
- if (visitedBlocks.Contains(b)) {
- multiPredBlocks.Add(b);
- continue;
- }
- visitedBlocks.Add(b);
- if (b.TransferCmd == null) continue;
- if (b.TransferCmd is ReturnCmd) continue;
- assert b.TransferCmd is GotoCmd;
- GotoCmd gotoCmd = (GotoCmd) b.TransferCmd;
- if (gotoCmd.labelTargets == null) continue;
- foreach (Block! succ in gotoCmd.labelTargets) {
- dfsStack.Push(succ);
- }
- }
- return multiPredBlocks;
- }
-
- public override Implementation! VisitImplementation(Implementation! impl) {
- //Console.WriteLine("Procedure {0}", impl.Name);
- //Console.WriteLine("Initial number of blocks = {0}", impl.Blocks.Count);
-
- Set<Block!> multiPredBlocks = ComputeMultiPredecessorBlocks(impl);
- Set<Block!> visitedBlocks = new Set<Block!>();
- Set<Block!> removedBlocks = new Set<Block!>();
- Stack<Block!> dfsStack = new Stack<Block!>();
- dfsStack.Push(impl.Blocks[0]);
- while (dfsStack.Count > 0) {
- Block! b = dfsStack.Pop();
- if (visitedBlocks.Contains(b)) continue;
- visitedBlocks.Add(b);
- if (b.TransferCmd == null) continue;
- if (b.TransferCmd is ReturnCmd) continue;
- assert b.TransferCmd is GotoCmd;
- GotoCmd gotoCmd = (GotoCmd) b.TransferCmd;
- if (gotoCmd.labelTargets == null) continue;
- if (gotoCmd.labelTargets.Length == 1) {
- Block! succ = (!)gotoCmd.labelTargets[0];
- if (!multiPredBlocks.Contains(succ)) {
- foreach (Cmd! cmd in succ.Cmds) {
- b.Cmds.Add(cmd);
- }
- b.TransferCmd = succ.TransferCmd;
- if (!b.tok.IsValid && succ.tok.IsValid) {
- b.tok = succ.tok;
- b.Label = succ.Label;
- }
- removedBlocks.Add(succ);
- dfsStack.Push(b);
- visitedBlocks.Remove(b);
- continue;
- }
- }
- foreach (Block! succ in gotoCmd.labelTargets) {
- dfsStack.Push(succ);
- }
- }
-
- List<Block!> newBlocks = new List<Block!>();
- foreach (Block! b in impl.Blocks) {
- if (!removedBlocks.Contains(b)) {
- newBlocks.Add(b);
- }
- }
- impl.Blocks = newBlocks;
-
- // Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count);
- return impl;
- }
- }
-
- public class LiveVariableAnalysis {
- public static void ClearLiveVariables(Implementation! impl) {
- foreach (Block! block in impl.Blocks) {
- block.liveVarsBefore = null;
- }
- }
-
- public static void ComputeLiveVariables(Implementation! impl) {
- Microsoft.Boogie.Helpers.ExtraTraceInformation("Starting live variable analysis");
- Graphing.Graph<Block> dag = new Graph<Block>();
- dag.AddSource((!)impl.Blocks[0]); // there is always at least one node in the graph
- foreach (Block b in impl.Blocks)
- {
- GotoCmd gtc = b.TransferCmd as GotoCmd;
- if (gtc != null)
- {
- assume gtc.labelTargets != null;
- foreach (Block! dest in gtc.labelTargets)
- {
- dag.AddEdge(dest, b);
- }
- }
- }
-
- IEnumerable<Block> sortedNodes = dag.TopologicalSort();
- foreach (Block! block in sortedNodes) {
- Set<Variable!>! liveVarsAfter = new Set<Variable!>();
- if (block.TransferCmd is GotoCmd) {
- GotoCmd gotoCmd = (GotoCmd) block.TransferCmd;
- if (gotoCmd.labelTargets != null) {
- foreach (Block! succ in gotoCmd.labelTargets) {
- assert succ.liveVarsBefore != null;
- liveVarsAfter.AddRange(succ.liveVarsBefore);
- }
- }
- }
-
- CmdSeq cmds = block.Cmds;
- int len = cmds.Length;
- for (int i = len - 1; i >= 0; i--) {
- if(cmds[i] is CallCmd) {
- Procedure! proc = (!)((CallCmd!)cmds[i]).Proc;
- if(InterProcGenKill.HasSummary(proc.Name)) {
- liveVarsAfter =
- InterProcGenKill.PropagateLiveVarsAcrossCall((CallCmd!)cmds[i], liveVarsAfter);
- continue;
- }
- }
- Propagate(cmds[i], liveVarsAfter);
- }
-
- block.liveVarsBefore = liveVarsAfter;
-
- }
- }
-
- // perform in place update of liveSet
- public static void Propagate(Cmd! cmd, Set<Variable!>! liveSet) {
- if (cmd is AssignCmd) {
- AssignCmd! assignCmd = (AssignCmd) cmd;
- // I must first iterate over all the targets and remove the live ones.
- // After the removals are done, I must add the variables referred on
- // the right side of the removed targets
- Set<int> indexSet = new Set<int>();
- int index = 0;
- foreach (AssignLhs! lhs in assignCmd.Lhss) {
- Variable var = lhs.DeepAssignedVariable;
- if (var != null && liveSet.Contains(var)) {
- indexSet.Add(index);
- if (lhs is SimpleAssignLhs) {
- // we should only remove non-map target variables because there is an implicit
- // read of a map variable in an assignment to it
- liveSet.Remove(var);
- }
- }
- index++;
- }
- index = 0;
- foreach (Expr! expr in assignCmd.Rhss) {
- if (indexSet.Contains(index)) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(expr);
- liveSet.AddRange(collector.usedVars);
- AssignLhs lhs = assignCmd.Lhss[index];
- if (lhs is MapAssignLhs) {
- // If the target is a map, then all indices are also read
- MapAssignLhs malhs = (MapAssignLhs) lhs;
- foreach (Expr e in malhs.Indexes) {
- VariableCollector! c = new VariableCollector();
- c.Visit(e);
- liveSet.AddRange(c.usedVars);
- }
- }
- }
- index++;
- }
- } else if (cmd is HavocCmd) {
- HavocCmd! havocCmd = (HavocCmd) cmd;
- foreach (IdentifierExpr! expr in havocCmd.Vars) {
- if (expr.Decl != null) {
- liveSet.Remove(expr.Decl);
- }
- }
- } else if (cmd is PredicateCmd) {
- assert (cmd is AssertCmd || cmd is AssumeCmd);
- PredicateCmd! predicateCmd = (PredicateCmd) cmd;
- if (predicateCmd.Expr is LiteralExpr) {
- LiteralExpr le = (LiteralExpr) predicateCmd.Expr;
- if (le.IsFalse) {
- liveSet.Clear();
- }
- } else {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(predicateCmd.Expr);
- liveSet.AddRange(collector.usedVars);
- }
- } else if (cmd is CommentCmd) {
- // comments are just for debugging and don't affect verification
- } else if (cmd is SugaredCmd) {
- SugaredCmd! sugCmd = (SugaredCmd) cmd;
- Propagate(sugCmd.Desugaring, liveSet);
- } else if (cmd is StateCmd) {
- StateCmd! stCmd = (StateCmd) cmd;
- CmdSeq! cmds = stCmd.Cmds;
- int len = cmds.Length;
- for (int i = len - 1; i >= 0; i--) {
- Propagate(cmds[i], liveSet);
- }
- foreach (Variable! v in stCmd.Locals) {
- liveSet.Remove(v);
- }
- } else {
- assert false;
- }
- }
- }
-
- /*
- // An idempotent semiring interface
- abstract public class Weight {
- abstract public Weight! one();
- abstract public Weight! zero();
- abstract public Weight! extend(Weight! w1, Weight! w2);
- abstract public Weight! combine(Weight! w1, Weight! w2);
- abstract public Weight! isEqual(Weight! w);
- abstract public Weight! projectLocals()
- }
- */
-
- // Weight domain for LiveVariableAnalysis (Gen/Kill)
-
- public class GenKillWeight {
- // lambda S. (S - kill) union gen
- Set<Variable!>! gen;
- Set<Variable!>! kill;
- bool isZero;
-
- public static GenKillWeight! oneWeight = new GenKillWeight(new Set<Variable!>(), new Set<Variable!>());
- public static GenKillWeight! zeroWeight = new GenKillWeight();
-
- // initializes to zero
- public GenKillWeight() {
- this.isZero = true;
- this.gen = new Set<Variable!>();
- this.kill = new Set<Variable!>();
- }
-
- public GenKillWeight(Set<Variable!> gen, Set<Variable!> kill) {
- assert gen != null;
- assert kill != null;
- this.gen = gen;
- this.kill = kill;
- this.isZero = false;
- }
-
- public static GenKillWeight! one() {
- return oneWeight;
- }
-
- public static GenKillWeight! zero() {
- return zeroWeight;
- }
-
- public static GenKillWeight! extend(GenKillWeight! w1, GenKillWeight! w2) {
- if(w1.isZero || w2.isZero) return zero();
-
- return new GenKillWeight(w1.gen.Union(w2.gen.Difference(w1.kill)), w1.kill.Union(w2.kill));
- }
-
- public static GenKillWeight! combine(GenKillWeight! w1, GenKillWeight! w2) {
- if(w1.isZero) return w2;
- if(w2.isZero) return w1;
-
- return new GenKillWeight(w1.gen.Union(w2.gen), w1.kill.Intersection(w2.kill));
- }
-
- public static GenKillWeight! projectLocals(GenKillWeight! w) {
- Set<Variable!> gen = w.gen.FindAll(isGlobal);
- Set<Variable!> kill = w.kill.FindAll(isGlobal);
-
- return new GenKillWeight(gen, kill);
- }
-
- public static bool isEqual(GenKillWeight! w1, GenKillWeight! w2) {
- if(w1.isZero) return w2.isZero;
- if(w2.isZero) return w1.isZero;
-
- return (w1.gen.Equals(w2.gen) && w1.kill.Equals(w2.kill));
- }
-
- private static bool isGlobal(Variable! v)
- {
- return (v is GlobalVariable);
- }
-
- [Pure]
- public override string! ToString() {
- return string.Format("({0},{1})", gen.ToString(), kill.ToString());
- }
-
- public Set<Variable!>! getLiveVars() {
- return gen;
- }
-
- public Set<Variable!>! getLiveVars(Set<Variable!>! lv) {
- Set<Variable!>! temp = (!)lv.Difference(kill);
- return (!)temp.Union(gen);
- }
-
- }
-
- public class ICFG
- {
- public Graph<Block!>! graph;
- // Map from procedure to the list of blocks that call that procedure
- public Dictionary<string!, List<Block!>!>! procsCalled;
- public Set<Block!>! nodes;
- public Dictionary<Block!, Set<Block!>!>! succEdges;
- public Dictionary<Block!, Set<Block!>!>! predEdges;
- private Dictionary<Block!, int>! priority;
-
- public Set<Block!>! srcNodes;
- public Set<Block!>! exitNodes;
-
- public Dictionary<Block!, GenKillWeight!>! weightBefore;
- public Dictionary<Block!, GenKillWeight!>! weightAfter;
- public Dictionary<Block!, Set<Variable!>!>! liveVarsAfter;
- public Dictionary<Block!, Set<Variable!>!>! liveVarsBefore;
-
- public GenKillWeight! summary;
- public Implementation! impl;
-
- [NotDelayed]
- public ICFG(Implementation! impl) {
- this.graph = new Graph<Block!>();
- this.procsCalled = new Dictionary<string!, List<Block!>!>();
- this.nodes = new Set<Block!>();
- this.succEdges = new Dictionary<Block!, Set<Block!>!>();
- this.predEdges = new Dictionary<Block!, Set<Block!>!>();
-
- this.priority = new Dictionary<Block!, int>();
-
- this.srcNodes = new Set<Block!>();
- this.exitNodes = new Set<Block!>();
-
- this.weightBefore = new Dictionary<Block!, GenKillWeight!>();
- this.weightAfter = new Dictionary<Block!, GenKillWeight!>();
- this.liveVarsAfter = new Dictionary<Block!, Set<Variable!>!>();
- this.liveVarsBefore = new Dictionary<Block!, Set<Variable!>!>();
-
- summary = GenKillWeight.zero();
- this.impl = impl;
-
- base();
-
- Initialize(impl);
-
- }
-
- private void Initialize(Implementation! impl) {
- addSource(impl.Blocks[0]);
- graph.AddSource(impl.Blocks[0]);
-
- foreach(Block! b in impl.Blocks) {
- if(b.TransferCmd is ReturnCmd) {
- exitNodes.Add(b);
- } else {
- GotoCmd gc = b.TransferCmd as GotoCmd;
- assert gc != null;
- assert gc.labelTargets != null;
- foreach(Block! t in gc.labelTargets) {
- addEdge(b,t);
- graph.AddEdge(b,t);
- }
- }
-
- weightBefore[b] = GenKillWeight.zero();
- weightAfter[b] = GenKillWeight.zero();
-
- foreach(Cmd! c in b.Cmds) {
- if(c is CallCmd) {
- CallCmd! cc = (CallCmd!)c;
- assert cc.Proc != null;
- string! procName = cc.Proc.Name;
- if(!procsCalled.ContainsKey(procName)) {
- procsCalled.Add(procName, new List<Block!>());
- }
- procsCalled[procName].Add(b);
- }
- }
- }
-
- List<Block>! sortedNodes;
- bool acyclic;
-
- graph.TarjanTopSort(out acyclic, out sortedNodes);
-
- if(!acyclic) {
- Console.WriteLine("Warning: graph is not a dag");
- }
-
- int num = sortedNodes.Count;
- foreach(Block! b in sortedNodes) {
- priority.Add(b,num);
- num--;
- }
-
- }
-
- public int getPriority(Block! b) {
- if(priority.ContainsKey(b)) return priority[b];
- return Int32.MaxValue;
- }
-
- private void addSource(Block! b) {
- registerNode(b);
- this.srcNodes.Add(b);
- }
-
- private void addExit(Block! b) {
- registerNode(b);
- this.exitNodes.Add(b);
- }
-
- private void registerNode(Block! b) {
- if(!succEdges.ContainsKey(b)) {
- succEdges.Add(b, new Set<Block!>());
- }
-
- if(!predEdges.ContainsKey(b)) {
- predEdges.Add(b, new Set<Block!>());
- }
-
- nodes.Add(b);
- }
-
- private void addEdge(Block! src, Block! tgt) {
- registerNode(src);
- registerNode(tgt);
-
- succEdges[src].Add(tgt);
- predEdges[tgt].Add(src);
- }
-
-
- }
-
- // Interprocedural Gen/Kill Analysis
- public class InterProcGenKill
- {
- Program! program;
- Dictionary<string!, ICFG!>! procICFG;
- Dictionary<string!, Procedure!>! name2Proc;
- Dictionary<string!, List<WorkItem!>!>! callers;
- Graph<string!>! callGraph;
- Dictionary<string!, int>! procPriority;
- int maxBlocksInProc;
-
- WorkList! workList;
-
- Implementation! mainImpl;
-
- static Dictionary<string!, Set<Variable!>!>! varsLiveAtExit = new Dictionary<string!, Set<Variable!>!>();
- static Dictionary<string!, Set<Variable!>!>! varsLiveAtEntry = new Dictionary<string!, Set<Variable!>!>();
- static Dictionary<string!, GenKillWeight!>! varsLiveSummary = new Dictionary<string!, GenKillWeight!>();
-
- [NotDelayed]
- public InterProcGenKill(Implementation! impl, Program! program) {
- this.program = program;
- procICFG = new Dictionary<string!, ICFG!>();
- name2Proc = new Dictionary<string!, Procedure!>();
- workList = new WorkList();
- this.callers = new Dictionary<string!, List<WorkItem!>!>();
- this.callGraph = new Graph<string!>();
- this.procPriority = new Dictionary<string!, int>();
- this.maxBlocksInProc = 0;
- this.mainImpl = impl;
-
- Dictionary<string!, Implementation!>! name2Impl = new Dictionary<string!, Implementation!>();
- varsLiveAtExit.Clear();
- varsLiveAtEntry.Clear();
- varsLiveSummary.Clear();
-
- base();
-
- foreach(Declaration! decl in program.TopLevelDeclarations) {
- if(decl is Implementation) {
- Implementation! imp = (Implementation!)decl;
- name2Impl[imp.Name] = imp;
- } else if(decl is Procedure) {
- Procedure! proc = (!)(decl as Procedure);
- name2Proc[proc.Name] = proc;
- }
- }
-
- ICFG! mainICFG = new ICFG(mainImpl);
- procICFG.Add(mainICFG.impl.Name, mainICFG);
- callGraph.AddSource(mainICFG.impl.Name);
-
- List<ICFG!>! procsToConsider = new List<ICFG!>();
- procsToConsider.Add(mainICFG);
-
- while(procsToConsider.Count != 0) {
- ICFG! p = procsToConsider[0];
- procsToConsider.RemoveAt(0);
-
- foreach(string! callee in p.procsCalled.Keys) {
- if(!name2Impl.ContainsKey(callee)) continue;
-
- callGraph.AddEdge(p.impl.Name, callee);
-
- if(maxBlocksInProc < p.nodes.Count) {
- maxBlocksInProc = p.nodes.Count;
- }
-
- if(!callers.ContainsKey(callee)) {
- callers.Add(callee, new List<WorkItem!>());
- }
- foreach(Block! b in p.procsCalled[callee]) {
- callers[callee].Add(new WorkItem(p, b));
- }
-
- if(procICFG.ContainsKey(callee)) continue;
- ICFG! ncfg = new ICFG(name2Impl[callee]);
- procICFG.Add(callee, ncfg);
- procsToConsider.Add(ncfg);
- }
- }
-
- bool acyclic;
- List<string>! sortedNodes;
- callGraph.TarjanTopSort(out acyclic, out sortedNodes);
-
- assert acyclic;
-
- int cnt = 0;
- for(int i = sortedNodes.Count - 1; i >= 0; i--) {
- string s = sortedNodes[i];
- if(s == null) continue;
- procPriority.Add(s, cnt);
- cnt++;
- }
-
- }
-
- public static Set<Variable!>! GetVarsLiveAtExit(Implementation! impl, Program! prog) {
- if(varsLiveAtExit.ContainsKey(impl.Name)) {
- return varsLiveAtExit[impl.Name];
- }
- // Return default: all globals and out params
- Set<Variable!>! lv = new Set<Variable!>();
- foreach(Variable! v in prog.GlobalVariables()) {
- lv.Add(v);
- }
- foreach(Variable! v in impl.OutParams) {
- lv.Add(v);
- }
- return lv;
- }
-
- public static Set<Variable!>! GetVarsLiveAtEntry(Implementation! impl, Program! prog) {
- if(varsLiveAtEntry.ContainsKey(impl.Name)) {
- return varsLiveAtEntry[impl.Name];
- }
- // Return default: all globals and in params
- Set<Variable!>! lv = new Set<Variable!>();
- foreach(Variable! v in prog.GlobalVariables()) {
- lv.Add(v);
- }
- foreach(Variable! v in impl.InParams) {
- lv.Add(v);
- }
- return lv;
- }
-
- public static bool HasSummary(string! name) {
- return varsLiveSummary.ContainsKey(name);
- }
-
- public static Set<Variable!>! PropagateLiveVarsAcrossCall(CallCmd! cmd, Set<Variable!>! lvAfter) {
- Procedure! proc = (!)cmd.Proc;
- if(varsLiveSummary.ContainsKey(proc.Name)) {
- GenKillWeight! w1 = getWeightBeforeCall(cmd);
- GenKillWeight! w2 = varsLiveSummary[proc.Name];
- GenKillWeight! w3 = getWeightAfterCall(cmd);
- GenKillWeight! w = GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
- return w.getLiveVars(lvAfter);
- }
- Set<Variable!>! ret = new Set<Variable!>();
- ret.AddRange(lvAfter);
- LiveVariableAnalysis.Propagate(cmd, ret);
- return ret;
- }
-
- class WorkItem {
- public ICFG! cfg;
- public Block! block;
-
- public WorkItem(ICFG! cfg, Block! block) {
- this.cfg = cfg;
- this.block = block;
- }
-
- public GenKillWeight! getWeightAfter() {
- return cfg.weightAfter[block];
- }
-
- public bool setWeightBefore(GenKillWeight! w) {
- GenKillWeight! prev = cfg.weightBefore[block];
- GenKillWeight! curr = GenKillWeight.combine(w, prev);
- if(GenKillWeight.isEqual(prev, curr)) return false;
- cfg.weightBefore[block] = curr;
- return true;
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object other)
- {
- WorkItem! wi = (WorkItem!)(other);
- return (wi.cfg == cfg && wi.block == block);
- }
-
- [Pure]
- public override int GetHashCode()
- {
- return 0;
- }
-
- public string! getLabel() {
- return cfg.impl.Name + "::" + block.Label;
- }
-
- }
-
- private void AddToWorkList(WorkItem! wi) {
- int i = procPriority[wi.cfg.impl.Name];
- int j = wi.cfg.getPriority(wi.block);
- int priority = (i * maxBlocksInProc) + j;
-
- workList.Add(wi, priority);
- }
-
- private void AddToWorkListReverse(WorkItem! wi) {
- int i = procPriority[wi.cfg.impl.Name];
- int j = wi.cfg.getPriority(wi.block);
- int priority = (procPriority.Count - i) * maxBlocksInProc + j;
- workList.Add(wi, priority);
- }
-
- class WorkList {
- SortedList<int,int>! priorities;
- Set<string!>! labels;
-
- Dictionary<int, List<WorkItem!>!>! workList;
-
- public WorkList() {
- labels = new Set<string!>();
- priorities = new SortedList<int,int>();
- workList = new Dictionary<int, List<WorkItem!>!>();
- }
-
- public void Add(WorkItem! wi, int priority) {
- string! lab = wi.getLabel();
- if(labels.Contains(lab)) {
- // Already on worklist
- return;
- }
- labels.Add(lab);
- if(!workList.ContainsKey(priority)) {
- workList.Add(priority, new List<WorkItem!>());
- }
- workList[priority].Add(wi);
- if(!priorities.ContainsKey(priority)) {
- priorities.Add(priority,0);
- }
-
- priorities[priority] = priorities[priority] + 1;
- }
-
- public WorkItem! Get() {
- // Get minimum priority
- int p = ((!)priorities.Keys)[0];
- priorities[p] = priorities[p] - 1;
- if(priorities[p] == 0) {
- priorities.Remove(p);
- }
-
- // Get a WI with this priority
- WorkItem! wi = workList[p][0];
- workList[p].RemoveAt(0);
-
- // update labels
- labels.Remove(wi.getLabel());
- return wi;
- }
-
- public int Count {
- get {
- return labels.Count;
- }
- }
- }
-
- private GenKillWeight! getSummary(CallCmd! cmd) {
- assert cmd.Proc != null;
- string! procName = cmd.Proc.Name;
- if(procICFG.ContainsKey(procName)) {
- ICFG! cfg = procICFG[procName];
- return GenKillWeight.projectLocals(cfg.summary);
- }
- assert false;
- }
-
- public static void ComputeLiveVars(Implementation! impl, Program !prog) {
- InterProcGenKill! ipgk = new InterProcGenKill(impl, prog);
- ipgk.Compute();
- }
-
- public void Compute() {
- // Put all exit nodes in the worklist
- foreach(ICFG! cfg in procICFG.Values) {
- foreach(Block! eb in cfg.exitNodes) {
- WorkItem! wi = new WorkItem(cfg, eb);
- cfg.weightAfter[eb] = GenKillWeight.one();
- AddToWorkList(wi);
- }
- }
-
- while(workList.Count != 0) {
- WorkItem! wi = workList.Get();
- process(wi);
- }
-
- // Propagate LV to all procedures
- foreach(ICFG! cfg in procICFG.Values) {
- foreach(Block! b in cfg.nodes) {
- cfg.liveVarsAfter.Add(b, new Set<Variable!>());
- cfg.liveVarsBefore.Add(b, new Set<Variable!>());
- }
- }
-
- ICFG! mainCfg = procICFG[mainImpl.Name];
- foreach(Block! eb in mainCfg.exitNodes) {
- WorkItem! wi = new WorkItem(mainCfg, eb);
- AddToWorkListReverse(wi);
- }
-
- while(workList.Count != 0) {
- WorkItem! wi = workList.Get();
- processLV(wi);
- }
-
- // Set live variable info
- foreach(ICFG! cfg in procICFG.Values) {
- Set<Variable!>! lv = new Set<Variable!>();
- foreach(Block! eb in cfg.exitNodes) {
- lv.AddRange(cfg.liveVarsAfter[eb]);
- }
- varsLiveAtExit.Add(cfg.impl.Name, lv);
- lv = new Set<Variable!>();
- foreach(Block! eb in cfg.srcNodes) {
- lv.AddRange(cfg.liveVarsBefore[eb]);
- }
- varsLiveAtEntry.Add(cfg.impl.Name, lv);
- varsLiveSummary.Add(cfg.impl.Name, cfg.summary);
- }
-
- /*
- foreach(Block! b in mainImpl.Blocks) {
- //Set<Variable!> lv = cfg.weightBefore[b].getLiveVars();
- b.liveVarsBefore = procICFG[mainImpl.Name].liveVarsAfter[b];
- //foreach(GlobalVariable! v in program.GlobalVariables()) {
- // b.liveVarsBefore.Add(v);
- //}
- }
- */
- }
-
- // Called when summaries have already been computed
- private void processLV(WorkItem! wi) {
- ICFG! cfg = wi.cfg;
- Block! block = wi.block;
-
- Set<Variable!>! lv = cfg.liveVarsAfter[block];
-
- // Propagate backwards in the block
- Set<Variable!>! prop = new Set<Variable!>();
- prop.AddRange(lv);
- for(int i = block.Cmds.Length - 1; i >= 0; i--) {
- Cmd! cmd = block.Cmds[i];
- if(cmd is CallCmd) {
- string! procName = ((!)((CallCmd!)cmd).Proc).Name;
- if(procICFG.ContainsKey(procName)) {
- ICFG! callee = procICFG[procName];
- // Inter propagation
- // Remove local variables; add return variables
- Set<Variable!>! elv = new Set<Variable!>();
- foreach(Variable! v in prop) {
- if(v is GlobalVariable) elv.Add(v);
- }
- foreach(Variable! v in callee.impl.OutParams) {
- elv.Add(v);
- }
-
- foreach(Block! eb in callee.exitNodes) {
- callee.liveVarsAfter[eb].AddRange(elv);
- // TODO: check if modified before inserting
- AddToWorkListReverse(new WorkItem(callee, eb));
- }
-
- // Continue with intra propagation
- GenKillWeight! summary = getWeightCall((CallCmd!)cmd);
- prop = summary.getLiveVars(prop);
- } else {
- LiveVariableAnalysis.Propagate(cmd, prop);
- }
- } else {
- LiveVariableAnalysis.Propagate(cmd, prop);
- }
- }
-
- cfg.liveVarsBefore[block].AddRange(prop);
-
- foreach(Block! b in cfg.predEdges[block]) {
- Set<Variable!>! prev = cfg.liveVarsAfter[b];
- Set<Variable!>! curr = (!)prev.Union(cfg.liveVarsBefore[block]);
- if(curr.Count != prev.Count) {
- cfg.liveVarsAfter[b] = curr;
- AddToWorkListReverse(new WorkItem(cfg, b));
- }
- }
- }
-
- private void process(WorkItem! wi)
- {
- GenKillWeight! w = wi.getWeightAfter();
-
- for(int i = wi.block.Cmds.Length - 1; i >= 0; i--) {
- Cmd! c = wi.block.Cmds[i];
- if(c is CallCmd && procICFG.ContainsKey( ((!)((CallCmd!)c).Proc).Name ) ){
- w = GenKillWeight.extend(getWeightCall((CallCmd!)c), w);
- } else {
- GenKillWeight! cweight = getWeight(c, wi.cfg.impl, program);
- w = GenKillWeight.extend(cweight, w);
- }
- }
-
- bool change = wi.setWeightBefore(w);
-
- if(change && wi.cfg.srcNodes.Contains(wi.block)) {
- GenKillWeight! prev = wi.cfg.summary;
- GenKillWeight! curr = GenKillWeight.combine(prev, wi.cfg.weightBefore[wi.block]);
- if(!GenKillWeight.isEqual(prev, curr)) {
- wi.cfg.summary = curr;
- // push callers onto the worklist
- if(callers.ContainsKey(wi.cfg.impl.Name)) {
- foreach(WorkItem! caller in callers[wi.cfg.impl.Name]) {
- AddToWorkList(caller);
- }
- }
- }
- }
-
- foreach(Block! b in wi.cfg.predEdges[wi.block]) {
- GenKillWeight! prev = wi.cfg.weightAfter[b];
- GenKillWeight! curr = GenKillWeight.combine(prev, w);
- if(!GenKillWeight.isEqual(prev, curr)) {
- wi.cfg.weightAfter[b] = curr;
- AddToWorkList(new WorkItem(wi.cfg, b));
- }
- }
-
- }
-
- static Dictionary<Cmd!, GenKillWeight!>! weightCache = new Dictionary<Cmd!, GenKillWeight!>();
-
- private static GenKillWeight! getWeight(Cmd! cmd) {
- return getWeight(cmd, null, null);
- }
-
- private GenKillWeight! getWeightCall(CallCmd! cmd) {
- GenKillWeight! w1 = getWeightBeforeCall(cmd);
- GenKillWeight! w2 = getSummary(cmd);
- GenKillWeight! w3 = getWeightAfterCall(cmd);
- return GenKillWeight.extend(w1, GenKillWeight.extend(w2, w3));
- }
-
- private static GenKillWeight! getWeight(Cmd! cmd, Implementation impl, Program prog) {
-
- if(weightCache.ContainsKey(cmd))
- return weightCache[cmd];
-
- Set<Variable!>! gen = new Set<Variable!>();
- Set<Variable!>! kill = new Set<Variable!>();
- GenKillWeight! ret;
-
- if (cmd is AssignCmd) {
- AssignCmd! assignCmd = (AssignCmd) cmd;
- // I must first iterate over all the targets and remove the live ones.
- // After the removals are done, I must add the variables referred on
- // the right side of the removed targets
- foreach (AssignLhs! lhs in assignCmd.Lhss) {
- Variable var = lhs.DeepAssignedVariable;
- if (var != null) {
- if (lhs is SimpleAssignLhs) {
- // we should only remove non-map target variables because there is an implicit
- // read of a map variable in an assignment to it
- kill.Add(var);
- }
- }
- }
- int index = 0;
- foreach (Expr! expr in assignCmd.Rhss) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(expr);
- gen.AddRange(collector.usedVars);
- AssignLhs lhs = assignCmd.Lhss[index];
- if (lhs is MapAssignLhs) {
- // If the target is a map, then all indices are also read
- MapAssignLhs malhs = (MapAssignLhs) lhs;
- foreach (Expr e in malhs.Indexes) {
- VariableCollector! c = new VariableCollector();
- c.Visit(e);
- gen.AddRange(c.usedVars);
- }
- }
- index++;
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is HavocCmd) {
- HavocCmd! havocCmd = (HavocCmd) cmd;
- foreach (IdentifierExpr! expr in havocCmd.Vars) {
- if (expr.Decl != null) {
- kill.Add(expr.Decl);
- }
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is PredicateCmd) {
- assert (cmd is AssertCmd || cmd is AssumeCmd);
- PredicateCmd! predicateCmd = (PredicateCmd) cmd;
- if (predicateCmd.Expr is LiteralExpr && prog != null && impl != null) {
- LiteralExpr le = (LiteralExpr) predicateCmd.Expr;
- if (le.IsFalse) {
- List<GlobalVariable!>! globals = prog.GlobalVariables();
- foreach(Variable! v in globals) {
- kill.Add(v);
- }
- foreach(Variable! v in impl.LocVars) {
- kill.Add(v);
- }
- foreach(Variable! v in impl.OutParams) {
- kill.Add(v);
- }
- }
- } else {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(predicateCmd.Expr);
- gen.AddRange(collector.usedVars);
- }
- ret = new GenKillWeight(gen, kill);
- } else if (cmd is CommentCmd) {
- ret = new GenKillWeight(gen, kill);
- // comments are just for debugging and don't affect verification
- } else if (cmd is SugaredCmd) {
- SugaredCmd! sugCmd = (SugaredCmd) cmd;
- ret = getWeight(sugCmd.Desugaring, impl, prog);
- } else if (cmd is StateCmd) {
- StateCmd! stCmd = (StateCmd) cmd;
- CmdSeq! cmds = stCmd.Cmds;
- int len = cmds.Length;
- ret = GenKillWeight.one();
- for (int i = len - 1; i >= 0; i--) {
- GenKillWeight! w = getWeight(cmds[i], impl, prog);
- ret = GenKillWeight.extend(w, ret);
- }
- foreach (Variable! v in stCmd.Locals) {
- kill.Add(v);
- }
- ret = GenKillWeight.extend(new GenKillWeight(gen, kill), ret);
- } else {
- assert false;
- }
-
- weightCache[cmd] = ret;
- return ret;
- }
-
- static Dictionary<Cmd!, GenKillWeight!>! weightCacheAfterCall = new Dictionary<Cmd!, GenKillWeight!>();
- static Dictionary<Cmd!, GenKillWeight!>! weightCacheBeforeCall = new Dictionary<Cmd!, GenKillWeight!>();
-
- private static GenKillWeight! getWeightAfterCall(Cmd! cmd) {
-
- if(weightCacheAfterCall.ContainsKey(cmd))
- return weightCacheAfterCall[cmd];
-
- Set<Variable!>! gen = new Set<Variable!>();
- Set<Variable!>! kill = new Set<Variable!>();
-
- assert (cmd is CallCmd);
- CallCmd! ccmd = (CallCmd!)cmd;
-
- foreach(IdentifierExpr! ie in ccmd.Outs) {
- if(ie.Decl != null) kill.Add(ie.Decl);
- }
-
- // Variables in ensures are considered as "read"
- foreach(Ensures! re in ((!)ccmd.Proc).Ensures) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach(Variable! v in collector.usedVars) {
- if(v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- GenKillWeight! ret = new GenKillWeight(gen, kill);
- weightCacheAfterCall[cmd] = ret;
- return ret;
- }
-
- private static GenKillWeight! getWeightBeforeCall(Cmd! cmd) {
- assert (cmd is CallCmd);
- if(weightCacheBeforeCall.ContainsKey(cmd))
- return weightCacheBeforeCall[cmd];
-
- Set<Variable!>! gen = new Set<Variable!>();
- Set<Variable!>! kill = new Set<Variable!>();
- CallCmd! ccmd = (CallCmd!)cmd;
-
- foreach (Expr! expr in ccmd.Ins) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(expr);
- gen.AddRange(collector.usedVars);
- }
-
- assert ccmd.Proc != null;
-
- // Variables in requires are considered as "read"
- foreach(Requires! re in ccmd.Proc.Requires) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach(Variable! v in collector.usedVars) {
- if(v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- // Old variables in ensures are considered as "read"
- foreach(Ensures! re in ccmd.Proc.Ensures) {
- VariableCollector! collector = new VariableCollector();
- collector.Visit(re.Condition);
- foreach(Variable! v in collector.oldVarsUsed) {
- if(v is GlobalVariable) {
- gen.Add(v);
- }
- }
- }
-
- GenKillWeight! ret = new GenKillWeight(gen, kill);
- weightCacheAfterCall[cmd] = ret;
- return ret;
- }
-
-
- }
-
-} \ No newline at end of file
diff --git a/Source/Core/Duplicator.ssc b/Source/Core/Duplicator.ssc
deleted file mode 100644
index f265ee35..00000000
--- a/Source/Core/Duplicator.ssc
+++ /dev/null
@@ -1,408 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - Duplicator.cs
-//---------------------------------------------------------------------------------------------
-
-using System.Collections;
-using System.Collections.Generic;
-
-namespace Microsoft.Boogie
-{
- public class Duplicator : StandardVisitor
- {
- public override Absy! Visit(Absy! node)
- {
- node = base.Visit(node);
- return node;
- }
-
- public override Cmd! VisitAssertCmd(AssertCmd! node)
- {
- return base.VisitAssertCmd ((AssertCmd)node.Clone());
- }
- public override Cmd! VisitAssignCmd(AssignCmd! node)
- {
- AssignCmd clone = (AssignCmd)node.Clone();
- clone.Lhss = new List<AssignLhs!>(clone.Lhss);
- clone.Rhss = new List<Expr!>(clone.Rhss);
- return base.VisitAssignCmd(clone);
- }
- public override Cmd! VisitAssumeCmd(AssumeCmd! node)
- {
- return base.VisitAssumeCmd ((AssumeCmd)node.Clone());
- }
- public override AtomicRE! VisitAtomicRE(AtomicRE! node)
- {
- return base.VisitAtomicRE ((AtomicRE)node.Clone());
- }
- public override Axiom! VisitAxiom(Axiom! node)
- {
- return base.VisitAxiom ((Axiom)node.Clone());
- }
- public override Type! VisitBasicType(BasicType! node)
- {
- // do /not/ clone the type recursively
- return (BasicType)node.Clone();
- }
- public override Block! VisitBlock(Block! node)
- {
- return base.VisitBlock ((Block)node.Clone());
- }
- public override Expr! VisitCodeExpr(CodeExpr! node)
- {
- CodeExpr clone = (CodeExpr)base.VisitCodeExpr((CodeExpr)node.Clone());
- // Before returning, fix up the resolved goto targets
- assert node.Blocks.Count == clone.Blocks.Count;
- Dictionary<Block,Block> subst = new Dictionary<Block,Block>();
- for (int i = 0; i < node.Blocks.Count; i++) {
- subst.Add(node.Blocks[i], clone.Blocks[i]);
- }
- foreach (Block! b in clone.Blocks) {
- GotoCmd g = b.TransferCmd as GotoCmd;
- if (g != null) {
- BlockSeq targets = new BlockSeq();
- foreach (Block t in (!)g.labelTargets) {
- Block nt = subst[t];
- targets.Add(nt);
- }
- g.labelTargets = targets;
- }
- }
- return clone;
- }
- public override BlockSeq! VisitBlockSeq(BlockSeq! blockSeq)
- {
- return base.VisitBlockSeq (new BlockSeq(blockSeq));
- }
- public override List<Block!>! VisitBlockList(List<Block!>! blocks)
- {
- return base.VisitBlockList (new List<Block!>(blocks));
- }
- public override BoundVariable! VisitBoundVariable(BoundVariable! node)
- {
- return base.VisitBoundVariable ((BoundVariable)node.Clone());
- }
- public override Type! VisitBvType(BvType! node)
- {
- // do /not/ clone the type recursively
- return (BvType)node.Clone();
- }
- public override Cmd! VisitCallCmd(CallCmd! node)
- {
- CallCmd! clone = (CallCmd)node.Clone();
- clone.Ins = new List<Expr>(clone.Ins);
- clone.Outs = new List<IdentifierExpr>(clone.Outs);
- return base.VisitCallCmd(clone);
- }
- public override Cmd! VisitCallForallCmd(CallForallCmd! node)
- {
- CallForallCmd! clone = (CallForallCmd)node.Clone();
- clone.Ins = new List<Expr>(clone.Ins);
- return base.VisitCallForallCmd(clone);
- }
- public override Choice! VisitChoice(Choice! node)
- {
- return base.VisitChoice ((Choice)node.Clone());
- }
- public override CmdSeq! VisitCmdSeq(CmdSeq! cmdSeq)
- {
- return base.VisitCmdSeq (cmdSeq);
- }
- public override Constant! VisitConstant(Constant! node)
- {
- return base.VisitConstant ((Constant)node.Clone());
- }
- public override CtorType! VisitCtorType(CtorType! node)
- {
- // do /not/ clone the type recursively
- return (CtorType)node.Clone();
- }
- public override Declaration! VisitDeclaration(Declaration! node)
- {
- return base.VisitDeclaration ((Declaration)node.Clone());
- }
- public override List<Declaration!>! VisitDeclarationList(List<Declaration!>! declarationList)
- {
- return base.VisitDeclarationList(declarationList);
- }
- public override DeclWithFormals! VisitDeclWithFormals(DeclWithFormals! node)
- {
- return base.VisitDeclWithFormals ((DeclWithFormals)node.Clone());
- }
- public override ExistsExpr! VisitExistsExpr(ExistsExpr! node)
- {
- return base.VisitExistsExpr ((ExistsExpr)node.Clone());
- }
- public override Expr! VisitExpr(Expr! node)
- {
- return base.VisitExpr ((Expr)node.Clone());
- }
- public override ExprSeq! VisitExprSeq(ExprSeq! list)
- {
- return base.VisitExprSeq (new ExprSeq(list));
- }
- public override ForallExpr! VisitForallExpr(ForallExpr! node)
- {
- return base.VisitForallExpr ((ForallExpr)node.Clone());
- }
- public override Formal! VisitFormal(Formal! node)
- {
- return base.VisitFormal ((Formal)node.Clone());
- }
- public override Function! VisitFunction(Function! node)
- {
- return base.VisitFunction ((Function)node.Clone());
- }
- public override GlobalVariable! VisitGlobalVariable(GlobalVariable! node)
- {
- return base.VisitGlobalVariable ((GlobalVariable)node.Clone());
- }
- public override GotoCmd! VisitGotoCmd(GotoCmd! node)
- {
- return base.VisitGotoCmd ((GotoCmd)node.Clone());
- }
- public override Cmd! VisitHavocCmd(HavocCmd! node)
- {
- return base.VisitHavocCmd ((HavocCmd)node.Clone());
- }
- public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
- {
- return base.VisitIdentifierExpr ((IdentifierExpr) node.Clone());
- }
- public override IdentifierExprSeq! VisitIdentifierExprSeq(IdentifierExprSeq! identifierExprSeq)
- {
- return base.VisitIdentifierExprSeq (new IdentifierExprSeq(identifierExprSeq));
- }
- public override Implementation! VisitImplementation(Implementation! node)
- {
- return base.VisitImplementation ((Implementation)node.Clone());
- }
- public override LiteralExpr! VisitLiteralExpr(LiteralExpr! node)
- {
- return base.VisitLiteralExpr ((LiteralExpr)node.Clone());
- }
- public override LocalVariable! VisitLocalVariable(LocalVariable! node)
- {
- return base.VisitLocalVariable ((LocalVariable)node.Clone());
- }
- public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node)
- {
- MapAssignLhs clone = (MapAssignLhs)node.Clone();
- clone.Indexes = new List<Expr!>(clone.Indexes);
- return base.VisitMapAssignLhs(clone);
- }
- public override MapType! VisitMapType(MapType! node)
- {
- // do /not/ clone the type recursively
- return (MapType)node.Clone();
- }
- public override Expr! VisitNAryExpr(NAryExpr! node)
- {
- return base.VisitNAryExpr ((NAryExpr)node.Clone());
- }
- public override Expr! VisitOldExpr(OldExpr! node)
- {
- return base.VisitOldExpr ((OldExpr) node.Clone());
- }
- public override Procedure! VisitProcedure(Procedure! node)
- {
- return base.VisitProcedure ((Procedure)node.Clone());
- }
- public override Program! VisitProgram(Program! node)
- {
- return base.VisitProgram ((Program) node.Clone());
- }
- public override BinderExpr! VisitBinderExpr(BinderExpr! node)
- {
- return base.VisitBinderExpr ((BinderExpr) node.Clone());
- }
- public override Cmd! VisitRE(RE! node)
- {
- return base.VisitRE ((RE) node.Clone());
- }
- public override RESeq! VisitRESeq(RESeq! reSeq)
- {
- return base.VisitRESeq (new RESeq(reSeq));
- }
- public override ReturnCmd! VisitReturnCmd(ReturnCmd! node)
- {
- return base.VisitReturnCmd ((ReturnCmd) node.Clone());
- }
- public override ReturnExprCmd! VisitReturnExprCmd(ReturnExprCmd! node)
- {
- return base.VisitReturnExprCmd((ReturnExprCmd)node.Clone());
- }
- public override Sequential! VisitSequential(Sequential! node)
- {
- return base.VisitSequential ((Sequential) node.Clone());
- }
- public override AssignLhs! VisitSimpleAssignLhs(SimpleAssignLhs! node)
- {
- return base.VisitSimpleAssignLhs ((SimpleAssignLhs)node.Clone());
- }
- public override Cmd! VisitStateCmd(StateCmd! node)
- {
- return base.VisitStateCmd ((StateCmd)node.Clone());
- }
- public override TransferCmd! VisitTransferCmd(TransferCmd! node)
- {
- return base.VisitTransferCmd ((TransferCmd) node.Clone());
- }
- public override Trigger! VisitTrigger(Trigger! node)
- {
- return base.VisitTrigger ((Trigger) node.Clone());
- }
- public override Type! VisitType(Type! node)
- {
- // do /not/ clone the type recursively
- return (Type)node.Clone();
- }
- public override TypedIdent! VisitTypedIdent(TypedIdent! node)
- {
- return base.VisitTypedIdent ((TypedIdent) node.Clone());
- }
- public override Variable! VisitVariable(Variable! node)
- {
- return node;
- }
- public override VariableSeq! VisitVariableSeq(VariableSeq! variableSeq)
- {
- return base.VisitVariableSeq (new VariableSeq(variableSeq));
- }
- public override Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
- {
- return base.VisitAssertRequiresCmd((AssertRequiresCmd)node.Clone());
- }
- public override Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
- {
- return base.VisitAssertEnsuresCmd((AssertEnsuresCmd)node.Clone());
- }
- public override Ensures! VisitEnsures(Ensures! node)
- {
- return base.VisitEnsures((Ensures)node.Clone());
- }
- public override Requires! VisitRequires(Requires! node)
- {
- return base.VisitRequires((Requires)node.Clone());
- }
- }
-
-
- #region A duplicator that also does substitutions for a set of variables
- /// <summary>
- /// A substitution is a partial mapping from Variables to Exprs.
- /// </summary>
- public delegate Expr/*?*/ Substitution(Variable! v);
-
- public static class Substituter
- {
- public static Substitution! SubstitutionFromHashtable(Hashtable/*Variable!->Expr!*/! map)
- {
- // TODO: With Whidbey, could use anonymous functions.
- return new Substitution(new CreateSubstitutionClosure(map).Method);
- }
- private sealed class CreateSubstitutionClosure
- {
- Hashtable/*Variable!->Expr!*/! map;
- public CreateSubstitutionClosure(Hashtable/*Variable!->Expr!*/! map) { this.map = map; base(); }
- public Expr/*?*/ Method(Variable! v) { return (Expr) map[v]; }
- }
-
- /// <summary>
- /// Apply a substitution to an expression. Any variables not in domain(subst)
- /// is not changed. The substitutions applies within the "old", but the "old"
- /// expression remains.
- /// </summary>
- public static Expr! Apply(Substitution! subst, Expr! expr)
- {
- return (Expr) new NormalSubstituter(subst).Visit(expr);
- }
-
- /// <summary>
- /// Apply a substitution to a command. Any variables not in domain(subst)
- /// is not changed. The substitutions applies within the "old", but the "old"
- /// expression remains.
- /// </summary>
- public static Cmd! Apply(Substitution! subst, Cmd! cmd)
- {
- return (Cmd) new NormalSubstituter(subst).Visit(cmd);
- }
-
- /// <summary>
- /// Apply a substitution to an expression replacing "old" expressions.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "oldExpr" to
- /// variables in domain(oldExpr), apply map "always" to variables in
- /// domain(always)-domain(oldExpr), and leave variable unchanged otherwise.
- /// </summary>
- public static Expr! ApplyReplacingOldExprs(Substitution! always, Substitution! forold, Expr! expr)
- {
- return (Expr) new ReplacingOldSubstituter(always, forold).Visit(expr);
- }
-
- /// <summary>
- /// Apply a substitution to a command replacing "old" expressions.
- /// Outside "old" expressions, the substitution "always" is applied; any variable not in
- /// domain(always) is not changed. Inside "old" expressions, apply map "oldExpr" to
- /// variables in domain(oldExpr), apply map "always" to variables in
- /// domain(always)-domain(oldExpr), and leave variable unchanged otherwise.
- /// </summary>
- public static Cmd! ApplyReplacingOldExprs(Substitution! always, Substitution! forold, Cmd! cmd)
- {
- return (Cmd) new ReplacingOldSubstituter(always, forold).Visit(cmd);
- }
-
- private sealed class NormalSubstituter : Duplicator
- {
- private readonly Substitution! subst;
- public NormalSubstituter(Substitution! subst) { this.subst = subst; base(); }
-
- public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
- {
- Expr/*?*/ e = subst((!)node.Decl);
- return e == null ? base.VisitIdentifierExpr(node) : e;
- }
- }
-
- private sealed class ReplacingOldSubstituter : Duplicator
- {
- private readonly Substitution! always;
- private readonly Substitution! forold;
- public ReplacingOldSubstituter(Substitution! always, Substitution! forold)
- { this.always = always; this.forold = forold; base(); }
-
- private bool insideOldExpr = false;
-
- public override Expr! VisitIdentifierExpr(IdentifierExpr! node)
- {
- Expr/*?*/ e = null;
-
- if (insideOldExpr)
- {
- e = forold((!)node.Decl);
- }
-
- if (e == null)
- {
- e = always((!)node.Decl);
- }
-
- return e == null ? base.VisitIdentifierExpr(node) : e;
- }
-
- public override Expr! VisitOldExpr(OldExpr! node)
- {
- bool previouslyInOld = insideOldExpr;
- insideOldExpr = true;
- Expr! e = (Expr!)this.Visit(node.Expr);
- insideOldExpr = previouslyInOld;
- return e;
- }
- }
- }
- #endregion
-}
diff --git a/Source/Core/GraphAlgorithms.ssc b/Source/Core/GraphAlgorithms.ssc
deleted file mode 100644
index e1303316..00000000
--- a/Source/Core/GraphAlgorithms.ssc
+++ /dev/null
@@ -1,175 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System.Collections.Generic;
-using Microsoft.Contracts;
-
-namespace Microsoft.Boogie
-{
- public delegate System.Collections.IEnumerable/*<Node!>*/! Adjacency<T>(T! node);
-
-
- // An SCC is a set of nodes
- public sealed class SCC<Node> : ICollection<Node>
- {
- private IDictionary<Node,object>! nodesMap = new Dictionary<Node,object>();
- private ICollection<Node>! nodes { get { return (!) nodesMap.Keys; } }
-
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- System.Collections.IEnumerator! System.Collections.IEnumerable.GetEnumerator()
- {
- return ((System.Collections.IEnumerable)nodes).GetEnumerator();
- }
-
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- IEnumerator<Node>! IEnumerable<Node>.GetEnumerator()
- {
- return ((IEnumerable<Node>)nodes).GetEnumerator();
- }
-
- public int Count { get { return nodes.Count; } }
- public bool IsReadOnly { get { return nodesMap.IsReadOnly; } }
- public void Add(Node item) { nodesMap.Add(item,null); }
- public void Clear() { nodesMap.Clear(); }
- [Pure]
- public bool Contains(Node item) { return nodesMap.ContainsKey(item); }
- public void CopyTo(Node[]! array, int arrayIndex) { nodes.CopyTo(array, arrayIndex); }
- public bool Remove(Node item) { return nodesMap.Remove(item); }
- }
-
- public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>!>
- {
- private readonly IDictionary<Node!,object>! graph;
- private readonly Adjacency<Node>! preds;
- private readonly Adjacency<Node>! succs;
-
- private bool computed = false;
- public bool Computed { get { return computed; } }
-
- [NotDelayed]
- public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/! graph, Adjacency<Node>! preds, Adjacency<Node>! succs)
- ensures !Computed;
- {
- IDictionary<Node!,object>! dict = new Dictionary<Node!,object>();
- foreach (Node! n in graph) { dict.Add(n,null); }
-
- this.graph = dict;
- this.preds = preds;
- this.succs = succs;
- base();
- }
-
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- System.Collections.IEnumerator! System.Collections.IEnumerable.GetEnumerator()
- {
- return ((System.Collections.IEnumerable)sccs).GetEnumerator();
- }
-
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- IEnumerator<SCC<Node>!>! IEnumerable<SCC<Node>!>.GetEnumerator()
- {
- assume Computed;
- return ((IEnumerable<SCC<Node>!>)sccs).GetEnumerator();
- }
-
- private readonly IList<SCC<Node>!>! sccs = new List<SCC<Node>!>();
-
- public void Compute()
- requires !Computed;
- ensures Computed;
- {
- // Compute post times on graph with edges reversed
- this.dfsNext = this.preds;
- foreach (Node! n in (!)graph.Keys)
- {
- if (!seen.ContainsKey(n))
- {
- OrderNodes(n);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- // Compute SCCs
- this.dfsNext = this.succs;
- while (postOrder.Count > 0)
- {
- Node! n = postOrder.Pop();
-
- if (!seen.ContainsKey(n))
- {
- SCC<Node>! curr = new SCC<Node>();
- FindSCCs(n, curr);
- sccs.Add(curr);
- }
- }
-
- // Clear seen
- seen.Clear();
-
- this.computed = true;
- }
-
- private Adjacency<Node>/*?*/ dfsNext = null;
-
- private readonly IDictionary<Node!,object>! seen = new Dictionary<Node!,object>();
- private readonly Stack<Node!>! postOrder = new Stack<Node!>();
-
- // DFS to order nodes by post times
- private void OrderNodes(Node! node)
- {
- seen.Add(node,null);
-
- assert dfsNext != null;
- System.Collections.IEnumerable! nexts = dfsNext(node);
- foreach (Node! n in nexts)
- {
- if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { OrderNodes(n); }
- }
-
- postOrder.Push(node);
- }
-
- // DFS to compute SCCs
- private void FindSCCs(Node! node, SCC<Node>! currSCC)
- //modifies currSCC.*;
- {
- seen.Add(node,null);
- currSCC.Add(node);
-
- assert dfsNext != null;
- System.Collections.IEnumerable! nexts = dfsNext(node);
- foreach (Node! n in nexts)
- {
- if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { FindSCCs(n,currSCC); }
- }
- }
-
- [Pure]
- public override string! ToString()
- {
- string outStr = "";
- int i = 0;
-
- foreach(ICollection<Node> component in this)
- {
- string! tmp = System.String.Format("\nComponent #{0} = ", i++);
- outStr += tmp;
-
- bool firstInRow = true;
-
- foreach(Node b in component)
- {
- string! tmpComponent = System.String.Format("{0}{1}", firstInRow? "" : ", ", b);
- outStr += tmpComponent;
- firstInRow = false;
- }
- }
- return outStr;
- }
-
- }
-}
diff --git a/Source/Core/Inline.ssc b/Source/Core/Inline.ssc
deleted file mode 100644
index 0db27d6d..00000000
--- a/Source/Core/Inline.ssc
+++ /dev/null
@@ -1,689 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
-
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using BoogiePL;
- using System.Diagnostics;
- using System.Text.RegularExpressions; // for procedure inlining
-
- // this callback is called before inlining a procedure
- public delegate void InlineCallback(Implementation! impl);
-
- public class Inliner
- {
- private InlineCallback inlineCallback;
-
- protected CodeCopier! codeCopier;
-
- protected Dictionary<string!,int>! /* Procedure.Name -> int */ recursiveProcUnrollMap;
-
- protected Dictionary<string!,int>! /* Procedure.Name -> int */ inlinedProcLblMap;
-
- protected void NextInlinedProcLabel(string! procName) {
- int currentId;
- if (inlinedProcLblMap.TryGetValue(procName, out currentId)) {
- inlinedProcLblMap[procName] = currentId + 1;
- } else {
- inlinedProcLblMap.Add(procName, 0);
- }
- }
-
- protected string! GetInlinedProcLabel(string! procName) {
- int currentId;
- if (!inlinedProcLblMap.TryGetValue(procName, out currentId)) {
- currentId = 0;
- inlinedProcLblMap.Add(procName, currentId);
- }
- return "inline$" + procName + "$" + currentId;
- }
-
- protected string! GetProcVarName(string! procName, string! formalName) {
- string! prefix = GetInlinedProcLabel(procName);
- return prefix + "$" + formalName;
- }
-
- protected Inliner(InlineCallback cb) {
- inlinedProcLblMap = new Dictionary<string!,int>();
- recursiveProcUnrollMap = new Dictionary<string!,int>();
- codeCopier = new CodeCopier();
- inlineCallback = cb;
- }
-
- public static void ProcessImplementation(Program! program, Implementation! impl, InlineCallback cb)
- requires impl.Proc != null;
- {
- Inliner inliner = new Inliner(cb);
-
- VariableSeq! newInParams = new VariableSeq(impl.InParams);
- VariableSeq! newOutParams = new VariableSeq(impl.OutParams);
- VariableSeq! newLocalVars = new VariableSeq(impl.LocVars);
-
- IdentifierExprSeq! newModifies = new IdentifierExprSeq(impl.Proc.Modifies);
-
- bool inlined = false;
- List<Block!>! newBlocks = inliner.DoInline(impl.Blocks, program, newLocalVars, newModifies, out inlined);
-
- if (!inlined) return;
-
- impl.InParams = newInParams;
- impl.OutParams = newOutParams;
- impl.LocVars = newLocalVars;
- impl.Blocks = newBlocks;
- impl.Proc.Modifies = newModifies;
-
- impl.ResetImplFormalMap();
-
- // we need to resolve the new code
- inliner.ResolveImpl(program, impl);
-
- if(CommandLineOptions.Clo.PrintInlined) {
- inliner.EmitImpl(impl);
- }
- }
-
-
- public static void ProcessImplementation(Program! program, Implementation! impl)
- requires impl.Proc != null;
- {
- ProcessImplementation(program, impl, null);
- }
-
- protected void EmitImpl(Implementation! impl)
- requires impl.Proc != null;
- {
- Console.WriteLine("after inlining procedure calls");
- impl.Proc.Emit(new TokenTextWriter("<console>", Console.Out), 0);
- impl.Emit(new TokenTextWriter("<console>", Console.Out), 0);
- }
-
- private sealed class DummyErrorSink : IErrorSink
- {
- public void Error(IToken! tok, string! msg) {
- // FIXME
- // noop.
- // This is required because during the resolution, some resolution errors happen
- // (such as the ones caused addion of loop invariants J_(block.Label) by the AI package
- }
- }
-
- protected void ResolveImpl(Program! program, Implementation! impl)
- ensures impl.Proc != null;
- {
- ResolutionContext rc = new ResolutionContext(new DummyErrorSink());
-
- foreach(Declaration decl in program.TopLevelDeclarations) {
- decl.Register(rc);
- }
-
- impl.Proc = null; // to force Resolve() redo the operation
- impl.Resolve(rc);
-
- TypecheckingContext tc = new TypecheckingContext(new DummyErrorSink());
-
- impl.Typecheck(tc);
- }
-
-
- // returns true if it is ok to further unroll the procedure
- // otherwise, the procedure is not inlined at the call site
- protected int GetInlineCount(Implementation! impl) {
- string! procName = impl.Name;
- int c;
- if (recursiveProcUnrollMap.TryGetValue(procName, out c)) {
- return c;
- }
-
- c = -1; // TryGetValue above always overwrites c
- impl.CheckIntAttribute("inline", ref c);
- // procedure attribute overrides implementation
- if (impl.Proc != null) {
- impl.Proc.CheckIntAttribute("inline", ref c);
- }
-
- recursiveProcUnrollMap[procName] = c;
- return c;
- }
-
- void CheckRecursion(Implementation! impl, Stack<Procedure!>! callStack) {
- foreach (Procedure! p in callStack) {
- if (p == impl.Proc) {
- string msg = "";
- foreach (Procedure! p in callStack) {
- msg = p.Name + " -> " + msg;
- }
- msg += p.Name;
- //checkingCtx.Error(impl, "inlined procedure is recursive, call stack: {0}", msg);
- }
- }
- }
-
- private List<Block!>! DoInlineBlocks(Stack<Procedure!>! callStack, List<Block!>! blocks, Program! program,
- VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, ref bool inlinedSomething)
- {
- List<Block!>! newBlocks = new List<Block!>();
-
- foreach(Block block in blocks) {
- TransferCmd! transferCmd = (!) block.TransferCmd;
- CmdSeq cmds = block.Cmds;
- CmdSeq newCmds = new CmdSeq();
- Block newBlock;
- string label = block.Label;
- int lblCount = 0;
-
- for(int i = 0; i < cmds.Length; ++i) {
- Cmd cmd = cmds[i];
- CallCmd callCmd = cmd as CallCmd;
-
- if(callCmd == null) {
- // if not call command, leave it as is
- newCmds.Add(codeCopier.CopyCmd(cmd));
- } else {
- assert(callCmd.Proc != null);
- Procedure proc = null;
- Implementation impl = null;
- string calleeName = callCmd.Proc.Name;
-
- int inline = -1;
-
- // *** now we do not allow constructors to be inlined
- if (!calleeName.Contains("..ctor")) {
- // FIXME why on earth are we searching by name?!
- bool implExists = FindProcImpl(program, calleeName, out proc, out impl);
- assume(!implExists || (proc != null && impl != null));
- if (implExists) {
- inline = GetInlineCount((!)impl);
- }
- }
-
- assert(inline == -1 || impl != null);
-
- if (inline > 0) { // at least one block should exist
- assume(impl != null && proc != null);
- assert(((!)impl.OriginalBlocks).Count > 0);
- inlinedSomething = true;
-
- // do inline now
- int nextlblCount = lblCount + 1;
- string nextBlockLabel = label + "$" + nextlblCount;
-
- // run the callback before each inline
- if(inlineCallback != null) {
- inlineCallback(impl);
- }
-
- // increment the counter for the procedure to be used in constructing the locals and formals
- NextInlinedProcLabel(proc.Name);
-
- BeginInline(newLocalVars, newModifies, proc, impl);
-
- List<Block!>! inlinedBlocks = CreateInlinedBlocks(callCmd, proc, impl, nextBlockLabel);
-
- EndInline();
-
- recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] - 1;
- callStack.Push((!)impl.Proc);
- inlinedBlocks = DoInlineBlocks(callStack, inlinedBlocks, program, newLocalVars, newModifies, ref inlinedSomething);
- callStack.Pop();
- recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] + 1;
-
- Block! startBlock = inlinedBlocks[0];
-
- GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new StringSeq(startBlock.Label));
- newBlock = new Block(block.tok, ((lblCount == 0) ? (label) : (label + "$" + lblCount)), newCmds, gotoCmd);
-
- newBlocks.Add(newBlock);
- newBlocks.AddRange(inlinedBlocks);
-
- lblCount = nextlblCount;
- newCmds = new CmdSeq();
- } else if (inline == 0) {
- inlinedSomething = true;
- if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assert) {
- // add assert
- newCmds.Add(new AssertCmd(callCmd.tok, Expr.False));
- } else if (CommandLineOptions.Clo.ProcedureInlining == CommandLineOptions.Inlining.Assume) {
- // add assume
- newCmds.Add(new AssumeCmd(callCmd.tok, Expr.False));
- } else {
- // add call
- newCmds.Add(codeCopier.CopyCmd(callCmd));
- }
- } else {
- newCmds.Add(codeCopier.CopyCmd(callCmd));
- }
- }
- }
-
- newBlock = new Block(block.tok, ((lblCount == 0) ? (label) : (label + "$" + lblCount)), newCmds, codeCopier.CopyTransferCmd(transferCmd));
- newBlocks.Add(newBlock);
- }
-
- return newBlocks;
- }
-
- protected List<Block!>! DoInline(List<Block!>! blocks, Program! program, VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, out bool inlined)
- {
- inlinedProcLblMap.Clear();
- recursiveProcUnrollMap.Clear();
-
- inlined = false;
- return DoInlineBlocks(new Stack<Procedure!>(), blocks, program, newLocalVars, newModifies, ref inlined);
- }
-
- protected void BeginInline(VariableSeq! newLocalVars, IdentifierExprSeq! newModifies, Procedure! proc, Implementation! impl) {
- Hashtable substMap = new Hashtable();
-
- foreach(Variable! locVar in (!)impl.OriginalLocVars) {
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr));
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(locVar, ie);
- }
-
- for (int i = 0; i < impl.InParams.Length; i++) {
- Variable inVar = (!) impl.InParams[i];
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr));
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(inVar, ie);
- // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
- Variable procInVar = (!)proc.InParams[i];
- if (procInVar != inVar) {
- substMap.Add(procInVar, ie);
- }
- }
-
- for (int i = 0; i < impl.OutParams.Length; i++) {
- Variable outVar = (!) impl.OutParams[i];
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr));
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMap.Add(outVar, ie);
- // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration
- Variable procOutVar = (!)proc.OutParams[i];
- if (procOutVar != outVar) {
- substMap.Add(procOutVar, ie);
- }
- }
-
- Hashtable /*Variable -> Expr*/ substMapOld = new Hashtable/*Variable -> Expr*/();
-
- foreach (IdentifierExpr! mie in proc.Modifies) {
- Variable! mVar = (!) mie.Decl;
- LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type));
- newLocalVars.Add(localVar);
- IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar);
- substMapOld.Add(mVar, ie);
- // FIXME why are we doing this? the modifies list should already include them.
- // add the modified variable to the modifies list of the procedure
- if(!newModifies.Has(mie)) {
- newModifies.Add(mie);
- }
- }
-
- codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap);
- codeCopier.OldSubst = Substituter.SubstitutionFromHashtable(substMapOld);
- }
-
- protected void EndInline() {
- codeCopier.Subst = null;
- codeCopier.OldSubst = null;
- }
-
-
- // result[0] is the entry block
- protected List<Block!>! CreateInlinedBlocks(CallCmd! callCmd, Procedure! proc, Implementation! impl, string! nextBlockLabel)
- requires (codeCopier.Subst != null);
- requires (codeCopier.OldSubst != null);
- {
-
- List<Block!>! implBlocks = (!)impl.OriginalBlocks;
- assert (implBlocks.Count > 0);
-
- string startLabel = implBlocks[0].Label;
-
- List<Block!>! inlinedBlocks = new List<Block!>();
-
- // create in block
- CmdSeq inCmds = new CmdSeq();
-
- // assign in parameters
- for(int i = 0; i < impl.InParams.Length; ++i) {
- Cmd cmd = Cmd.SimpleAssign(impl.tok,
- (IdentifierExpr) (!) codeCopier.Subst( (!)impl.InParams[i]),
- (!)callCmd.Ins[i]);
- inCmds.Add(cmd);
- }
-
- // inject non-free requires
- for (int i = 0; i < proc.Requires.Length; i++) {
- Requires! req = (!) proc.Requires[i];
- if (!req.Free) {
- Requires! reqCopy = (Requires!) req.Clone();
- reqCopy.Condition = codeCopier.CopyExpr(req.Condition);
- AssertCmd! a = new AssertRequiresCmd(callCmd, reqCopy);
- a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
- inCmds.Add(a);
- }
- }
-
- VariableSeq locVars = (!)impl.OriginalLocVars;
-
- // add where clauses of local vars as assume
- for(int i = 0; i < locVars.Length; ++i) {
- Expr whereExpr = ((!)locVars[i]).TypedIdent.WhereExpr;
- if(whereExpr != null) {
- whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
- // FIXME we cannot overwrite it, can we?!
- ((!)locVars[i]).TypedIdent.WhereExpr = whereExpr;
- AssumeCmd! a = new AssumeCmd(Token.NoToken, whereExpr);
- inCmds.Add(a);
- }
- }
-
- // add where clauses of output params as assume
- for(int i = 0; i < impl.OutParams.Length; ++i) {
- Expr whereExpr = ((!)impl.OutParams[i]).TypedIdent.WhereExpr;
- if(whereExpr != null) {
- whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
- // FIXME likewise
- ((!)impl.OutParams[i]).TypedIdent.WhereExpr = whereExpr;
- AssumeCmd! a = new AssumeCmd(Token.NoToken, whereExpr);
- inCmds.Add(a);
- }
- }
-
- // assign modifies old values
- foreach (IdentifierExpr! mie in proc.Modifies)
- {
- Variable! mvar = (!) mie.Decl;
- AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr) (!) codeCopier.OldSubst(mvar), mie);
- inCmds.Add(assign);
- }
-
- GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new StringSeq(GetInlinedProcLabel(proc.Name) + "$" + startLabel));
- Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd);
- inlinedBlocks.Add(inBlock);
-
- // inject the blocks of the implementation
- Block intBlock;
- foreach (Block block in implBlocks) {
- CmdSeq copyCmds = codeCopier.CopyCmdSeq(block.Cmds);
- TransferCmd transferCmd = CreateInlinedTransferCmd((!) block.TransferCmd, GetInlinedProcLabel(proc.Name));
- intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd);
- inlinedBlocks.Add(intBlock);
- }
-
- // create out block
- CmdSeq outCmds = new CmdSeq();
-
- // inject non-free ensures
- for (int i = 0; i < proc.Ensures.Length; i++) {
- Ensures! ens = (!) proc.Ensures[i];
- if (!ens.Free) {
- Ensures! ensCopy = (Ensures!) ens.Clone();
- ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
- AssertCmd! a = new AssertEnsuresCmd(ensCopy);
- outCmds.Add(a);
- }
- }
-
- // assign out params
- for(int i = 0; i < impl.OutParams.Length; ++i) {
- Expr! cout_exp = (IdentifierExpr) (!) codeCopier.Subst((!)impl.OutParams[i]);
- Cmd cmd = Cmd.SimpleAssign(impl.tok, (!)callCmd.Outs[i], cout_exp);
- outCmds.Add(cmd);
- }
-
- // create out block
- GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new StringSeq(nextBlockLabel));
- Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd);
- inlinedBlocks.Add(outBlock);
-
- return inlinedBlocks;
- }
-
- protected TransferCmd CreateInlinedTransferCmd(TransferCmd! transferCmd, string! procLabel) {
- TransferCmd newTransferCmd;
-
- GotoCmd gotoCmd = transferCmd as GotoCmd;
- if(gotoCmd != null) {
- StringSeq gotoSeq = gotoCmd.labelNames;
- StringSeq newGotoSeq = new StringSeq();
- foreach(string! blockLabel in (!) gotoSeq) {
- newGotoSeq.Add(procLabel + "$" + blockLabel);
- }
- newTransferCmd = new GotoCmd(transferCmd.tok, newGotoSeq);
- } else {
- newTransferCmd = new GotoCmd(transferCmd.tok, new StringSeq(procLabel + "$Return"));
- }
-
- return newTransferCmd;
- }
-
- protected static bool FindProcImpl(Program! program, string! procName, out Procedure outProc, out Implementation outImpl)
- {
- // this assumes that there is at most one procedure and only one associated implementation in the current context
-
- foreach(Declaration decl in program.TopLevelDeclarations) {
- Implementation impl = decl as Implementation;
- if(impl != null) {
- if(impl.Name.Equals(procName)) {
- assert(impl.Proc != null);
- outProc = impl.Proc;
- outImpl = impl;
- return true;
- }
- }
- }
-
- foreach(Declaration decl in program.TopLevelDeclarations) {
- Procedure proc = decl as Procedure;
- if(proc != null) {
- if(proc.Name.Equals(procName)) {
- outProc = proc;
- outImpl = null;
- return false;
- }
- }
- }
-
- outProc = null;
- outImpl = null;
- return false;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- public class CodeCopier
- {
- public Substitution Subst;
- public Substitution OldSubst;
-
- public CodeCopier(Hashtable! substMap) {
- Subst = Substituter.SubstitutionFromHashtable(substMap);
- }
-
- public CodeCopier(Hashtable! substMap, Hashtable! oldSubstMap) {
- Subst = Substituter.SubstitutionFromHashtable(substMap);
- OldSubst = Substituter.SubstitutionFromHashtable(oldSubstMap);
- }
-
- public CodeCopier() {
- }
-
- public CmdSeq! CopyCmdSeq(CmdSeq! cmds) {
- CmdSeq newCmds = new CmdSeq();
- foreach (Cmd! cmd in cmds) {
- newCmds.Add(CopyCmd(cmd));
- }
- return newCmds;
- }
-
- public TransferCmd! CopyTransferCmd(TransferCmd! cmd) {
- TransferCmd transferCmd;
- GotoCmd gotocmd = cmd as GotoCmd;
- if(gotocmd != null) {
- assert(gotocmd.labelNames != null);
- StringSeq labels = new StringSeq();
- labels.AddRange(gotocmd.labelNames);
- transferCmd = new GotoCmd(cmd.tok, labels);
- } else {
- transferCmd = new ReturnCmd(cmd.tok);
- }
- return transferCmd;
- }
-
- public Cmd! CopyCmd(Cmd! cmd) {
- if (Subst == null) {
- return cmd;
- } else if (OldSubst == null) {
- return Substituter.Apply(Subst, cmd);
- } else {
- return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, cmd);
- }
- }
-
- public Expr! CopyExpr(Expr! expr) {
- if (Subst == null) {
- return expr;
- } else if (OldSubst == null) {
- return Substituter.Apply(Subst, expr);
- } else {
- return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, expr);
- }
- }
- } // end class CodeCopier
-
-
- public class AxiomExpander : Duplicator
- {
- readonly Program! program;
- readonly TypecheckingContext! tc;
-
- public AxiomExpander(Program! prog, TypecheckingContext! t)
- {
- program = prog;
- tc = t;
- }
-
- public void CollectExpansions()
- {
- foreach (Declaration! decl in program.TopLevelDeclarations) {
- Axiom ax = decl as Axiom;
- if (ax != null) {
- bool expand = false;
- if (!ax.CheckBooleanAttribute("inline", ref expand)) {
- Error(decl.tok, "{:inline ...} expects either true or false as the argument");
- }
- if (expand) {
- AddExpansion(ax.Expr, ax.FindStringAttribute("ignore"));
- }
- }
- Function f = decl as Function;
- if (f != null && f.Body != null) {
- Variable[]! formals = new Variable [f.InParams.Length];
- for (int i = 0; i < formals.Length; ++i)
- formals[i] = f.InParams[i];
- AddExpansion(f, new Expansion(null, f.Body,
- new TypeVariableSeq (f.TypeParameters),
- formals));
- }
- }
- }
-
- void Error(IToken! tok, string msg)
- {
- tc.Error(tok, "expansion: " + msg);
- }
-
- void AddExpansion(Expr! axiomBody, string? ignore)
- {
- // it would be sooooooooo much easier with pattern matching
- ForallExpr all = axiomBody as ForallExpr;
- if (all != null) {
- NAryExpr nary = all.Body as NAryExpr;
- BinaryOperator bin = nary == null ? null : nary.Fun as BinaryOperator;
- //System.Console.WriteLine("{0} {1} {2}", nary==null, bin==null, bin==null?0 : bin.Op);
- if (nary != null && bin != null && (bin.Op == BinaryOperator.Opcode.Eq || bin.Op == BinaryOperator.Opcode.Iff)) {
- NAryExpr? func = nary.Args[0] as NAryExpr;
- //System.Console.WriteLine("{0} {1}", func == null, func == null ? null : func.Fun.GetType());
- while (func != null && func.Fun is TypeCoercion)
- func = func.Args[0] as NAryExpr;
- if (func != null && func.Fun is FunctionCall) {
- Function fn = (!)((FunctionCall)func.Fun).Func;
- Expansion exp = new Expansion(ignore, (!)nary.Args[1],
- new TypeVariableSeq (),
- new Variable[func.Args.Length]);
- int pos = 0;
- Dictionary<Declaration, bool> parms = new Dictionary<Declaration, bool>();
- foreach (Expr! e in func.Args) {
- IdentifierExpr id = e as IdentifierExpr;
- if (id == null) {
- Error(e.tok, "only identifiers supported as function arguments");
- return;
- }
- exp.formals[pos++] = id.Decl;
- if (parms.ContainsKey(id.Decl)) {
- Error(all.tok, "an identifier was used more than once");
- return;
- }
- parms[id.Decl] = true;
- if (!all.Dummies.Has(id.Decl)) {
- Error(all.tok, "identifier was not quantified over");
- return;
- }
- }
- if (func.Args.Length != all.Dummies.Length) {
- Error(all.tok, "more variables quantified over, than used in function");
- return;
- }
-
- Dictionary<TypeVariable!, bool> typeVars = new Dictionary<TypeVariable!, bool>();
- foreach (TypeVariable! v in ((!)func.TypeParameters).FormalTypeParams) {
- if (!func.TypeParameters[v].IsVariable) {
- Error(all.tok, "only identifiers supported as type parameters");
- return;
- }
- TypeVariable! formal = func.TypeParameters[v].AsVariable;
- exp.TypeParameters.Add(formal);
- if (typeVars.ContainsKey(formal)) {
- Error(all.tok, "an identifier was used more than once");
- return;
- }
- typeVars[formal] = true;
- if (!all.TypeParameters.Has(formal)) {
- Error(all.tok, "identifier was not quantified over");
- return;
- }
- }
- if (((FunctionCall)func.Fun).Func.TypeParameters.Length != all.TypeParameters.Length) {
- Error(all.tok, "more variables quantified over, than used in function");
- return;
- }
- AddExpansion(fn, exp);
- return;
- }
- }
- }
-
- Error(axiomBody.tok, "axiom to be expanded must have form (forall VARS :: f(VARS) == expr(VARS))");
- }
-
- void AddExpansion(Function! fn, Expansion! x) {
- if (fn.expansions == null) {
- fn.expansions = new List<Expansion!>();
- }
- fn.expansions.Add(x);
- }
- }
-} // end namespace
-
diff --git a/Source/Core/LambdaHelper.ssc b/Source/Core/LambdaHelper.ssc
deleted file mode 100644
index 83b66ce0..00000000
--- a/Source/Core/LambdaHelper.ssc
+++ /dev/null
@@ -1,161 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie {
-
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
-
- public static class LambdaHelper
- {
- public static Absy! Desugar(Absy! node, out List<Expr!>! axioms, out List<Function!>! functions)
- {
- LambdaVisitor v = new LambdaVisitor();
- node = v.Visit(node);
- axioms = v.lambdaAxioms;
- functions = v.lambdaFunctions;
- if (CommandLineOptions.Clo.TraceVerify) {
- Console.WriteLine("Desugaring of lambda expressions produced {0} functions and {1} axioms:", functions.Count, axioms.Count);
- TokenTextWriter wr = new TokenTextWriter("<console>", Console.Out);
- foreach (Function f in functions) {
- f.Emit(wr, 0);
- }
- foreach (Expr ax in axioms) {
- ax.Emit(wr);
- Console.WriteLine();
- }
- }
- return node;
- }
-
- public static void ExpandLambdas(Program! prog)
- {
- List<Expr!>! axioms;
- List<Function!>! functions;
- Desugar(prog, out axioms, out functions);
- foreach (var f in functions) {
- prog.TopLevelDeclarations.Add(f);
- }
- foreach (var a in axioms) {
- prog.TopLevelDeclarations.Add(new Axiom(a.tok, a));
- }
- }
-
- private class LambdaVisitor : StandardVisitor
- {
- internal List<Expr!>! lambdaAxioms = new List<Expr!>();
- internal List<Function!>! lambdaFunctions = new List<Function!>();
- static int lambdaid = 0;
-
- public override Program! VisitProgram(Program! prog)
- {
- foreach (Declaration! decl in prog.TopLevelDeclarations) {
- if (decl is Axiom || decl is Function) {
- this.Visit(decl);
- }
- }
-
- return prog;
- }
-
- public override Procedure! VisitProcedure(Procedure! node)
- {
- // do not visit requires/ensures when calling this on Implementation
- return node;
- }
-
- public override Absy! Visit(Absy! node)
- {
- node = base.Visit(node);
-
- LambdaExpr lambda = node as LambdaExpr;
- if (lambda != null) {
- IToken! tok = lambda.tok;
-
- Set freeVars = new Set();
- lambda.ComputeFreeVariables(freeVars);
- // this is ugly, the output will depend on hashing order
- Hashtable subst = new Hashtable();
- VariableSeq formals = new VariableSeq();
- ExprSeq callArgs = new ExprSeq();
- ExprSeq axCallArgs = new ExprSeq();
- VariableSeq dummies = new VariableSeq(lambda.Dummies);
- TypeVariableSeq freeTypeVars = new TypeVariableSeq();
- List<Type!> fnTypeVarActuals = new List<Type!>();
- TypeVariableSeq freshTypeVars = new TypeVariableSeq(); // these are only used in the lambda@n function's definition
- foreach (object o in freeVars) {
- // 'o' is either a Variable or a TypeVariable. Since the lambda desugaring happens only
- // at the outermost level of a program (where there are no mutable variables) and, for
- // procedure bodies, after the statements have been passified (when mutable variables have
- // been replaced by immutable incarnations), we are interested only in BoundVar's and
- // TypeVariable's.
- BoundVariable v = o as BoundVariable;
- if (v != null) {
- TypedIdent ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type);
- Formal f = new Formal(v.tok, ti, true);
- formals.Add(f);
- BoundVariable b = new BoundVariable(v.tok, ti);
- dummies.Add(b);
- callArgs.Add(new IdentifierExpr(v.tok, v));
- Expr! id = new IdentifierExpr(f.tok, b);
- subst.Add(v, id);
- axCallArgs.Add(id);
- } else if (o is TypeVariable) {
- TypeVariable tv = (TypeVariable)o;
- freeTypeVars.Add(tv);
- fnTypeVarActuals.Add(tv);
- freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name));
- }
- }
-
- Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, (!)lambda.Type), false);
- Function fn = new Function(tok, "lambda@" + lambdaid++, freshTypeVars, formals, res, "auto-generated lambda function", lambda.Attributes);
- lambdaFunctions.Add(fn);
-
- FunctionCall fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name));
- fcall.Func = fn; // resolve here
-
- List<Expr!> selectArgs = new List<Expr!>();
- foreach (Variable! v in lambda.Dummies) {
- selectArgs.Add(new IdentifierExpr(v.tok, v));
- }
- NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs);
- axcall.Type = res.TypedIdent.Type;
- axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
- NAryExpr select = Expr.Select(axcall, selectArgs);
- select.Type = lambda.Body.Type;
- List<Type!> selectTypeParamActuals = new List<Type!>();
- TypeVariableSeq forallTypeVariables = new TypeVariableSeq();
- foreach (TypeVariable! tp in lambda.TypeParameters) {
- selectTypeParamActuals.Add(tp);
- forallTypeVariables.Add(tp);
- }
- forallTypeVariables.AddRange(freeTypeVars);
- select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals);
-
- Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambda.Body);
- NAryExpr body = Expr.Eq(select, bb);
- body.Type = Type.Bool;
- body.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
- Trigger trig = new Trigger(select.tok, true, new ExprSeq(select));
- lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, lambda.Attributes, trig, body));
-
- NAryExpr call = new NAryExpr(tok, fcall, callArgs);
- call.Type = res.TypedIdent.Type;
- call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals);
-
- return call;
- }
-
- return node;
- }
- }
- }
-
-} // end namespace
-
diff --git a/Source/Core/LoopUnroll.ssc b/Source/Core/LoopUnroll.ssc
deleted file mode 100644
index 68bc8847..00000000
--- a/Source/Core/LoopUnroll.ssc
+++ /dev/null
@@ -1,224 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using Microsoft.Contracts;
-using System.Collections.Generic;
-using Cci = System.Compiler;
-using Bpl = Microsoft.Boogie;
-
-namespace Microsoft.Boogie
-{
- public class LoopUnroll {
- public static List<Block!>! UnrollLoops(Block! start, int unrollMaxDepth)
- requires 0 <= unrollMaxDepth;
- {
- Dictionary<Block,GraphNode!> gd = new Dictionary<Block,GraphNode!>();
- Cci.HashSet/*Block*/! beingVisited = new Cci.HashSet/*Block*/();
- GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);
-
- // Compute SCCs
- StronglyConnectedComponents<GraphNode!> sccs =
- new StronglyConnectedComponents<GraphNode!>(gd.Values, Preds, Succs);
- sccs.Compute();
- Dictionary<GraphNode!, SCC<GraphNode!>> containingSCC = new Dictionary<GraphNode!, SCC<GraphNode!>>();
- foreach (SCC<GraphNode!> scc in sccs)
- {
- foreach (GraphNode! n in scc)
- {
- containingSCC[n] = scc;
- }
- }
-
- LoopUnroll lu = new LoopUnroll(unrollMaxDepth, containingSCC, new List<Block!>());
- lu.Visit(gStart);
- lu.newBlockSeqGlobal.Reverse();
- return lu.newBlockSeqGlobal;
- }
-
- private static System.Collections.IEnumerable/*<GraphNode!>*/! Succs(GraphNode! n)
- {
- List<GraphNode!>! AllEdges = new List<GraphNode!>();
- AllEdges.AddRange(n.ForwardEdges);
- AllEdges.AddRange(n.BackEdges);
- return AllEdges;
- }
- private static System.Collections.IEnumerable/*<GraphNode!>*/! Preds(GraphNode! n)
- {
- return n.Predecessors;
- }
-
- class GraphNode {
- public readonly Block! Block;
- public readonly CmdSeq! Body;
- bool isCutPoint; // is set during ComputeGraphInfo
- public bool IsCutPoint { get { return isCutPoint; } }
- [Rep] public readonly List<GraphNode!>! ForwardEdges = new List<GraphNode!>();
- [Rep] public readonly List<GraphNode!>! BackEdges = new List<GraphNode!>();
- [Rep] public readonly List<GraphNode!>! Predecessors = new List<GraphNode!>();
- invariant isCutPoint <==> BackEdges.Count != 0;
-
- GraphNode(Block! b, CmdSeq! body) {
- this.Block = b;
- this.Body = body;
- }
-
- static CmdSeq! GetOptimizedBody(CmdSeq! cmds) {
- int n = 0;
- foreach (Cmd c in cmds) {
- n++;
- PredicateCmd pc = c as PredicateCmd;
- if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse) {
- // return a sequence consisting of the commands seen so far
- Cmd[] s = new Cmd[n];
- for (int i = 0; i < n; i++) {
- s[i] = cmds[i];
- }
- return new CmdSeq(s);
- }
- }
- return cmds;
- }
-
- public static GraphNode! ComputeGraphInfo(GraphNode from, Block! b, Dictionary<Block,GraphNode!>! gd, Cci.HashSet/*Block*/! beingVisited) {
- GraphNode g;
- if (gd.TryGetValue(b, out g)) {
- assume from != null;
- assert g != null;
- if (beingVisited.Contains(b)) {
- // it's a cut point
- g.isCutPoint = true;
- from.BackEdges.Add(g);
- g.Predecessors.Add(from);
- } else {
- from.ForwardEdges.Add(g);
- g.Predecessors.Add(from);
- }
-
- } else {
- CmdSeq body = GetOptimizedBody(b.Cmds);
- g = new GraphNode(b, body);
- gd.Add(b, g);
- if (from != null) {
- from.ForwardEdges.Add(g);
- g.Predecessors.Add(from);
- }
-
- if (body != b.Cmds) {
- // the body was optimized -- there is no way through this block
- } else {
- beingVisited.Add(b);
-
- GotoCmd gcmd = b.TransferCmd as GotoCmd;
- if (gcmd != null) {
- assume gcmd.labelTargets != null;
- foreach (Block! succ in gcmd.labelTargets) {
- ComputeGraphInfo(g, succ, gd, beingVisited);
- }
- }
-
- beingVisited.Remove(b);
- }
- }
- return g;
- }
- }
-
- readonly List<Block!>! newBlockSeqGlobal;
- readonly Dictionary<GraphNode!, SCC<GraphNode!>>! containingSCC;
- readonly int c;
- readonly LoopUnroll next;
- readonly LoopUnroll head;
- invariant head != null;
- Dictionary<Block,Block!>! newBlocks = new Dictionary<Block,Block!>();
-
- [NotDelayed]
- private LoopUnroll(int unrollMaxDepth, Dictionary<GraphNode!, SCC<GraphNode!>>! scc, List<Block!>! newBlockSeqGlobal)
- requires 0 <= unrollMaxDepth;
- {
- this.newBlockSeqGlobal = newBlockSeqGlobal;
- this.c = unrollMaxDepth;
- this.containingSCC = scc;
- base();
- this.head = this;
- if (unrollMaxDepth != 0) {
- next = new LoopUnroll(unrollMaxDepth - 1, scc, newBlockSeqGlobal, this);
- }
- }
-
- private LoopUnroll(int unrollMaxDepth, Dictionary<GraphNode!, SCC<GraphNode!>>! scc, List<Block!>! newBlockSeqGlobal, LoopUnroll! head)
- requires 0 <= unrollMaxDepth;
- {
- this.newBlockSeqGlobal = newBlockSeqGlobal;
- this.c = unrollMaxDepth;
- this.containingSCC = scc;
- this.head = head;
- if (unrollMaxDepth != 0) {
- next = new LoopUnroll(unrollMaxDepth - 1, scc, newBlockSeqGlobal, head);
- }
- }
-
- Block! Visit(GraphNode! node) {
- Block orig = node.Block;
- Block nw;
- if (newBlocks.TryGetValue(orig, out nw)) {
- assert nw != null;
-
- } else {
- CmdSeq body;
- TransferCmd tcmd;
- assert orig.TransferCmd != null;
-
- if (next == null && node.IsCutPoint) {
- // as the body, use the assert/assume commands that make up the loop invariant
- body = new CmdSeq();
- foreach (Cmd! c in node.Body) {
- if (c is PredicateCmd || c is CommentCmd) {
- body.Add(c);
- } else {
- break;
- }
- }
- body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False));
-
- tcmd = new ReturnCmd(orig.TransferCmd.tok);
-
- } else {
- body = node.Body;
- BlockSeq newSuccs = new BlockSeq();
-
- foreach (GraphNode succ in node.ForwardEdges) {
- Block s;
- if (containingSCC[node] == containingSCC[succ]) {
- s = Visit(succ);
- } else {
- assert head != null; // follows from object invariant
- s = head.Visit(succ);
- }
- newSuccs.Add(s);
- }
-
- assert next == null ==> node.BackEdges.Count == 0; // follows from if-else test above and the GraphNode invariant
- foreach (GraphNode succ in node.BackEdges) {
- assert next != null; // since if we get here, node.BackEdges.Count != 0
- Block s = next.Visit(succ);
- newSuccs.Add(s);
- }
-
- if (newSuccs.Length == 0) {
- tcmd = new ReturnCmd(orig.TransferCmd.tok);
- } else {
- tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs);
- }
- }
-
- nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd);
- newBlocks.Add(orig, nw);
- newBlockSeqGlobal.Add(nw);
- }
-
- return nw;
- }
- }
-}
diff --git a/Source/Core/OOLongUtil.ssc b/Source/Core/OOLongUtil.ssc
deleted file mode 100644
index e87666f3..00000000
--- a/Source/Core/OOLongUtil.ssc
+++ /dev/null
@@ -1,174 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Microsoft.Contracts;
-
-namespace Boogie.Util {
- public class TeeWriter : TextWriter {
- readonly TextWriter! a;
- readonly TextWriter! b;
-
- public TeeWriter(TextWriter! a, TextWriter! b) {
- this.a = a;
- this.b = b;
- }
-
- public override System.Text.Encoding Encoding {
- get {
- return a.Encoding;
- }
- }
-
- public override void Close() {
- a.Close();
- b.Close();
- }
-
- public override void Flush() {
- a.Flush();
- b.Flush();
- }
-
- [Pure]
- public override string! ToString() {
- return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
- }
-
- public override void Write(char ch) {
- a.Write(ch);
- b.Write(ch);
- }
-
- public override void Write(string s) {
- a.Write(s);
- b.Write(s);
- }
- }
-
- /// <summary>
- /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
- /// It simply reads from the given "reader".
- /// </summary>
- public class LineReader : TextReader {
- [Rep] readonly TextReader! reader;
- string readAhead;
- int readAheadConsumed;
- invariant readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length);
-
- public LineReader([Captured] TextReader! reader) {
- this.reader = reader;
- }
- public override void Close() {
- expose (this) {
- reader.Close();
- }
- }
- public override int Read() {
- expose (this) {
- while (readAhead == null) {
- readAhead = reader.ReadLine();
- if (readAhead == null) {
- // we're at EOF
- return -1;
- } else if (readAhead.Length > 0) {
- readAheadConsumed = 0;
- break;
- }
- }
- int res = readAhead[readAheadConsumed++];
- if (readAheadConsumed == readAhead.Length) {
- readAhead = null;
- }
- return res;
- }
- }
- public override int Read(char[]! buffer, int index, int count) {
- int n = 0;
- for (; n < count; n++) {
- int ch = Read();
- if (ch == -1) {
- break;
- }
- buffer[index + n] = (char)ch;
- }
- return n;
- }
- public override string ReadLine() {
- string res;
- if (readAhead != null) {
- expose (this) {
- res = readAhead.Substring(readAheadConsumed);
- readAhead = null;
- }
- } else {
- res = reader.ReadLine();
- }
- return res;
- }
- }
-
- public class IfdefReader : LineReader {
- [Rep] readonly List<string!>! defines;
- [Rep] readonly List<bool>! readState = new List<bool>();
- int ignoreCutoff = 0; // 0 means we're not ignoring
- invariant 0 <= ignoreCutoff && ignoreCutoff <= readState.Count;
-
- public IfdefReader([Captured] TextReader! reader, [Captured] List<string!>! defines) {
- base(reader);
- this.defines = defines;
- }
-
- public override string ReadLine() {
- while (true) {
- string s = base.ReadLine();
- if (s == null) {
- return s;
- }
- string t = s.Trim();
- if (t.StartsWith("#if")) {
- string arg = t.Substring(3).TrimStart();
- bool sense = true;
- while (t.StartsWith("!")) {
- sense = !sense;
- t = t.Substring(1).TrimStart();
- }
- // push "true", since we're in a "then" branch
- readState.Add(true);
- if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
- ignoreCutoff = readState.Count; // start ignoring
- }
- } else if (t == "#else") {
- if (readState.Count == 0 || !readState[readState.Count-1]) {
- return s; // malformed input; return the read line as if it were not special
- }
- // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
- readState[readState.Count-1] = false;
- if (ignoreCutoff == 0) {
- // the "then" branch had been included, so we'll ignore the "else" branch
- ignoreCutoff = readState.Count;
- } else if (ignoreCutoff == readState.Count) {
- // we had ignored the "then" branch, so we'll include the "else" branch
- ignoreCutoff = 0;
- }
- } else if (t == "#endif") {
- if (readState.Count == 0) {
- return s; // malformed input; return the read line as if it were not special
- }
- if (ignoreCutoff == readState.Count) {
- // we had ignored the branch that ends here; so, now we start including again
- ignoreCutoff = 0;
- }
- // pop
- readState.RemoveAt(readState.Count-1);
- } else if (ignoreCutoff == 0) {
- return s;
- }
- }
- }
- }
-}
diff --git a/Source/Core/Parser.ssc b/Source/Core/Parser.ssc
deleted file mode 100644
index 86f792bb..00000000
--- a/Source/Core/Parser.ssc
+++ /dev/null
@@ -1,2168 +0,0 @@
-using PureCollections;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using Bpl = Microsoft.Boogie;
-using AI = Microsoft.AbstractInterpretationFramework;
-
-
-
-
-using System;
-using Microsoft.Contracts;
-
-namespace Microsoft.Boogie {
-
-
-
-public class Parser {
- public const int _EOF = 0;
- public const int _ident = 1;
- public const int _bvlit = 2;
- public const int _digits = 3;
- public const int _string = 4;
- public const int _float = 5;
- public const int maxT = 88;
-
- const bool T = true;
- const bool x = false;
- const int minErrDist = 2;
-
- public Scanner/*!*/ scanner;
- public Errors/*!*/ errors;
-
- public Token/*!*/ t; // last recognized token
- public Token/*!*/ la; // lookahead token
- int errDist = minErrDist;
-
-static Program! Pgm = new Program();
-
-static Expr! dummyExpr = new LiteralExpr(Token.NoToken, false);
-static Cmd! dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr);
-static Block! dummyBlock = new Block(Token.NoToken, "dummyBlock", new CmdSeq(),
- new ReturnCmd(Token.NoToken));
-static Bpl.Type! dummyType = new BasicType(Token.NoToken, SimpleType.Bool);
-static Bpl.ExprSeq! dummyExprSeq = new ExprSeq ();
-static TransferCmd! dummyTransferCmd = new ReturnCmd(Token.NoToken);
-static StructuredCmd! dummyStructuredCmd = new BreakCmd(Token.NoToken, null);
-
-///<summary>
-///Returns the number of parsing errors encountered. If 0, "program" returns as
-///the parsed program.
-///</summary>
-public static int Parse (string! filename, /*maybe null*/ List<string!> defines, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
-
-
- FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- return Parse(stream, filename, defines, out program);
-}
-
-// Read the program from a stream. This allows the program to be stored in memory.
-public static int Parse (Stream! stream, string! filename, /*maybe null*/ List<string!> defines, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
-
- if (defines == null) {
- defines = new List<string!>();
- }
- string s = ParserHelper.Fill(stream, defines);
- byte[]! buffer = (!) UTF8Encoding.Default.GetBytes(s);
- MemoryStream ms = new MemoryStream(buffer,false);
- Errors errors = new Errors();
- Scanner scanner = new Scanner(ms, errors, filename);
-
- Parser parser = new Parser(scanner, errors);
- Pgm = new Program(); // reset the global variable
- parser.Parse();
- if (parser.errors.count == 0)
- {
- program = Pgm;
- return 0;
- }
- else
- {
- program = null;
- return parser.errors.count;
- }
-}
-
-// Class to represent the bounds of a bitvector expression t[a:b].
-// Objects of this class only exist during parsing and are directly
-// turned into BvExtract before they get anywhere else
-private class BvBounds : Expr {
- public BigNum Lower;
- public BigNum Upper;
- public BvBounds(IToken! tok, BigNum lower, BigNum upper) {
- base(tok);
- this.Lower = lower;
- this.Upper = upper;
- }
- public override Type! ShallowType { get { return Bpl.Type.Int; } }
- public override void Resolve(ResolutionContext! rc) {
- rc.Error(this, "bitvector bounds in illegal position");
- }
- public override void Emit(TokenTextWriter! stream,
- int contextBindingStrength, bool fragileContext) {
- assert false;
- }
- public override void ComputeFreeVariables(Set! freeVars) { assert false; }
- public override AI.IExpr! IExpr { get { assert false; } }
-}
-
-/*--------------------------------------------------------------------------*/
-
-
- public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors) {
- this.scanner = scanner;
- this.errors = errors;
- Token! tok = new Token();
- tok.val = "";
- this.la = tok;
- this.t = new Token(); // just to satisfy its non-null constraint
- }
-
- void SynErr (int n) {
- if (errDist >= minErrDist) errors.SynErr(la.filename, la.line, la.col, n);
- errDist = 0;
- }
-
- public void SemErr (string! msg) {
- if (errDist >= minErrDist) errors.SemErr(t, msg);
- errDist = 0;
- }
-
- public void SemErr(IToken! tok, string! msg) {
- errors.SemErr(tok, msg);
- }
-
- void Get () {
- for (;;) {
- t = la;
- la = scanner.Scan();
- if (la.kind <= maxT) { ++errDist; break; }
-
- la = t;
- }
- }
-
- void Expect (int n) {
- if (la.kind==n) Get(); else { SynErr(n); }
- }
-
- bool StartOf (int s) {
- return set[s, la.kind];
- }
-
- void ExpectWeak (int n, int follow) {
- if (la.kind == n) Get();
- else {
- SynErr(n);
- while (!StartOf(follow)) Get();
- }
- }
-
-
- bool WeakSeparator(int n, int syFol, int repFol) {
- int kind = la.kind;
- if (kind == n) {Get(); return true;}
- else if (StartOf(repFol)) {return false;}
- else {
- SynErr(n);
- while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
- Get();
- kind = la.kind;
- }
- return StartOf(syFol);
- }
- }
-
-
- void BoogiePL() {
- VariableSeq! vs;
- DeclarationSeq! ds;
- Axiom! ax;
- List<Declaration!>! ts;
- Procedure! pr;
- Implementation im;
- Implementation! nnim;
-
- while (StartOf(1)) {
- switch (la.kind) {
- case 19: {
- Consts(out vs);
- foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); }
- break;
- }
- case 23: {
- Function(out ds);
- foreach (Bpl.Declaration! d in ds) { Pgm.TopLevelDeclarations.Add(d); }
- break;
- }
- case 27: {
- Axiom(out ax);
- Pgm.TopLevelDeclarations.Add(ax);
- break;
- }
- case 28: {
- UserDefinedTypes(out ts);
- foreach (Declaration! td in ts) {
- Pgm.TopLevelDeclarations.Add(td);
- }
- break;
- }
- case 6: {
- GlobalVars(out vs);
- foreach (Bpl.Variable! v in vs) { Pgm.TopLevelDeclarations.Add(v); }
- break;
- }
- case 30: {
- Procedure(out pr, out im);
- Pgm.TopLevelDeclarations.Add(pr);
- if (im != null) {
- Pgm.TopLevelDeclarations.Add(im);
- }
-
- break;
- }
- case 31: {
- Implementation(out nnim);
- Pgm.TopLevelDeclarations.Add(nnim);
- break;
- }
- }
- }
- Expect(0);
- }
-
- void Consts(out VariableSeq! ds) {
- IToken! y; TypedIdentSeq! xs;
- ds = new VariableSeq();
- bool u = false; QKeyValue kv = null;
- bool ChildrenComplete = false;
- List<ConstantParent!> Parents = null;
- Expect(19);
- y = t;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- if (la.kind == 20) {
- Get();
- u = true;
- }
- IdsType(out xs);
- if (la.kind == 21) {
- OrderSpec(out ChildrenComplete, out Parents);
- }
- bool makeClone = false;
- foreach(TypedIdent! x in xs) {
-
- // ensure that no sharing is introduced
- List<ConstantParent!> ParentsClone;
- if (makeClone && Parents != null) {
- ParentsClone = new List<ConstantParent!> ();
- foreach (ConstantParent! p in Parents)
- ParentsClone.Add(new ConstantParent (
- new IdentifierExpr (p.Parent.tok, p.Parent.Name),
- p.Unique));
- } else {
- ParentsClone = Parents;
- }
- makeClone = true;
-
- ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
- }
-
- Expect(7);
- }
-
- void Function(out DeclarationSeq! ds) {
- ds = new DeclarationSeq(); IToken! z;
- IToken! typeParamTok;
- TypeVariableSeq! typeParams = new TypeVariableSeq();
- VariableSeq arguments = new VariableSeq();
- TypedIdent! tyd;
- TypedIdent retTyd = null;
- Type! retTy;
- QKeyValue kv = null;
- Expr definition = null;
- Expr! tmp;
-
- Expect(23);
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- Ident(out z);
- if (la.kind == 17) {
- TypeParams(out typeParamTok, out typeParams);
- }
- Expect(8);
- if (StartOf(2)) {
- VarOrType(out tyd);
- arguments.Add(new Formal(tyd.tok, tyd, true));
- while (la.kind == 11) {
- Get();
- VarOrType(out tyd);
- arguments.Add(new Formal(tyd.tok, tyd, true));
- }
- }
- Expect(9);
- if (la.kind == 24) {
- Get();
- Expect(8);
- VarOrType(out tyd);
- Expect(9);
- retTyd = tyd;
- } else if (la.kind == 10) {
- Get();
- Type(out retTy);
- retTyd = new TypedIdent(retTy.tok, "", retTy);
- } else SynErr(89);
- if (la.kind == 25) {
- Get();
- Expression(out tmp);
- definition = tmp;
- Expect(26);
- } else if (la.kind == 7) {
- Get();
- } else SynErr(90);
- if (retTyd == null) {
- // construct a dummy type for the case of syntax error
- tyd = new TypedIdent(t, "", new BasicType(t, SimpleType.Int));
- } else {
- tyd = retTyd;
- }
- Function! func = new Function(z, z.val, typeParams, arguments,
- new Formal(tyd.tok, tyd, false), null, kv);
- ds.Add(func);
- bool allUnnamed = true;
- foreach (Formal! f in arguments) {
- if (f.TypedIdent.Name != "") {
- allUnnamed = false;
- break;
- }
- }
- if (!allUnnamed) {
- Type prevType = null;
- for (int i = arguments.Length - 1; i >= 0; i--) {
- TypedIdent! curr = ((!)arguments[i]).TypedIdent;
- if (curr.Name == "") {
- if (prevType == null) {
- this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
- break;
- }
- Type ty = curr.Type;
- if (ty is UnresolvedTypeIdentifier &&
- ((!)(ty as UnresolvedTypeIdentifier)).Arguments.Length == 0) {
- curr.Name = ((!)(ty as UnresolvedTypeIdentifier)).Name;
- curr.Type = prevType;
- } else {
- this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
- }
- } else {
- prevType = curr.Type;
- }
- }
- }
- if (definition != null) {
- // generate either an axiom or a function body
- if (QKeyValue.FindBoolAttribute(kv, "inline")) {
- func.Body = definition;
- } else {
- VariableSeq dummies = new VariableSeq();
- ExprSeq callArgs = new ExprSeq();
- int i = 0;
- foreach (Formal! f in arguments) {
- string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
- dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
- callArgs.Add(new IdentifierExpr(f.tok, nm));
- i++;
- }
- TypeVariableSeq! quantifiedTypeVars = new TypeVariableSeq ();
- foreach (TypeVariable! t in typeParams)
- quantifiedTypeVars.Add(new TypeVariable (Token.NoToken, t.Name));
-
- Expr call = new NAryExpr(z, new FunctionCall(new IdentifierExpr(z, z.val)), callArgs);
- // specify the type of the function, because it might be that
- // type parameters only occur in the output type
- call = Expr.CoerceType(z, call, (Type)tyd.Type.Clone());
- Expr def = Expr.Eq(call, definition);
- if (quantifiedTypeVars.Length != 0 || dummies.Length != 0) {
- def = new ForallExpr(z, quantifiedTypeVars, dummies,
- kv,
- new Trigger(z, true, new ExprSeq(call), null),
- def);
- }
- ds.Add(new Axiom(z, def, "autogenerated definition axiom", null));
- }
- }
-
- }
-
- void Axiom(out Axiom! m) {
- Expr! e; QKeyValue kv = null;
- Expect(27);
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- IToken! x = t;
- Proposition(out e);
- Expect(7);
- m = new Axiom(x,e, null, kv);
- }
-
- void UserDefinedTypes(out List<Declaration!>! ts) {
- Declaration! decl; QKeyValue kv = null; ts = new List<Declaration!> ();
- Expect(28);
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- UserDefinedType(out decl, kv);
- ts.Add(decl);
- while (la.kind == 11) {
- Get();
- UserDefinedType(out decl, kv);
- ts.Add(decl);
- }
- Expect(7);
- }
-
- void GlobalVars(out VariableSeq! ds) {
- TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq(); QKeyValue kv = null;
- Expect(6);
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- IdsTypeWheres(true, tyds);
- Expect(7);
- foreach(TypedIdent! tyd in tyds) {
- ds.Add(new GlobalVariable(tyd.tok, tyd, kv));
- }
-
- }
-
- void Procedure(out Procedure! proc, out /*maybe null*/ Implementation impl) {
- IToken! x;
- TypeVariableSeq! typeParams;
- VariableSeq! ins, outs;
- RequiresSeq! pre = new RequiresSeq();
- IdentifierExprSeq! mods = new IdentifierExprSeq();
- EnsuresSeq! post = new EnsuresSeq();
-
- VariableSeq! locals = new VariableSeq();
- StmtList! stmtList;
- QKeyValue kv = null;
- impl = null;
-
- Expect(30);
- ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
- if (la.kind == 7) {
- Get();
- while (StartOf(3)) {
- Spec(pre, mods, post);
- }
- } else if (StartOf(4)) {
- while (StartOf(3)) {
- Spec(pre, mods, post);
- }
- ImplBody(out locals, out stmtList);
- impl = new Implementation(x, x.val, typeParams,
- Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, this.errors);
-
- } else SynErr(91);
- proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
- }
-
- void Implementation(out Implementation! impl) {
- IToken! x;
- TypeVariableSeq! typeParams;
- VariableSeq! ins, outs;
- VariableSeq! locals;
- StmtList! stmtList;
- QKeyValue kv;
-
- Expect(31);
- ProcSignature(false, out x, out typeParams, out ins, out outs, out kv);
- ImplBody(out locals, out stmtList);
- impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors);
- }
-
- void Attribute(ref QKeyValue kv) {
- Trigger trig = null;
- AttributeOrTrigger(ref kv, ref trig);
- if (trig != null) this.SemErr("only attributes, not triggers, allowed here");
- }
-
- void IdsTypeWheres(bool allowWhereClauses, TypedIdentSeq! tyds) {
- IdsTypeWhere(allowWhereClauses, tyds);
- while (la.kind == 11) {
- Get();
- IdsTypeWhere(allowWhereClauses, tyds);
- }
- }
-
- void LocalVars(VariableSeq! ds) {
- TypedIdentSeq! tyds = new TypedIdentSeq(); QKeyValue kv = null;
- Expect(6);
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- IdsTypeWheres(true, tyds);
- Expect(7);
- foreach(TypedIdent! tyd in tyds) {
- ds.Add(new LocalVariable(tyd.tok, tyd, kv));
- }
-
- }
-
- void ProcFormals(bool incoming, bool allowWhereClauses, out VariableSeq! ds) {
- TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq();
- Expect(8);
- if (la.kind == 1) {
- IdsTypeWheres(allowWhereClauses, tyds);
- }
- Expect(9);
- foreach (TypedIdent! tyd in tyds) {
- ds.Add(new Formal(tyd.tok, tyd, incoming));
- }
-
- }
-
- void BoundVars(IToken! x, out VariableSeq! ds) {
- TypedIdentSeq! tyds = new TypedIdentSeq(); ds = new VariableSeq();
- IdsTypeWheres(false, tyds);
- foreach (TypedIdent! tyd in tyds) {
- ds.Add(new BoundVariable(tyd.tok, tyd));
- }
-
- }
-
- void IdsType(out TypedIdentSeq! tyds) {
- TokenSeq! ids; Bpl.Type! ty;
- Idents(out ids);
- Expect(10);
- Type(out ty);
- tyds = new TypedIdentSeq();
- foreach (Token! id in ids) {
- tyds.Add(new TypedIdent(id, id.val, ty, null));
- }
-
- }
-
- void Idents(out TokenSeq! xs) {
- IToken! id; xs = new TokenSeq();
- Ident(out id);
- xs.Add(id);
- while (la.kind == 11) {
- Get();
- Ident(out id);
- xs.Add(id);
- }
- }
-
- void Type(out Bpl.Type! ty) {
- IToken! tok; ty = dummyType;
- if (la.kind == 8 || la.kind == 13 || la.kind == 14) {
- TypeAtom(out ty);
- } else if (la.kind == 1) {
- Ident(out tok);
- TypeSeq! args = new TypeSeq ();
- if (StartOf(2)) {
- TypeArgs(args);
- }
- ty = new UnresolvedTypeIdentifier (tok, tok.val, args);
- } else if (la.kind == 15 || la.kind == 17) {
- MapType(out ty);
- } else SynErr(92);
- }
-
- void IdsTypeWhere(bool allowWhereClauses, TypedIdentSeq! tyds) {
- TokenSeq! ids; Bpl.Type! ty; Expr wh = null; Expr! nne;
- Idents(out ids);
- Expect(10);
- Type(out ty);
- if (la.kind == 12) {
- Get();
- Expression(out nne);
- if (allowWhereClauses) {
- wh = nne;
- } else {
- this.SemErr("where clause not allowed here");
- }
-
- }
- foreach (Token! id in ids) {
- tyds.Add(new TypedIdent(id, id.val, ty, wh));
- }
-
- }
-
- void Expression(out Expr! e0) {
- IToken! x; Expr! e1;
- ImpliesExpression(false, out e0);
- while (la.kind == 50 || la.kind == 51) {
- EquivOp();
- x = t;
- ImpliesExpression(false, out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1);
- }
- }
-
- void TypeAtom(out Bpl.Type! ty) {
- ty = dummyType;
- if (la.kind == 13) {
- Get();
- ty = new BasicType(t, SimpleType.Int);
- } else if (la.kind == 14) {
- Get();
- ty = new BasicType(t, SimpleType.Bool);
- } else if (la.kind == 8) {
- Get();
- Type(out ty);
- Expect(9);
- } else SynErr(93);
- }
-
- void Ident(out IToken! x) {
- Expect(1);
- x = t;
- if (x.val.StartsWith("\\"))
- x.val = x.val.Substring(1);
-
- }
-
- void TypeArgs(TypeSeq! ts) {
- IToken! tok; Type! ty;
- if (la.kind == 8 || la.kind == 13 || la.kind == 14) {
- TypeAtom(out ty);
- ts.Add(ty);
- if (StartOf(2)) {
- TypeArgs(ts);
- }
- } else if (la.kind == 1) {
- Ident(out tok);
- TypeSeq! args = new TypeSeq ();
- ts.Add(new UnresolvedTypeIdentifier (tok, tok.val, args));
- if (StartOf(2)) {
- TypeArgs(ts);
- }
- } else if (la.kind == 15 || la.kind == 17) {
- MapType(out ty);
- ts.Add(ty);
- } else SynErr(94);
- }
-
- void MapType(out Bpl.Type! ty) {
- IToken tok = null;
- IToken! nnTok;
- TypeSeq! arguments = new TypeSeq();
- Type! result;
- TypeVariableSeq! typeParameters = new TypeVariableSeq();
-
- if (la.kind == 17) {
- TypeParams(out nnTok, out typeParameters);
- tok = nnTok;
- }
- Expect(15);
- if (tok == null) tok = t;
- if (StartOf(2)) {
- Types(arguments);
- }
- Expect(16);
- Type(out result);
- ty = new MapType(tok, typeParameters, arguments, result);
-
- }
-
- void TypeParams(out IToken! tok, out Bpl.TypeVariableSeq! typeParams) {
- TokenSeq! typeParamToks;
- Expect(17);
- tok = t;
- Idents(out typeParamToks);
- Expect(18);
- typeParams = new TypeVariableSeq ();
- foreach (Token! id in typeParamToks)
- typeParams.Add(new TypeVariable(id, id.val));
-
- }
-
- void Types(TypeSeq! ts) {
- Bpl.Type! ty;
- Type(out ty);
- ts.Add(ty);
- while (la.kind == 11) {
- Get();
- Type(out ty);
- ts.Add(ty);
- }
- }
-
- void OrderSpec(out bool ChildrenComplete, out List<ConstantParent!> Parents) {
- ChildrenComplete = false;
- Parents = null;
- bool u;
- IToken! parent;
- Expect(21);
- Parents = new List<ConstantParent!> ();
- u = false;
- if (la.kind == 1 || la.kind == 20) {
- if (la.kind == 20) {
- Get();
- u = true;
- }
- Ident(out parent);
- Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u));
- while (la.kind == 11) {
- Get();
- u = false;
- if (la.kind == 20) {
- Get();
- u = true;
- }
- Ident(out parent);
- Parents.Add(new ConstantParent (
- new IdentifierExpr(parent, parent.val), u));
- }
- }
- if (la.kind == 22) {
- Get();
- ChildrenComplete = true;
- }
- }
-
- void VarOrType(out TypedIdent! tyd) {
- string! varName = ""; Bpl.Type! ty; IToken! tok;
- Type(out ty);
- tok = ty.tok;
- if (la.kind == 10) {
- Get();
- if (ty is UnresolvedTypeIdentifier &&
- ((!)(ty as UnresolvedTypeIdentifier)).Arguments.Length == 0) {
- varName = ((!)(ty as UnresolvedTypeIdentifier)).Name;
- } else {
- this.SemErr("expected identifier before ':'");
- }
-
- Type(out ty);
- }
- tyd = new TypedIdent(tok, varName, ty);
- }
-
- void Proposition(out Expr! e) {
- Expression(out e);
- }
-
- void UserDefinedType(out Declaration! decl, QKeyValue kv) {
- IToken! id; IToken! id2; TokenSeq! paramTokens = new TokenSeq ();
- Type! body = dummyType; bool synonym = false;
- Ident(out id);
- if (la.kind == 1) {
- WhiteSpaceIdents(out paramTokens);
- }
- if (la.kind == 29) {
- Get();
- Type(out body);
- synonym = true;
- }
- if (synonym) {
- TypeVariableSeq! typeParams = new TypeVariableSeq();
- foreach (Token! t in paramTokens)
- typeParams.Add(new TypeVariable(t, t.val));
- decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
- } else {
- decl = new TypeCtorDecl(id, id.val, paramTokens.Length, kv);
- }
-
- }
-
- void WhiteSpaceIdents(out TokenSeq! xs) {
- IToken! id; xs = new TokenSeq();
- Ident(out id);
- xs.Add(id);
- while (la.kind == 1) {
- Ident(out id);
- xs.Add(id);
- }
- }
-
- void ProcSignature(bool allowWhereClausesOnFormals, out IToken! name, out TypeVariableSeq! typeParams,
-out VariableSeq! ins, out VariableSeq! outs, out QKeyValue kv) {
- IToken! typeParamTok; typeParams = new TypeVariableSeq();
- outs = new VariableSeq(); kv = null;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- Ident(out name);
- if (la.kind == 17) {
- TypeParams(out typeParamTok, out typeParams);
- }
- ProcFormals(true, allowWhereClausesOnFormals, out ins);
- if (la.kind == 24) {
- Get();
- ProcFormals(false, allowWhereClausesOnFormals, out outs);
- }
- }
-
- void Spec(RequiresSeq! pre, IdentifierExprSeq! mods, EnsuresSeq! post) {
- TokenSeq! ms;
- if (la.kind == 32) {
- Get();
- if (la.kind == 1) {
- Idents(out ms);
- foreach (IToken! m in ms) {
- mods.Add(new IdentifierExpr(m, m.val));
- }
-
- }
- Expect(7);
- } else if (la.kind == 33) {
- Get();
- SpecPrePost(true, pre, post);
- } else if (la.kind == 34 || la.kind == 35) {
- SpecPrePost(false, pre, post);
- } else SynErr(95);
- }
-
- void ImplBody(out VariableSeq! locals, out StmtList! stmtList) {
- locals = new VariableSeq();
- Expect(25);
- while (la.kind == 6) {
- LocalVars(locals);
- }
- StmtList(out stmtList);
- }
-
- void SpecPrePost(bool free, RequiresSeq! pre, EnsuresSeq! post) {
- Expr! e; VariableSeq! locals; BlockSeq! blocks; Token tok = null; QKeyValue kv = null;
- if (la.kind == 34) {
- Get();
- tok = t;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- Proposition(out e);
- Expect(7);
- pre.Add(new Requires(tok, free, e, null, kv));
- } else if (la.kind == 35) {
- Get();
- tok = t;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- Proposition(out e);
- Expect(7);
- post.Add(new Ensures(tok, free, e, null, kv));
- } else SynErr(96);
- }
-
- void StmtList(out StmtList! stmtList) {
- List<BigBlock!> bigblocks = new List<BigBlock!>();
- /* built-up state for the current BigBlock: */
- IToken startToken = null; string currentLabel = null;
- CmdSeq cs = null; /* invariant: startToken != null ==> cs != null */
- /* temporary variables: */
- IToken label; Cmd c; BigBlock b;
- StructuredCmd ec = null; StructuredCmd! ecn;
- TransferCmd tc = null; TransferCmd! tcn;
-
- while (StartOf(5)) {
- if (StartOf(6)) {
- LabelOrCmd(out c, out label);
- if (c != null) {
- // LabelOrCmd read a Cmd
- assert label == null;
- if (startToken == null) { startToken = c.tok; cs = new CmdSeq(); }
- assert cs != null;
- cs.Add(c);
- } else {
- // LabelOrCmd read a label
- assert label != null;
- if (startToken != null) {
- assert cs != null;
- // dump the built-up state into a BigBlock
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- cs = null;
- }
- startToken = label;
- currentLabel = label.val;
- cs = new CmdSeq();
- }
-
- } else if (la.kind == 38 || la.kind == 40 || la.kind == 43) {
- StructuredCmd(out ecn);
- ec = ecn;
- if (startToken == null) { startToken = ec.tok; cs = new CmdSeq(); }
- assert cs != null;
- b = new BigBlock(startToken, currentLabel, cs, ec, null);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
-
- } else {
- TransferCmd(out tcn);
- tc = tcn;
- if (startToken == null) { startToken = tc.tok; cs = new CmdSeq(); }
- assert cs != null;
- b = new BigBlock(startToken, currentLabel, cs, null, tc);
- bigblocks.Add(b);
- startToken = null; currentLabel = null; cs = null;
-
- }
- }
- Expect(26);
- IToken! endCurly = t;
- if (startToken == null && bigblocks.Count == 0) {
- startToken = t; cs = new CmdSeq();
- }
- if (startToken != null) {
- assert cs != null;
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- }
-
- stmtList = new StmtList(bigblocks, endCurly);
-
- }
-
- void LabelOrCmd(out Cmd c, out IToken label) {
- IToken! x; Expr! e;
- TokenSeq! xs;
- IdentifierExprSeq ids;
- c = dummyCmd; label = null;
- Cmd! cn;
- QKeyValue kv = null;
-
- if (la.kind == 1) {
- LabelOrAssign(out c, out label);
- } else if (la.kind == 44) {
- Get();
- x = t;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- Proposition(out e);
- c = new AssertCmd(x,e, kv);
- Expect(7);
- } else if (la.kind == 45) {
- Get();
- x = t;
- Proposition(out e);
- c = new AssumeCmd(x,e);
- Expect(7);
- } else if (la.kind == 46) {
- Get();
- x = t;
- Idents(out xs);
- Expect(7);
- ids = new IdentifierExprSeq();
- foreach (IToken! y in xs) {
- ids.Add(new IdentifierExpr(y, y.val));
- }
- c = new HavocCmd(x,ids);
-
- } else if (la.kind == 48) {
- CallCmd(out cn);
- Expect(7);
- c = cn;
- } else SynErr(97);
- }
-
- void StructuredCmd(out StructuredCmd! ec) {
- ec = dummyStructuredCmd; assume ec.IsPeerConsistent;
- IfCmd! ifcmd; WhileCmd! wcmd; BreakCmd! bcmd;
-
- if (la.kind == 38) {
- IfCmd(out ifcmd);
- ec = ifcmd;
- } else if (la.kind == 40) {
- WhileCmd(out wcmd);
- ec = wcmd;
- } else if (la.kind == 43) {
- BreakCmd(out bcmd);
- ec = bcmd;
- } else SynErr(98);
- }
-
- void TransferCmd(out TransferCmd! tc) {
- tc = dummyTransferCmd;
- Token y; TokenSeq! xs;
- StringSeq ss = new StringSeq();
-
- if (la.kind == 36) {
- Get();
- y = t;
- Idents(out xs);
- foreach (IToken! s in xs) { ss.Add(s.val); }
- tc = new GotoCmd(y, ss);
-
- } else if (la.kind == 37) {
- Get();
- tc = new ReturnCmd(t);
- } else SynErr(99);
- Expect(7);
- }
-
- void IfCmd(out IfCmd! ifcmd) {
- IToken! x;
- Expr guard;
- StmtList! thn;
- IfCmd! elseIf; IfCmd elseIfOption = null;
- StmtList! els; StmtList elseOption = null;
-
- Expect(38);
- x = t;
- Guard(out guard);
- Expect(25);
- StmtList(out thn);
- if (la.kind == 39) {
- Get();
- if (la.kind == 38) {
- IfCmd(out elseIf);
- elseIfOption = elseIf;
- } else if (la.kind == 25) {
- Get();
- StmtList(out els);
- elseOption = els;
- } else SynErr(100);
- }
- ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption);
- }
-
- void WhileCmd(out WhileCmd! wcmd) {
- IToken! x; Token z;
- Expr guard; Expr! e; bool isFree;
- List<PredicateCmd!> invariants = new List<PredicateCmd!>();
- StmtList! body;
-
- Expect(40);
- x = t;
- Guard(out guard);
- assume guard == null || Owner.None(guard);
- while (la.kind == 33 || la.kind == 41) {
- isFree = false; z = la/*lookahead token*/;
- if (la.kind == 33) {
- Get();
- isFree = true;
- }
- Expect(41);
- Expression(out e);
- if (isFree) {
- invariants.Add(new AssumeCmd(z, e));
- } else {
- invariants.Add(new AssertCmd(z, e));
- }
-
- Expect(7);
- }
- Expect(25);
- StmtList(out body);
- wcmd = new WhileCmd(x, guard, invariants, body);
- }
-
- void BreakCmd(out BreakCmd! bcmd) {
- IToken! x; IToken! y;
- string breakLabel = null;
-
- Expect(43);
- x = t;
- if (la.kind == 1) {
- Ident(out y);
- breakLabel = y.val;
- }
- Expect(7);
- bcmd = new BreakCmd(x, breakLabel);
- }
-
- void Guard(out Expr e) {
- Expr! ee; e = null;
- Expect(8);
- if (la.kind == 42) {
- Get();
- e = null;
- } else if (StartOf(7)) {
- Expression(out ee);
- e = ee;
- } else SynErr(101);
- Expect(9);
- }
-
- void LabelOrAssign(out Cmd c, out IToken label) {
- IToken! id; IToken! x, y; Expr! e, e0;
- c = dummyCmd; label = null;
- AssignLhs! lhs;
- List<AssignLhs!>! lhss;
- List<Expr!>! rhss;
- List<Expr!>! indexes;
-
- Ident(out id);
- x = t;
- if (la.kind == 10) {
- Get();
- c = null; label = x;
- } else if (la.kind == 11 || la.kind == 15 || la.kind == 47) {
- lhss = new List<AssignLhs!>();
- lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 15) {
- MapAssignIndex(out y, out indexes);
- lhs = new MapAssignLhs(y, lhs, indexes);
- }
- lhss.Add(lhs);
- while (la.kind == 11) {
- Get();
- Ident(out id);
- lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val));
- while (la.kind == 15) {
- MapAssignIndex(out y, out indexes);
- lhs = new MapAssignLhs(y, lhs, indexes);
- }
- lhss.Add(lhs);
- }
- Expect(47);
- x = t; /* use location of := */
- Expression(out e0);
- rhss = new List<Expr!> ();
- rhss.Add(e0);
- while (la.kind == 11) {
- Get();
- Expression(out e0);
- rhss.Add(e0);
- }
- Expect(7);
- c = new AssignCmd(x, lhss, rhss);
- } else SynErr(102);
- }
-
- void CallCmd(out Cmd! c) {
- IToken! x; IToken! first; IToken p;
- List<IdentifierExpr>! ids = new List<IdentifierExpr>();
- List<Expr>! es = new List<Expr>();
- QKeyValue kv = null;
- Expr en; List<Expr> args;
- c = dummyCmd;
-
- Expect(48);
- x = t;
- while (la.kind == 25) {
- Attribute(ref kv);
- }
- if (la.kind == 1) {
- Ident(out first);
- if (la.kind == 8) {
- Get();
- if (StartOf(8)) {
- CallForallArg(out en);
- es.Add(en);
- while (la.kind == 11) {
- Get();
- CallForallArg(out en);
- es.Add(en);
- }
- }
- Expect(9);
- c = new CallCmd(x, first.val, es, ids, kv);
- } else if (la.kind == 11 || la.kind == 47) {
- ids.Add(new IdentifierExpr(first, first.val));
- if (la.kind == 11) {
- Get();
- CallOutIdent(out p);
- if (p==null) {
- ids.Add(null);
- } else {
- ids.Add(new IdentifierExpr(p, p.val));
- }
-
- while (la.kind == 11) {
- Get();
- CallOutIdent(out p);
- if (p==null) {
- ids.Add(null);
- } else {
- ids.Add(new IdentifierExpr(p, p.val));
- }
-
- }
- }
- Expect(47);
- Ident(out first);
- Expect(8);
- if (StartOf(8)) {
- CallForallArg(out en);
- es.Add(en);
- while (la.kind == 11) {
- Get();
- CallForallArg(out en);
- es.Add(en);
- }
- }
- Expect(9);
- c = new CallCmd(x, first.val, es, ids, kv);
- } else SynErr(103);
- } else if (la.kind == 49) {
- Get();
- Ident(out first);
- Expect(8);
- args = new List<Expr>();
- if (StartOf(8)) {
- CallForallArg(out en);
- args.Add(en);
- while (la.kind == 11) {
- Get();
- CallForallArg(out en);
- args.Add(en);
- }
- }
- Expect(9);
- c = new CallForallCmd(x, first.val, args, kv);
- } else if (la.kind == 42) {
- Get();
- ids.Add(null);
- if (la.kind == 11) {
- Get();
- CallOutIdent(out p);
- if (p==null) {
- ids.Add(null);
- } else {
- ids.Add(new IdentifierExpr(p, p.val));
- }
-
- while (la.kind == 11) {
- Get();
- CallOutIdent(out p);
- if (p==null) {
- ids.Add(null);
- } else {
- ids.Add(new IdentifierExpr(p, p.val));
- }
-
- }
- }
- Expect(47);
- Ident(out first);
- Expect(8);
- if (StartOf(8)) {
- CallForallArg(out en);
- es.Add(en);
- while (la.kind == 11) {
- Get();
- CallForallArg(out en);
- es.Add(en);
- }
- }
- Expect(9);
- c = new CallCmd(x, first.val, es, ids, kv);
- } else SynErr(104);
- }
-
- void MapAssignIndex(out IToken! x, out List<Expr!>! indexes) {
- indexes = new List<Expr!> ();
- Expr! e;
-
- Expect(15);
- x = t;
- if (StartOf(7)) {
- Expression(out e);
- indexes.Add(e);
- while (la.kind == 11) {
- Get();
- Expression(out e);
- indexes.Add(e);
- }
- }
- Expect(16);
- }
-
- void CallForallArg(out Expr exprOptional) {
- exprOptional = null;
- Expr! e;
-
- if (la.kind == 42) {
- Get();
- } else if (StartOf(7)) {
- Expression(out e);
- exprOptional = e;
- } else SynErr(105);
- }
-
- void CallOutIdent(out IToken id) {
- id = null;
- IToken! p;
-
- if (la.kind == 42) {
- Get();
- } else if (la.kind == 1) {
- Ident(out p);
- id = p;
- } else SynErr(106);
- }
-
- void Expressions(out ExprSeq! es) {
- Expr! e; es = new ExprSeq();
- Expression(out e);
- es.Add(e);
- while (la.kind == 11) {
- Get();
- Expression(out e);
- es.Add(e);
- }
- }
-
- void ImpliesExpression(bool noExplies, out Expr! e0) {
- IToken! x; Expr! e1;
- LogicalExpression(out e0);
- if (StartOf(9)) {
- if (la.kind == 52 || la.kind == 53) {
- ImpliesOp();
- x = t;
- ImpliesExpression(true, out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1);
- } else {
- ExpliesOp();
- if (noExplies)
- this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
- x = t;
- LogicalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
- while (la.kind == 54 || la.kind == 55) {
- ExpliesOp();
- x = t;
- LogicalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0);
- }
- }
- }
- }
-
- void EquivOp() {
- if (la.kind == 50) {
- Get();
- } else if (la.kind == 51) {
- Get();
- } else SynErr(107);
- }
-
- void LogicalExpression(out Expr! e0) {
- IToken! x; Expr! e1; BinaryOperator.Opcode op;
- RelationalExpression(out e0);
- if (StartOf(10)) {
- if (la.kind == 56 || la.kind == 57) {
- AndOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
- while (la.kind == 56 || la.kind == 57) {
- AndOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1);
- }
- } else {
- OrOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
- while (la.kind == 58 || la.kind == 59) {
- OrOp();
- x = t;
- RelationalExpression(out e1);
- e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1);
- }
- }
- }
- }
-
- void ImpliesOp() {
- if (la.kind == 52) {
- Get();
- } else if (la.kind == 53) {
- Get();
- } else SynErr(108);
- }
-
- void ExpliesOp() {
- if (la.kind == 54) {
- Get();
- } else if (la.kind == 55) {
- Get();
- } else SynErr(109);
- }
-
- void RelationalExpression(out Expr! e0) {
- IToken! x; Expr! e1; BinaryOperator.Opcode op;
- BvTerm(out e0);
- if (StartOf(11)) {
- RelOp(out x, out op);
- BvTerm(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void AndOp() {
- if (la.kind == 56) {
- Get();
- } else if (la.kind == 57) {
- Get();
- } else SynErr(110);
- }
-
- void OrOp() {
- if (la.kind == 58) {
- Get();
- } else if (la.kind == 59) {
- Get();
- } else SynErr(111);
- }
-
- void BvTerm(out Expr! e0) {
- IToken! x; Expr! e1;
- Term(out e0);
- while (la.kind == 68) {
- Get();
- x = t;
- Term(out e1);
- e0 = new BvConcatExpr(x, e0, e1);
- }
- }
-
- void RelOp(out IToken! x, out BinaryOperator.Opcode op) {
- x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- switch (la.kind) {
- case 60: {
- Get();
- x = t; op=BinaryOperator.Opcode.Eq;
- break;
- }
- case 17: {
- Get();
- x = t; op=BinaryOperator.Opcode.Lt;
- break;
- }
- case 18: {
- Get();
- x = t; op=BinaryOperator.Opcode.Gt;
- break;
- }
- case 61: {
- Get();
- x = t; op=BinaryOperator.Opcode.Le;
- break;
- }
- case 62: {
- Get();
- x = t; op=BinaryOperator.Opcode.Ge;
- break;
- }
- case 63: {
- Get();
- x = t; op=BinaryOperator.Opcode.Neq;
- break;
- }
- case 64: {
- Get();
- x = t; op=BinaryOperator.Opcode.Subtype;
- break;
- }
- case 65: {
- Get();
- x = t; op=BinaryOperator.Opcode.Neq;
- break;
- }
- case 66: {
- Get();
- x = t; op=BinaryOperator.Opcode.Le;
- break;
- }
- case 67: {
- Get();
- x = t; op=BinaryOperator.Opcode.Ge;
- break;
- }
- default: SynErr(112); break;
- }
- }
-
- void Term(out Expr! e0) {
- IToken! x; Expr! e1; BinaryOperator.Opcode op;
- Factor(out e0);
- while (la.kind == 69 || la.kind == 70) {
- AddOp(out x, out op);
- Factor(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void Factor(out Expr! e0) {
- IToken! x; Expr! e1; BinaryOperator.Opcode op;
- UnaryExpression(out e0);
- while (la.kind == 42 || la.kind == 71 || la.kind == 72) {
- MulOp(out x, out op);
- UnaryExpression(out e1);
- e0 = Expr.Binary(x, op, e0, e1);
- }
- }
-
- void AddOp(out IToken! x, out BinaryOperator.Opcode op) {
- x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 69) {
- Get();
- x = t; op=BinaryOperator.Opcode.Add;
- } else if (la.kind == 70) {
- Get();
- x = t; op=BinaryOperator.Opcode.Sub;
- } else SynErr(113);
- }
-
- void UnaryExpression(out Expr! e) {
- IToken! x;
- e = dummyExpr;
-
- if (la.kind == 70) {
- Get();
- x = t;
- UnaryExpression(out e);
- e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e);
- } else if (la.kind == 73 || la.kind == 74) {
- NegOp();
- x = t;
- UnaryExpression(out e);
- e = Expr.Unary(x, UnaryOperator.Opcode.Not, e);
- } else if (StartOf(12)) {
- CoercionExpression(out e);
- } else SynErr(114);
- }
-
- void MulOp(out IToken! x, out BinaryOperator.Opcode op) {
- x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/;
- if (la.kind == 42) {
- Get();
- x = t; op=BinaryOperator.Opcode.Mul;
- } else if (la.kind == 71) {
- Get();
- x = t; op=BinaryOperator.Opcode.Div;
- } else if (la.kind == 72) {
- Get();
- x = t; op=BinaryOperator.Opcode.Mod;
- } else SynErr(115);
- }
-
- void NegOp() {
- if (la.kind == 73) {
- Get();
- } else if (la.kind == 74) {
- Get();
- } else SynErr(116);
- }
-
- void CoercionExpression(out Expr! e) {
- IToken! x;
- Type! coercedTo;
- BigNum bn;
-
- ArrayExpression(out e);
- while (la.kind == 10) {
- Get();
- x = t;
- if (StartOf(2)) {
- Type(out coercedTo);
- e = Expr.CoerceType(x, e, coercedTo);
- } else if (la.kind == 3) {
- Nat(out bn);
- if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
- this.SemErr("arguments of extract need to be integer literals");
- e = new BvBounds(x, bn, BigNum.ZERO);
- } else {
- e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
- }
-
- } else SynErr(117);
- }
- }
-
- void ArrayExpression(out Expr! e) {
- IToken! x;
- Expr! index0 = dummyExpr; Expr! e1;
- bool store; bool bvExtract;
- ExprSeq! allArgs = dummyExprSeq;
-
- AtomExpression(out e);
- while (la.kind == 15) {
- Get();
- x = t; allArgs = new ExprSeq ();
- allArgs.Add(e);
- store = false; bvExtract = false;
- if (StartOf(13)) {
- if (StartOf(7)) {
- Expression(out index0);
- if (index0 is BvBounds)
- bvExtract = true;
- else
- allArgs.Add(index0);
-
- while (la.kind == 11) {
- Get();
- Expression(out e1);
- if (bvExtract || e1 is BvBounds)
- this.SemErr("bitvectors only have one dimension");
- allArgs.Add(e1);
-
- }
- if (la.kind == 47) {
- Get();
- Expression(out e1);
- if (bvExtract || e1 is BvBounds)
- this.SemErr("assignment to bitvectors is not possible");
- allArgs.Add(e1); store = true;
-
- }
- } else {
- Get();
- Expression(out e1);
- allArgs.Add(e1); store = true;
- }
- }
- Expect(16);
- if (store)
- e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
- else if (bvExtract)
- e = new BvExtractExpr(x, e,
- ((BvBounds)index0).Upper.ToIntSafe,
- ((BvBounds)index0).Lower.ToIntSafe);
- else
- e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
-
- }
- }
-
- void Nat(out BigNum n) {
- Expect(3);
- try {
- n = BigNum.FromString(t.val);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigNum.ZERO;
- }
-
- }
-
- void AtomExpression(out Expr! e) {
- IToken! x; int n; BigNum bn;
- ExprSeq! es; VariableSeq! ds; Trigger trig;
- TypeVariableSeq! typeParams;
- IdentifierExpr! id;
- Bpl.Type! ty;
- QKeyValue kv;
- e = dummyExpr;
- VariableSeq! locals;
- List<Block!>! blocks;
-
- switch (la.kind) {
- case 75: {
- Get();
- e = new LiteralExpr(t, false);
- break;
- }
- case 76: {
- Get();
- e = new LiteralExpr(t, true);
- break;
- }
- case 3: {
- Nat(out bn);
- e = new LiteralExpr(t, bn);
- break;
- }
- case 2: {
- BvLit(out bn, out n);
- e = new LiteralExpr(t, bn, n);
- break;
- }
- case 1: {
- Ident(out x);
- id = new IdentifierExpr(x, x.val); e = id;
- if (la.kind == 8) {
- Get();
- if (StartOf(7)) {
- Expressions(out es);
- e = new NAryExpr(x, new FunctionCall(id), es);
- } else if (la.kind == 9) {
- e = new NAryExpr(x, new FunctionCall(id), new ExprSeq());
- } else SynErr(118);
- Expect(9);
- }
- break;
- }
- case 77: {
- Get();
- x = t;
- Expect(8);
- Expression(out e);
- Expect(9);
- e = new OldExpr(x, e);
- break;
- }
- case 8: {
- Get();
- if (StartOf(7)) {
- Expression(out e);
- if (e is BvBounds)
- this.SemErr("parentheses around bitvector bounds " +
- "are not allowed");
- } else if (la.kind == 49 || la.kind == 81) {
- Forall();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (typeParams.Length + ds.Length > 0)
- e = new ForallExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 82 || la.kind == 83) {
- Exists();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (typeParams.Length + ds.Length > 0)
- e = new ExistsExpr(x, typeParams, ds, kv, trig, e);
- } else if (la.kind == 84 || la.kind == 85) {
- Lambda();
- x = t;
- QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e);
- if (trig != null)
- SemErr("triggers not allowed in lambda expressions");
- if (typeParams.Length + ds.Length > 0)
- e = new LambdaExpr(x, typeParams, ds, kv, e);
- } else SynErr(119);
- Expect(9);
- break;
- }
- case 38: {
- IfThenElseExpression(out e);
- break;
- }
- case 78: {
- CodeExpression(out locals, out blocks);
- e = new CodeExpr(locals, blocks);
- break;
- }
- default: SynErr(120); break;
- }
- }
-
- void BvLit(out BigNum n, out int m) {
- Expect(2);
- int pos = t.val.IndexOf("bv");
- string a = t.val.Substring(0, pos);
- string b = t.val.Substring(pos + 2);
- try {
- n = BigNum.FromString(a);
- m = Convert.ToInt32(b);
- } catch (FormatException) {
- this.SemErr("incorrectly formatted bitvector");
- n = BigNum.ZERO;
- m = 0;
- }
-
- }
-
- void Forall() {
- if (la.kind == 49) {
- Get();
- } else if (la.kind == 81) {
- Get();
- } else SynErr(121);
- }
-
- void QuantifierBody(IToken! q, out TypeVariableSeq! typeParams, out VariableSeq! ds,
-out QKeyValue kv, out Trigger trig, out Expr! body) {
- trig = null; typeParams = new TypeVariableSeq ();
- IToken! tok; Expr! e; ExprSeq! es;
- kv = null; string key; string value;
- ds = new VariableSeq ();
-
- if (la.kind == 17) {
- TypeParams(out tok, out typeParams);
- if (la.kind == 1) {
- BoundVars(q, out ds);
- }
- } else if (la.kind == 1) {
- BoundVars(q, out ds);
- } else SynErr(122);
- QSep();
- while (la.kind == 25) {
- AttributeOrTrigger(ref kv, ref trig);
- }
- Expression(out body);
- }
-
- void Exists() {
- if (la.kind == 82) {
- Get();
- } else if (la.kind == 83) {
- Get();
- } else SynErr(123);
- }
-
- void Lambda() {
- if (la.kind == 84) {
- Get();
- } else if (la.kind == 85) {
- Get();
- } else SynErr(124);
- }
-
- void IfThenElseExpression(out Expr! e) {
- IToken! tok;
- Expr! e0, e1, e2;
- e = dummyExpr;
- Expect(38);
- tok = t;
- Expression(out e0);
- Expect(80);
- Expression(out e1);
- Expect(39);
- Expression(out e2);
- e = new NAryExpr(tok, new IfThenElse(tok), new ExprSeq(e0, e1, e2));
- }
-
- void CodeExpression(out VariableSeq! locals, out List<Block!>! blocks) {
- locals = new VariableSeq(); Block! b;
- blocks = new List<Block!>();
-
- Expect(78);
- while (la.kind == 6) {
- LocalVars(locals);
- }
- SpecBlock(out b);
- blocks.Add(b);
- while (la.kind == 1) {
- SpecBlock(out b);
- blocks.Add(b);
- }
- Expect(79);
- }
-
- void SpecBlock(out Block! b) {
- IToken! x; IToken! y;
- Cmd c; IToken label;
- CmdSeq cs = new CmdSeq();
- TokenSeq! xs;
- StringSeq ss = new StringSeq();
- b = dummyBlock;
- Expr! e;
-
- Ident(out x);
- Expect(10);
- while (StartOf(6)) {
- LabelOrCmd(out c, out label);
- if (c != null) {
- assert label == null;
- cs.Add(c);
- } else {
- assert label != null;
- SemErr("SpecBlock's can only have one label");
- }
-
- }
- if (la.kind == 36) {
- Get();
- y = t;
- Idents(out xs);
- foreach (IToken! s in xs) { ss.Add(s.val); }
- b = new Block(x,x.val,cs,new GotoCmd(y,ss));
-
- } else if (la.kind == 37) {
- Get();
- Expression(out e);
- b = new Block(x,x.val,cs,new ReturnExprCmd(t,e));
- } else SynErr(125);
- Expect(7);
- }
-
- void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) {
- IToken! tok; Expr! e; ExprSeq! es;
- string key; string value;
- List<object!> parameters; object! param;
-
- Expect(25);
- tok = t;
- if (la.kind == 10) {
- Get();
- Expect(1);
- key = t.val; parameters = new List<object!>();
- if (StartOf(14)) {
- AttributeParameter(out param);
- parameters.Add(param);
- while (la.kind == 11) {
- Get();
- AttributeParameter(out param);
- parameters.Add(param);
- }
- }
- if (key == "nopats") {
- if (parameters.Count == 1 && parameters[0] is Expr) {
- e = (Expr)parameters[0];
- if(trig==null){
- trig = new Trigger(tok, false, new ExprSeq(e), null);
- } else {
- trig.AddLast(new Trigger(tok, false, new ExprSeq(e), null));
- }
- } else {
- this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
- }
- } else {
- if (kv==null) {
- kv = new QKeyValue(tok, key, parameters, null);
- } else {
- kv.AddLast(new QKeyValue(tok, key, parameters, null));
- }
- }
-
- } else if (StartOf(7)) {
- Expression(out e);
- es = new ExprSeq(e);
- while (la.kind == 11) {
- Get();
- Expression(out e);
- es.Add(e);
- }
- if (trig==null) {
- trig = new Trigger(tok, true, es, null);
- } else {
- trig.AddLast(new Trigger(tok, true, es, null));
- }
-
- } else SynErr(126);
- Expect(26);
- }
-
- void AttributeParameter(out object! o) {
- o = "error";
- Expr! e;
-
- if (la.kind == 4) {
- Get();
- o = t.val.Substring(1, t.val.Length-2);
- } else if (StartOf(7)) {
- Expression(out e);
- o = e;
- } else SynErr(127);
- }
-
- void QSep() {
- if (la.kind == 86) {
- Get();
- } else if (la.kind == 87) {
- Get();
- } else SynErr(128);
- }
-
-
-
- public void Parse() {
- la = new Token();
- la.val = "";
- Get();
- BoogiePL();
-
- Expect(0);
- }
-
- static readonly bool[,]! set = {
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, x,x,x,T, T,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, T,x,x,x, x,T,T,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, T,x,x,T, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,T, T,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x}
-
- };
-} // end Parser
-
-
-public class Errors {
- public int count = 0; // number of errors detected
- public System.IO.TextWriter! errorStream = Console.Out; // error messages go to this stream
-// public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
- public string! errMsgFormat4 = "{0}({1},{2}): Error: {3}"; // 0=line, 1=column, 2=text
- public string! errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-
- public void SynErr (string filename, int line, int col, int n) {
- string s;
- Console.Write("{0}({1},{2}): syntax error: ", filename, line, col);
- switch (n) {
- case 0: s = "EOF expected"; break;
- case 1: s = "ident expected"; break;
- case 2: s = "bvlit expected"; break;
- case 3: s = "digits expected"; break;
- case 4: s = "string expected"; break;
- case 5: s = "float expected"; break;
- case 6: s = "\"var\" expected"; break;
- case 7: s = "\";\" expected"; break;
- case 8: s = "\"(\" expected"; break;
- case 9: s = "\")\" expected"; break;
- case 10: s = "\":\" expected"; break;
- case 11: s = "\",\" expected"; break;
- case 12: s = "\"where\" expected"; break;
- case 13: s = "\"int\" expected"; break;
- case 14: s = "\"bool\" expected"; break;
- case 15: s = "\"[\" expected"; break;
- case 16: s = "\"]\" expected"; break;
- case 17: s = "\"<\" expected"; break;
- case 18: s = "\">\" expected"; break;
- case 19: s = "\"const\" expected"; break;
- case 20: s = "\"unique\" expected"; break;
- case 21: s = "\"extends\" expected"; break;
- case 22: s = "\"complete\" expected"; break;
- case 23: s = "\"function\" expected"; break;
- case 24: s = "\"returns\" expected"; break;
- case 25: s = "\"{\" expected"; break;
- case 26: s = "\"}\" expected"; break;
- case 27: s = "\"axiom\" expected"; break;
- case 28: s = "\"type\" expected"; break;
- case 29: s = "\"=\" expected"; break;
- case 30: s = "\"procedure\" expected"; break;
- case 31: s = "\"implementation\" expected"; break;
- case 32: s = "\"modifies\" expected"; break;
- case 33: s = "\"free\" expected"; break;
- case 34: s = "\"requires\" expected"; break;
- case 35: s = "\"ensures\" expected"; break;
- case 36: s = "\"goto\" expected"; break;
- case 37: s = "\"return\" expected"; break;
- case 38: s = "\"if\" expected"; break;
- case 39: s = "\"else\" expected"; break;
- case 40: s = "\"while\" expected"; break;
- case 41: s = "\"invariant\" expected"; break;
- case 42: s = "\"*\" expected"; break;
- case 43: s = "\"break\" expected"; break;
- case 44: s = "\"assert\" expected"; break;
- case 45: s = "\"assume\" expected"; break;
- case 46: s = "\"havoc\" expected"; break;
- case 47: s = "\":=\" expected"; break;
- case 48: s = "\"call\" expected"; break;
- case 49: s = "\"forall\" expected"; break;
- case 50: s = "\"<==>\" expected"; break;
- case 51: s = "\"\\u21d4\" expected"; break;
- case 52: s = "\"==>\" expected"; break;
- case 53: s = "\"\\u21d2\" expected"; break;
- case 54: s = "\"<==\" expected"; break;
- case 55: s = "\"\\u21d0\" expected"; break;
- case 56: s = "\"&&\" expected"; break;
- case 57: s = "\"\\u2227\" expected"; break;
- case 58: s = "\"||\" expected"; break;
- case 59: s = "\"\\u2228\" expected"; break;
- case 60: s = "\"==\" expected"; break;
- case 61: s = "\"<=\" expected"; break;
- case 62: s = "\">=\" expected"; break;
- case 63: s = "\"!=\" expected"; break;
- case 64: s = "\"<:\" expected"; break;
- case 65: s = "\"\\u2260\" expected"; break;
- case 66: s = "\"\\u2264\" expected"; break;
- case 67: s = "\"\\u2265\" expected"; break;
- case 68: s = "\"++\" expected"; break;
- case 69: s = "\"+\" expected"; break;
- case 70: s = "\"-\" expected"; break;
- case 71: s = "\"/\" expected"; break;
- case 72: s = "\"%\" expected"; break;
- case 73: s = "\"!\" expected"; break;
- case 74: s = "\"\\u00ac\" expected"; break;
- case 75: s = "\"false\" expected"; break;
- case 76: s = "\"true\" expected"; break;
- case 77: s = "\"old\" expected"; break;
- case 78: s = "\"|{\" expected"; break;
- case 79: s = "\"}|\" expected"; break;
- case 80: s = "\"then\" expected"; break;
- case 81: s = "\"\\u2200\" expected"; break;
- case 82: s = "\"exists\" expected"; break;
- case 83: s = "\"\\u2203\" expected"; break;
- case 84: s = "\"lambda\" expected"; break;
- case 85: s = "\"\\u03bb\" expected"; break;
- case 86: s = "\"::\" expected"; break;
- case 87: s = "\"\\u2022\" expected"; break;
- case 88: s = "??? expected"; break;
- case 89: s = "invalid Function"; break;
- case 90: s = "invalid Function"; break;
- case 91: s = "invalid Procedure"; break;
- case 92: s = "invalid Type"; break;
- case 93: s = "invalid TypeAtom"; break;
- case 94: s = "invalid TypeArgs"; break;
- case 95: s = "invalid Spec"; break;
- case 96: s = "invalid SpecPrePost"; break;
- case 97: s = "invalid LabelOrCmd"; break;
- case 98: s = "invalid StructuredCmd"; break;
- case 99: s = "invalid TransferCmd"; break;
- case 100: s = "invalid IfCmd"; break;
- case 101: s = "invalid Guard"; break;
- case 102: s = "invalid LabelOrAssign"; break;
- case 103: s = "invalid CallCmd"; break;
- case 104: s = "invalid CallCmd"; break;
- case 105: s = "invalid CallForallArg"; break;
- case 106: s = "invalid CallOutIdent"; break;
- case 107: s = "invalid EquivOp"; break;
- case 108: s = "invalid ImpliesOp"; break;
- case 109: s = "invalid ExpliesOp"; break;
- case 110: s = "invalid AndOp"; break;
- case 111: s = "invalid OrOp"; break;
- case 112: s = "invalid RelOp"; break;
- case 113: s = "invalid AddOp"; break;
- case 114: s = "invalid UnaryExpression"; break;
- case 115: s = "invalid MulOp"; break;
- case 116: s = "invalid NegOp"; break;
- case 117: s = "invalid CoercionExpression"; break;
- case 118: s = "invalid AtomExpression"; break;
- case 119: s = "invalid AtomExpression"; break;
- case 120: s = "invalid AtomExpression"; break;
- case 121: s = "invalid Forall"; break;
- case 122: s = "invalid QuantifierBody"; break;
- case 123: s = "invalid Exists"; break;
- case 124: s = "invalid Lambda"; break;
- case 125: s = "invalid SpecBlock"; break;
- case 126: s = "invalid AttributeOrTrigger"; break;
- case 127: s = "invalid AttributeParameter"; break;
- case 128: s = "invalid QSep"; break;
-
- default: s = "error " + n; break;
- }
- //errorStream.WriteLine(errMsgFormat, line, col, s);
- errorStream.WriteLine(s);
- count++;
- }
-
- public void SemErr (int line, int col, string! s) {
- errorStream.WriteLine(errMsgFormat, line, col, s);
- count++;
- }
-
- public void SemErr (string filename, int line, int col, string! s) {
- errorStream.WriteLine(errMsgFormat4, filename, line, col, s);
- count++;
- }
-
- public void SemErr (string s) {
- errorStream.WriteLine(s);
- count++;
- }
-
- public void SemErr(IToken! tok, string! msg) { // semantic errors
- SemErr(tok.filename, tok.line, tok.col, msg);
- }
-
- public void Warning (int line, int col, string s) {
- errorStream.WriteLine(errMsgFormat, line, col, s);
- }
-
- public void Warning(string s) {
- errorStream.WriteLine(s);
- }
-} // Errors
-
-
-public class FatalError: Exception {
- public FatalError(string m): base(m) {}
-}
-
-} \ No newline at end of file
diff --git a/Source/Core/ParserHelper.ssc b/Source/Core/ParserHelper.ssc
deleted file mode 100644
index 67cd261a..00000000
--- a/Source/Core/ParserHelper.ssc
+++ /dev/null
@@ -1,188 +0,0 @@
-using System.Text;
-using System.Collections.Generic;
-using System.IO;
-using Microsoft.Contracts;
-
-namespace Microsoft.Boogie {
-
- [Immutable]
- public interface IToken {
- int kind {get; set; } // token kind
- string filename {get; set; } // token file
- int pos {get; set; } // token position in the source text (starting at 0)
- int col {get; set; } // token column (starting at 0)
- int line {get; set; } // token line (starting at 1)
- string/*!*/ val {get; set; } // token value
-
- bool IsValid { get; }
- }
-
- [Immutable]
- public class Token : IToken {
- public int _kind; // token kind
- string _filename; // token file
- public int _pos; // token position in the source text (starting at 0)
- public int _col; // token column (starting at 1)
- public int _line; // token line (starting at 1)
- public string/*!*/ _val; // token value
- public Token next; // ML 2005-03-11 Tokens are kept in linked list
-
- public static IToken! NoToken = new Token();
-
- public Token() {
- this._val = "anything so that it is nonnull";
- }
- public Token(int linenum, int colnum) {
- this._line = linenum;
- this._col = colnum;
- this._val = "anything so that it is nonnull";
- base();
- }
-
- public int kind {
- get { return this._kind; }
- set { this._kind = value; }
- }
-
- public string filename{
- get { return this._filename; }
- set { this._filename = value; }
- }
-
- public int pos{
- get { return this._pos; }
- set { this._pos = value; }
- }
-
- public int col{
- get { return this._col; }
- set { this._col = value; }
- }
-
- public int line{
- get { return this._line; }
- set { this._line = value; }
- }
-
- public string/*!*/ val{
- get { return this._val; }
- set { this._val = value; }
- }
-
- public bool IsValid { get { return this._filename != null; } }
-
-
-}
-
-public static class ParserHelper {
- struct ReadState {
- public bool hasSeenElse;
- public bool mayStillIncludeAnotherAlternative;
- public ReadState(bool hasSeenElse, bool mayStillIncludeAnotherAlternative) {
- this.hasSeenElse = hasSeenElse;
- this.mayStillIncludeAnotherAlternative = mayStillIncludeAnotherAlternative;
- }
- }
- // "arg" is assumed to be trimmed
- private static bool IfdefConditionSaysToInclude(string! arg, List<string!>! defines) {
- bool sense = true;
- while (arg.StartsWith("!")) {
- sense = !sense;
- arg = arg.Substring(1).TrimStart();
- }
- return defines.Contains(arg) == sense;
- }
-
- public static string! Fill(Stream! stream, List<string!>! defines) {
- StreamReader! reader = new StreamReader(stream);
- return Fill(reader, defines);
- }
- public static string! Fill(TextReader! reader, List<string!>! defines) {
- StringBuilder sb = new StringBuilder();
- List<ReadState>! readState = new List<ReadState>(); // readState.Count is the current nesting level of #if's
- int ignoreCutoff = -1; // -1 means we're not ignoring; for 0<=n, n means we're ignoring because of something at nesting level n
- while (true)
- //invariant -1 <= ignoreCutoff && ignoreCutoff < readState.Count;
- {
- string s = reader.ReadLine();
- if (s == null) {
- if (readState.Count != 0) {
- sb.AppendLine("#MalformedInput: missing #endif");
- }
- break;
- }
- string t = s.Trim();
- if (t.StartsWith("#if")) {
- ReadState rs = new ReadState(false, false);
- if (ignoreCutoff != -1) {
- // we're already in a state of ignoring, so continue to ignore
- } else if (IfdefConditionSaysToInclude(t.Substring(3).TrimStart(), defines)) {
- // include this branch
- } else {
- ignoreCutoff = readState.Count; // start ignoring
- rs.mayStillIncludeAnotherAlternative = true; // allow some later "elsif" or "else" branch to be included
- }
- readState.Add(rs);
- sb.AppendLine(); // ignore the #if line
-
- } else if (t.StartsWith("#elsif")) {
- ReadState rs;
- if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
- sb.AppendLine("#MalformedInput: misplaced #elsif"); // malformed input
- break;
- }
- if (ignoreCutoff == -1) {
- // we had included the previous branch
- //assert !rs.mayStillIncludeAnotherAlternative;
- ignoreCutoff = readState.Count-1; // start ignoring
- } else if (rs.mayStillIncludeAnotherAlternative && IfdefConditionSaysToInclude(t.Substring(6).TrimStart(), defines)) {
- // include this branch, but no subsequent branch at this level
- ignoreCutoff = -1;
- rs.mayStillIncludeAnotherAlternative = false;
- readState[readState.Count-1] = rs;
- }
- sb.AppendLine(); // ignore the #elsif line
-
- } else if (t == "#else") {
- ReadState rs;
- if (readState.Count == 0 || (rs = readState[readState.Count-1]).hasSeenElse) {
- sb.AppendLine("#MalformedInput: misplaced #else"); // malformed input
- break;
- }
- rs.hasSeenElse = true;
- if (ignoreCutoff == -1) {
- // we had included the previous branch
- //assert !rs.mayStillIncludeAnotherAlternative;
- ignoreCutoff = readState.Count-1; // start ignoring
- } else if (rs.mayStillIncludeAnotherAlternative) {
- // include this branch
- ignoreCutoff = -1;
- rs.mayStillIncludeAnotherAlternative = false;
- }
- readState[readState.Count-1] = rs;
- sb.AppendLine(); // ignore the #else line
-
- } else if (t == "#endif") {
- if (readState.Count == 0) {
- sb.AppendLine("#MalformedInput: misplaced #endif"); // malformed input
- break;
- }
- readState.RemoveAt(readState.Count-1); // pop
- if (ignoreCutoff == readState.Count) {
- // we had ignored the branch that ends here; so, now we start including again
- ignoreCutoff = -1;
- }
- sb.AppendLine(); // ignore the #endif line
-
- } else if (ignoreCutoff == -1) {
- sb.AppendLine(s); // included line
-
- } else {
- sb.AppendLine(); // ignore the line
- }
- }
-
- return sb.ToString();
- }
-}
-} \ No newline at end of file
diff --git a/Source/Core/PureCollections.ssc b/Source/Core/PureCollections.ssc
deleted file mode 100644
index e6d68a34..00000000
--- a/Source/Core/PureCollections.ssc
+++ /dev/null
@@ -1,785 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-
-//---------------------------------------------------------------------
-// PureCollections.cs
-// - Mostly pure functions for tuples, sets, maps, Sequences
-// Version 1.0, WS, 3/23/2002
-//---------------------------------------------------------------------
-
-
-using System;
-using System.Collections;
-using Microsoft.Contracts;
-
-namespace PureCollections {
- //-------------------------------------------------------------------
- // General types
- //-------------------------------------------------------------------
-
- public class MissingCase :Exception{}
-
- public struct Capacity{
- public int capacity;
- public Capacity (int i) {capacity = i;}
- }
-
- abstract public class Coll {
- public object[] elems; // null is used to show empty spots!
- protected int card;
- protected Coll() {}
- protected Coll(object[] elems, int card) {this.elems = elems; this.card = card; }
- protected Coll(Coll! c)
- requires c.elems != null;
- {
- this.elems = (object[])c.elems.Clone();
- this.card = c.card;
- }
- }
-
-
- // ------------------------------------------------------------------
- // Tuple
- // ------------------------------------------------------------------
-
- public class Tuple : Coll, IComparable
- {
- //public object[] elems;
-
- //invariant this.elems != null;
-
- // Constructor - - - - - - - - - - - - - - - - - - - - - - - - - -
- public Tuple(params object []! ts) {
- elems = ts;
- card = ts.Length;}
- public Tuple(Capacity c) {
- elems = new object[c.capacity];
- card = c.capacity;
- }
-
- //Equality - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals (object o){
- assert this.elems != null;
- if (o == null || !(o is Tuple) || elems.Length != ((!)((Tuple)o).elems).Length)
- return false;
-
- Tuple s = (Tuple) o;
- for(int i = 0; i < elems.Length; i ++)
- if ( ! Equals(this.elems[i], s.elems[i]))
- return false;
- return true;
- }
-
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator == (Tuple s, Tuple t) {return s == null ? t == null : s.Equals(t);}
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator != (Tuple s, Tuple t) { return ! (t == s); }
-
- [Pure]
- public override int GetHashCode (){
- int h =0;
- assume this.elems != null;
- for(int i = 0; i < elems.Length; i++)
- {
- object elem = elems[i];
- if (elem != null)
- h += elem.GetHashCode();
- }
- return h;
- }
-
- //Compare - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- int IComparable.CompareTo(object o) {
- assert this.elems != null;
- if (o == null || !(o is Tuple) || elems.Length != ((!)((Tuple)o).elems).Length)
- throw new MissingCase();
-
- Tuple t = (Tuple) o;
- for(int i = 0; i < elems.Length; i ++) {
- int c = ((IComparable!) elems[i]).CompareTo(t.elems[i]);
- if (c < 0) return -1;
- else if (c > 0) return +1;
- }
- return 0;
- }
-
- public static bool operator <= (Tuple s, Tuple t) {return s == null ? t == null : ((IComparable) s).CompareTo(t) <= 0;}
- public static bool operator < (Tuple s, Tuple t) {return s == null ? false : ((IComparable) s).CompareTo(t) < 0;}
- public static bool operator >= (Tuple s, Tuple t) {return t <= s; }
- public static bool operator > (Tuple s, Tuple t) { return t < s; }
-
- //Select and Update - - - - - - - - - - - - - - - - - - - - - - - -
- public object this[int index]{
- get{assert this.elems != null; return elems[index];}
- set{assert this.elems != null; elems[index] = value;}
- }
-
- //ToString - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure]
- public override string! ToString() {
- assert this.elems != null;
- if (elems.Length==0)
- return "()";
-
- string s = "(";
- for (int i= 0; i< elems.Length-1; i++)
- s += ((!)elems[i]).ToString() + ", ";
- return s + ((!)elems[elems.Length-1]).ToString() + ")";
- }
- }
-
- // ------------------------------------------------------------------
- // Pair
- public class Pair : Tuple{
- protected Pair(){}
- public Pair(object first, object second) {
- elems = new object[]{first,second};
- }
- public object First{
- get{assert this.elems != null; return elems[0];}
- set{assert this.elems != null; elems[0]=value;}
- }
- public object Second{
- get{assert this.elems != null; return elems[1];}
- set{assert this.elems != null; elems[1]=value;}
- }
- }
-
- // --------------------------------------------------------------------
- // Map
- // --------------------------------------------------------------------
-
- public class MapEnumerator: IEnumerator{
- private Map! map;
- private int index = -1;
- public MapEnumerator(Map! m) { map = m;}
- public bool MoveNext() {
- do{
- index++;
- assert map.elems != null;
- } while (index < map.elems.Length && map.elems[index] == null);
- return index < map.elems.Length;
- }
- public object Current{ get { assert map.elems != null; return new Pair(map.elems[index],map.vals[index]); }}
- public void Reset() {index = -1; }
- }
-
- public class Map:Coll, IEnumerable, IComparable
- {
- public Object[]! vals;
-
- //invariant this.elems != null;
-
- // constructors - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public Map(Capacity c){
- elems = new Object[c.capacity*2];
- vals = new Object[c.capacity*2];
- card = 0;
- }
-
- [NotDelayed]
- public Map(params Pair []! ps){
- elems = new Object[ps.Length*2];
- vals = new Object[ps.Length*2];
- base();
- card = 0;
- for(int i = 0; i < ps.Length; i++)
- Insert( ((!)ps[i]).First, ((!)ps[i]).Second);
- }
-
- // iterators - - - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- public IEnumerator! GetEnumerator() {
- return new MapEnumerator(this);
- }
- public Pair[] ToArray() {
- Pair [] n = new Pair[card];
- int ct = 0;
- assert this.elems != null;
- for(int i =0; i < elems.Length ; i++)
- if (elems[i] != null)
- n[ct++] = new Pair(elems[i], vals[i]);
- return n;
- }
-
- //(ASM) Update- - - - - - - - - - - - - - - - - - - - - - - - - - -
- public Map Update(object k, object v) {
- Map n = new Map(new Capacity(card+1));
- assert this.elems != null;
- for (int i = 0; i < elems.Length; i++ )
- if (elems[i] != null && ! Equals(elems[i], k))
- n.Insert(elems[i], vals[i]);
- n.Insert(k,v);
- return n;
- }
-
- //In place Update (and Remove)- - - - - - - - - - - - - - - - - - -
- public object this[object index]{
- get{return this.Apply(index);}
- set{this.Insert(index,value);}
- }
-
- public void Remove(object! o) {
- assert this.elems != null;
- int h = Math.Abs(o.GetHashCode()) % elems.Length;
- for (int i = 0; i < elems.Length; i++ ) {
- int j = (i+ h) % elems.Length;
- if (elems[j] == null) {
- break;
- } else if (Equals(elems[j], o)){
- elems[j] = null;
- vals[j] = null;
- break;
- }
- }
- }
-
- public void Insert(Object key, Object val) {
- if (key == null)
- throw new MissingCase();
-
- assert this.elems != null;
- if (elems.Length == 0 || 2*card >= elems.Length){
- int m = card*2; if (m < 4) m = 4;
- object [] newElems = new object [m];
- object [] newVals = new object [m];
- for (int k = 0; k < elems.Length; k++) {
- object elem = elems[k];
- if (elem != null) {
- int newHash = Math.Abs(elem.GetHashCode()) % newElems.Length;
- for (int i = 0; i < newElems.Length; i++ ) {
- int j = (i+ newHash) % newElems.Length;
- if (newElems[j] == null) {
- newElems[j] = elem;
- newVals[j] = vals[k];
- break;
- }
- }
- }
- }
- elems = newElems;
- vals = newVals;
- }
- int h = Math.Abs(key.GetHashCode()) % elems.Length;
- for (int i = 0; i < elems.Length; i++ ) {
- int j = (i+ h) % elems.Length;
- if (elems[j] == null) {
- elems[j] = key;
- vals[j] = val;
- card ++;
- return;
- } else if (key.Equals(elems[j])) {
- vals[j] = val;
- return;
- }
- }
- }
-
- //ToString - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure]
- public override string! ToString() {
- if (card ==0)
- return "{|->}";
- else {
- string s = "{"; int ct = 0;
- assert this.elems != null;
- for(int i =0; i < elems.Length ; i++) {
- object elem = elems[i];
- if (elem != null){
- s += elem.ToString() +"|->" + ((!)vals[i]).ToString() ;
- s +=(ct!=card-1) ? ", " : "";
- ct ++;
- }
- }
- return s+"}";
- }
- }
-
- // Subset operations - - - - - - - - - - - - - - - - - - - - - - -
- // View Map as Set of Pairs
-
- int IComparable.CompareTo(object o) {
- if (o == null || !(o is Map))
- throw new MissingCase();
- // WS Improve performance!
- Map t = (Map) o;
- if (this < t) return -1;
- else if(this > t) return +1;
- else return 0;
- }
- public static bool operator <= (Map s, Map t){
- if (s==null) return t==null;
- if (t==null) return false;
- assert s.elems != null;
- for(int i = 0; i < s.elems.Length; i++)
- if (s.elems[i]!= null) {
- object o = t.Apply(s.elems[i]);
- if (o == null || !o.Equals(s.vals[i]))
- return false;
- }
- return true;
- }
- public static bool operator < (Map s, Map t){
- return s == null || t == null ? false : s.card < t.card && s <= t;
- }
- public static bool operator >= (Map s, Map t){
- return t <= s;
- }
- public static bool operator > (Map s, Map t){
- return t < s;
- }
-
- // Equality - - - - - - - - - - - - - - - - - - - - - - -
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals (Object t){
- return t != null && t is Map && card == ((Map) t).card && this<= ((Map) t);
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator == (Map s, Map t){
- if ((object)s==null)
- if ((object)t==null) return true;
- else return t.Equals(s);
- else
- return s.Equals(t);
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator != (Map s, Map t){
- return ! (t == s);
- }
- [Pure]
- public override int GetHashCode (){
- int h =0;
- assert this.elems != null;
- for(int i = 0; i < elems.Length; i++)
- {
- object elem = elems[i];
- if (elem != null)
- {
- h += elem.GetHashCode() + ((!)vals[i]).GetHashCode();
- }
- }
- return h;
- }
-
- //Ordinary map operations- - - - - - - - - - - - - - - - - - - - - - - -
-
- [Pure]
- public bool Has(Object x) {
- if (x == null)
- throw new MissingCase();
-
- assert this.elems != null;
- if (elems.Length == 0)
- return false;
- int h = Math.Abs(x.GetHashCode()) % elems.Length;
- for (int i = 0; i < elems.Length; i++ ) {
- int j = (i+ h) % elems.Length;
- if (x.Equals(elems[j]))
- return true;
- }
- return false;
- }
-
- public object Apply(object x) {
- if (x == null)
- throw new MissingCase();
- assert this.elems != null;
- if (elems.Length == 0)
- return null;
- int h = Math.Abs(x.GetHashCode()) % elems.Length;
- for (int i = 0; i < elems.Length; i++ ) {
- int j = (i+ h) % elems.Length;
- if (elems[j] != null && x.Equals(elems[j]))
- return vals[j];
- }
- return null;
- }
-
- public static Map Override(Map! s, Map! t) {
- Map m = new Map(new Capacity(s.card+t.card));
- assert s.elems != null;
- for(int i = 0; i< s.elems.Length; i++)
- if (s.elems[i] != null)
- m.Insert(s.elems[i], s.vals[i]);
- assert t.elems != null;
- for(int i = 0; i< t.elems.Length; i++)
- if (t.elems[i] != null)
- m.Insert(t.elems[i], t.vals[i]);
- return m;
- }
- }
-
- // --------------------------------------------------------------------
- // Sequence
-
- public class SequenceEnumerator: IEnumerator{
- [Peer] private Sequence! seq;
- private int index = -1;
- [Captured]
- public SequenceEnumerator(Sequence! s) { seq = s;}
- public bool MoveNext() {
- index++;
- //while (index < seq.elems.Length); // Sequences allow nils ... && seq.elems[index] == null);
- return index < seq.Length;
- }
- public object Current{ get { assert seq.elems != null; return seq.elems[index]; }}
- public void Reset() {index = -1; }
- }
-
- public class Sequence:Coll, IEnumerable, IComparable
- {
- public Sequence(){elems = new object [4];}
-
- //invariant this.elems != null;
-
- //constructors - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public Sequence(params object []! ds){card = ds.Length; elems = ds; }
- public Sequence(Sequence! seq) {
- base(seq);
- }
- public Sequence(Capacity c){elems = new object [c.capacity];}
-
- // Iterators - - - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure] [GlobalAccess(false)] [Escapes(true,false)]
- public IEnumerator! GetEnumerator()
- ensures Owner.Same(result, this);
- ensures result.IsNew;
- {
- return new SequenceEnumerator(this);
- }
-
- public object[] ToArray() {
- object [] n = new object[card];
- int ct = 0;
- assert this.elems != null;
- for(int i =0; i < elems.Length ; i++)
- n[ct++] = elems[i];
- return n;
- }
-
- //ASM Update - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public Sequence Update(int i, object v) {
- Sequence n = new Sequence(new Capacity(card+1));
- assert this.elems != null;
- assert n.elems != null;
- for (int j = 0; j < elems.Length; j++ )
- n.elems[j] = elems[j];
- if (i >= 0 && i < card){
- n.elems[i] = v;
- n.card = card;
- return n;
- } else if (i == card) {
- n.elems[i] = v;
- n.card = card+1;
- return n;
- } else
- throw new Exception("Sequence Update out of range");
- }
-
- //In place Update (and Remove) and Length - - - - - - - - - - - - - - -
- public int Length {
- get{return this.card;}
- }
-
- public object this[int index]{
- get{assert this.elems != null; return this.elems[index];}
- set{assert this.elems != null; this.elems[index] = value;}
- }
-
- public void Add(object o){
- assert this.elems != null;
- int n = this.elems.Length;
- int i = this.card++;
- if (i == n){
- int m = n*2; if (m < 4) m = 4;
- object [] newElems = new object [m];
- for (int j = 0; j < n; j++) newElems[j] = elems[j];
- elems = newElems;
- }
- elems[i] = o;
- }
-
- public void AddRange(Sequence! seq){
- foreach (object o in seq) {
- Add(o);
- }
- }
-
- public void Remove(){
- if (card == 0)
- return;
- card--;
- }
-
- // remove the first occurrence of o from this sequence
- public void Remove(Object x) {
- if (x == null)
- throw new MissingCase();
- assert this.elems != null;
- for (int i = 0; i < card; i++) {
- if (x.Equals(elems[i])) {
- ++i;
- while (i < card) {
- elems[i-1] = elems[i];
- ++i;
- }
- card--;
- elems[card] = null;
- return;
- }
- }
- }
-
- public void Truncate(int newLen)
- requires 0 <= newLen && newLen <= Length;
- {
- assert elems != null;
- for (int i = newLen; i < card; i++) {
- elems[i] = null;
- }
- card = newLen;
- }
-
- //ToString - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure]
- public override string! ToString() {
- string s ="";
- assert this.elems != null;
- if (card > 0 && elems[0] is Char) {
- for(int i =0; i < card ; i++)
- {
- object elem = elems[i];
- if (elem != null) { s +=elem.ToString(); }
- }
- return s;
- } else {
- s = "[";
- for(int i =0; i < card-1; i++) {
- object elem = elems[i];
- if (elem != null) { s += elem.ToString()+", "; }
- }
- if (card > 0)
- {
- object last = elems[card-1];
- if (last != null) { s += last.ToString(); }
- }
- s += "]";
- return s;
- }
- }
- //Equality- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- [Pure][Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals (object that){
- return that != null && that is Sequence && ((Sequence) this == (Sequence) that);
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator == (Sequence s, Sequence t){
- if ((object)s == (object)t) {
- return true;
- } else if ((object)s == null || (object)t == null) {
- return false;
- }
- if (s.card != t.card) return false;
- assert s.elems != null;
- assert t.elems != null;
- for(int i = 0; i < s.card; i++)
- if (! Equals(s.elems[i], t.elems[i]))
- return false;
- return true;
- }
- [Pure][Reads(ReadsAttribute.Reads.Nothing)] // ugh, is this right? --KRML
- public static bool operator != (Sequence s, Sequence t){
- return !(s == t);
- }
- [Pure]
- public override int GetHashCode (){
- int h = 0;
- for(int i = 0; i < card; i++)
- {
- assert this.elems != null;
- object elem = elems[i];
- if (elem != null) { h += elem.GetHashCode(); }
- }
- return h;
- }
- //Subset- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- // View Sequence of T as Set of (Integer,T)
- int IComparable.CompareTo(object o) {
- if (o == null || !(o is Sequence))
- throw new MissingCase();
- // WS Improve performance!
- Sequence t = (Sequence) o;
- if (this < t) return -1;
- else if(this > t) return +1;
- else return 0;
- }
-
- public static bool operator < (Sequence s, Sequence t){
- if (s==null) throw new ArgumentNullException("s");
- if (t==null) throw new ArgumentNullException("t");
- if (s.card >= t.card) return false;
- assert s.elems != null;
- assert t.elems != null;
- for(int i = 0; i < s.card; i++)
- if ( ! Equals(s.elems[i], t.elems[i]))
- return false;
- return true;
- }
- public static bool operator <= (Sequence s, Sequence t){
- if (s==null) throw new ArgumentNullException("s");
- if (t==null) throw new ArgumentNullException("t");
- if (s.card > t.card) return false;
- assert s.elems != null;
- assert t.elems != null;
- for(int i = 0; i < s.card; i++)
- if ( ! Equals(s.elems[i], t.elems[i]))
- return false;
- return true;
- }
- public static bool operator > (Sequence s, Sequence t){ return t < s;}
- public static bool operator >= (Sequence s, Sequence t){ return t <= s;}
-
- //pure---------------------------------------------------------------
- [Pure]
- public bool Has(object x) { // WS translate to tailrecursion
- if (x == null)
- throw new MissingCase();
- assert this.elems != null;
- for (int i = 0; i< card; i++)
- if (x.Equals(elems[i]))
- return true;
- return false;
- }
-
- // the index of the first occurrence of x in this sequence,
- // or -1 if x does not occur
- [Pure]
- public int IndexOf(object x) {
- if (x == null)
- throw new MissingCase();
- assert this.elems != null;
- for (int i = 0; i< card; i++)
- if (x.Equals(elems[i]))
- return i;
- return -1;
- }
-
- // the index of the last occurrence of x in this sequence,
- // or -1 if x does not occur
- [Pure]
- public int LastIndexOf(object x) {
- if (x == null)
- throw new MissingCase();
- assert this.elems != null;
- for (int i = card - 1; i >= 0; i--)
- if (x.Equals(elems[i]))
- return i;
- return -1;
- }
-
- public object Head() {assert this.elems != null; return elems[0]; }
- public object Last() {assert this.elems != null; return elems[card-1]; }
-
- public static Sequence Tail(Sequence! s) {
- Sequence n = new Sequence(new Capacity(s.card-1));
- assert n.elems != null;
- assert s.elems != null;
- for (int i = 1; i< s.card; i++) n.elems[n.card++] = s.elems[i];
- return n;
- }
-
- public static Sequence Front(Sequence! s) {
- Sequence n = new Sequence(new Capacity(s.card-1));
- assert n.elems != null;
- assert s.elems != null;
- for (int i = 0; i< s.card-1; i++) n.elems[n.card++] = s.elems[i];
- return n;
- }
- public static Sequence Concat(Sequence! s) {
- Sequence n = new Sequence(new Capacity(s.card));
- assert n.elems != null;
- assert s.elems != null;
- for (int i = 0; i< s.card; i++) {
- Sequence t = (Sequence!) s.elems[i];
- assert t.elems != null;
- for (int j = 0; j < t.card; j ++)
- n.Add(t.elems[j]);
- }
- return n;
- }
-
- public static Sequence Reverse(Sequence! s) {
- Sequence n = new Sequence(new Capacity(s.card));
- assert n.elems != null;
- assert s.elems != null;
- for (int i = s.card-1; i>=0; i--) n.elems[n.card++] = s.elems[i];
- return n;
- }
-
- public static Sequence operator + (Sequence s, Sequence t)
- {
- if (s==null) throw new ArgumentNullException("s");
- if (t == null) throw new ArgumentNullException("t");
- return Append(t,s);
- }
-
- public static Sequence! Append(Sequence! s, Sequence! t) {
- Sequence! n = new Sequence(new Capacity(s.card + t.card));
- assert n.elems != null;
- assert s.elems != null;
- assert t.elems != null;
- for (int i = 0; i< s.card; i++) n.elems[n.card++] = s.elems[i];
- for (int i = 0; i< t.card; i++) n.elems[n.card++] = t.elems[i];
- return n;
- }
- public static Sequence Zip(Sequence! s, Sequence! t) {
- int min = s.card<t.card ? s.card : t.card;
- Sequence n = new Sequence(new Capacity(min));
- assert n.elems != null;
- assert s.elems != null;
- assert t.elems != null;
- for (int i = 0; i< min; i++) n.elems[n.card++] = new Tuple(s.elems[i], t.elems[i]);
- return n;
- }
- public static Tuple Unzip(Sequence! s) {
- Sequence n0 = new Sequence(new Capacity(s.card));
- Sequence n1 = new Sequence(new Capacity(s.card));
- assert s.elems != null;
- assert n0.elems != null;
- assert n1.elems != null;
- for (int i = 0; i< s.card; i++) {
- n0.elems[n0.card++] = ((!)((Tuple!)s.elems[i]).elems)[0];
- n1.elems[n1.card++] = ((!)((Tuple!)s.elems[i]).elems)[1];
- }
- return new Tuple(n0,n1);
- }
-
- public static Sequence FromTo(int from, int to) { //WS hash the result!
- if (from > to) return new Sequence();
- Sequence n = new Sequence(new Capacity(to-from+1));
- assert n.elems != null;
- for (int i = from; i<= to; i++)
- n.elems[n.card++] = i;
- return n;
- }
-
- public static Sequence FromStepTo(int from, int step, int to) {
- Sequence n = new Sequence();
- int incr = step-from;
- if (incr >0)
- for (int i = from; i<= to; i+=incr)
- n.Add(i);
- else if (incr < 0)
- for (int i = to; i>= from; i-=incr)
- n.Add(i);
- return n;
- }
-
- }
-
-}
diff --git a/Source/Core/ResolutionContext.ssc b/Source/Core/ResolutionContext.ssc
deleted file mode 100644
index 10ff7d87..00000000
--- a/Source/Core/ResolutionContext.ssc
+++ /dev/null
@@ -1,539 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie
-{
- using System.Collections;
- using System.Collections.Generic;
- using System;
- using Microsoft.SpecSharp.Collections;
- using Microsoft.Contracts;
-
- public interface IErrorSink
- {
- void Error(IToken! tok, string! msg);
- }
-
- public class CheckingContext
- {
- // ------------------------------ Error counting ------------------------------
-
- IErrorSink errorSink;
- int errors;
-
- public CheckingContext(IErrorSink errorSink)
- {
- this.errorSink = errorSink;
- }
-
- public int ErrorCount
- {
- get { return errors; }
- set { errors = value; }
- }
-
- public void Error(Absy! subject, string! msg, params object[]! args)
- {
- Error(subject.tok, msg, args);
- }
-
- public virtual void Error(IToken! tok, string! msg)
- {
- errors++;
- if (errorSink == null) {
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine("{0}({1},{2}): Error: {3}",
- tok.filename, tok.line, tok.col-1,
- msg);
- Console.ForegroundColor = col;
- } else {
- errorSink.Error(tok, msg);
- }
- }
-
- private string! Format(string! msg, params object[] args) {
- if (System.Type.GetType("Mono.Runtime") != null) { // MONO
- // something in mono seems to be broken so that calling
- // NamedDeclarations.ToString (and similar ToString methods)
- // causes a stack overflow. We therefore convert those to
- // strings by hand
- object[] fixedArgs = new object [((!)args).Length];
- for (int i = 0; i < args.Length; ++i) {
- if (args[i] is NamedDeclaration) {
- fixedArgs[i] = ((NamedDeclaration!)args[i]).Name;
- } else if (args[i] is Type) {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
- ((Type!)args[i]).Emit(stream);
- }
- fixedArgs[i] = buffer.ToString();
- } else if (args[i] is Expr) {
- System.IO.StringWriter buffer = new System.IO.StringWriter();
- using (TokenTextWriter stream = new TokenTextWriter("<buffer>", buffer, false)) {
- ((Expr!)args[i]).Emit(stream, 0, false);
- }
- fixedArgs[i] = buffer.ToString();
- } else {
- fixedArgs[i] = args[i];
- }
- }
- args = fixedArgs;
- }
- return string.Format(msg, args);
- }
-
- public void Error(IToken! tok, string! msg, params object[] args)
- {
- Error(tok, Format(msg, args));
- }
-
- public void Warning(Absy! subject, string! msg, params object[]! args)
- {
- Warning(subject.tok, msg, args);
- }
-
- public virtual void Warning(IToken! tok, string! msg)
- {
- // warnings are currently always written to the console
- ConsoleColor col = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine("{0}({1},{2}): Warning: {3}",
- tok.filename, tok.line, tok.col-1,
- msg);
- Console.ForegroundColor = col;
- }
-
- public void Warning(IToken! tok, string! msg, params object[] args)
- {
- Warning(tok, Format(msg, args));
- }
- }
-
- public class ResolutionContext : CheckingContext
- {
- public ResolutionContext(IErrorSink errorSink)
- {
- base(errorSink);
- }
-
- // ------------------------------ Boogie 2 Types -------------------------
-
- // user-defined types, which can be either TypeCtorDecl or TypeSynonymDecl
- Hashtable /*string->NamedDeclaration*/! types = new Hashtable /*string->NamedDeclaration*/ ();
-
- /// <summary>
- /// Checks if name coincides with the name of a bitvector type. If so, reports an error and
- /// returns true; otherwise, returns false.
- /// </summary>
- private bool CheckBvNameClashes(Absy! absy, string! name) {
- if (name.StartsWith("bv") && name.Length > 2) {
- for (int i = 2; i < name.Length; ++i)
- if (!char.IsDigit(name[i])) return false;
- Error(absy, "type name: {0} is registered for bitvectors", name);
- return true;
- }
- return false;
- }
-
- public void AddType(NamedDeclaration! td)
- {
- assert (td is TypeCtorDecl) || (td is TypeSynonymDecl);
-
- string! name = (!)td.Name;
- if (CheckBvNameClashes(td, name))
- return; // error has already been reported
-
- if (types[name] != null)
- {
- Error(td, "more than one declaration of type name: {0}", name);
- }
- else
- {
- types.Add(name, td);
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named type, or null if
- /// no such type is declared. Also return null if the type
- /// declared with the given name is not a constructor but a
- /// type synonym
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public TypeCtorDecl LookUpType(string! name)
- {
- return types[name] as TypeCtorDecl;
- }
-
- public TypeSynonymDecl LookUpTypeSynonym(string! name)
- {
- return types[name] as TypeSynonymDecl;
- }
-
- // ------------------------------ Boogie 2 Type Binders ------------------------------
-
- List<TypeVariable!>! typeBinders = new List<TypeVariable!>(5);
-
- public void AddTypeBinder(TypeVariable! td) {
- if (CheckBvNameClashes(td, td.Name)) {
- return;
- }
- if (types.ContainsKey(td.Name)) {
- Error(td, "name is already reserved for type constructor: {0}", td.Name);
- return;
- }
- for (int i = 0; i < typeBinders.Count; i++) {
- if (typeBinders[i].Name == td.Name) {
- Error(td, "more than one declaration of type variable: {0}", td.Name);
- return;
- }
- }
- typeBinders.Add(td);
- }
-
- public int TypeBinderState {
- get { return typeBinders.Count; }
- set { typeBinders.RemoveRange(value, typeBinders.Count - value); }
- }
-
- /// <summary>
- /// Returns the declaration of the named type binder, or null if
- /// no such binder is declared.
- /// </summary>
- public TypeVariable LookUpTypeBinder(string! name)
- {
- for (int i = typeBinders.Count; 0 <= --i; ) {
- TypeVariable! td = typeBinders[i];
- if (td.Name == name) {
- return td;
- }
- }
- return null; // not present
- }
-
- // ------------------------------ Types ------------------------------
-
- // user-defined types
- // Hashtable /*string->TypeDecl*/! types = new Hashtable /*string->TypeDecl*/ ();
-/*
- public void AddType(TypeDecl! td)
- {
- string! name = (!)td.Name;
-
- if (name.StartsWith("bv") && name.Length > 2) {
- bool isBv = true;
- for (int i = 2; i < name.Length; ++i)
- if (!char.IsDigit(name[i])) isBv = false;
- if (isBv)
- Error(td, "type name: {0} is registered for bitvectors", name);
- }
-
- if (types[name] != null)
- {
- Error(td, "more than one declaration of type name: {0}", name);
- }
- else
- {
- types.Add(name, td);
- }
- }
-*/
- /// <summary>
- /// Returns the declaration of the named type, or null if
- /// no such type is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- /* public TypeDecl LookUpType(string! name)
- {
- return (TypeDecl)types[name];
- }
- */
- // ------------------------------ Type Binders ------------------------------
-/*
- List<TypeBinderDecl!>! typeBinders = new List<TypeBinderDecl!>(5);
-
- public void AddTypeBinder(TypeBinderDecl! td) {
- for (int i = 0; i < typeBinders.Count; i++) {
- if (typeBinders[i].Name == td.Name) {
- Error(td, "more than one declaration of type binder name: {0}", td.Name);
- return;
- }
- }
- typeBinders.Add(td);
- }
-
- public int TypeBinderState {
- get { return typeBinders.Count; }
- set { typeBinders.RemoveRange(value, typeBinders.Count - value); }
- }
-
- /// <summary>
- /// Returns the declaration of the named type binder, or null if
- /// no such binder is declared.
- /// </summary>
- public TypeDecl LookUpTypeBinder(string! name)
- {
- for (int i = typeBinders.Count; 0 <= --i; ) {
- TypeBinderDecl td = typeBinders[i];
- if (td.Name == name) {
- return td;
- }
- }
- return null; // not present
- }
- */
- // ------------------------------ Variables ------------------------------
-
- class VarContextNode
- {
- public readonly Hashtable /*string->Variable*/! VarSymbols = new Hashtable /*string->Variable*/();
- public /*maybe null*/ VarContextNode ParentContext;
- public readonly bool Opaque;
-
- public VarContextNode(/*maybe null*/ VarContextNode parentContext, bool opaque)
- {
- ParentContext = parentContext;
- Opaque = opaque;
- }
- }
-
- // symbolic constants, global variables, local variables, formals, expression-bound variables
- VarContextNode! varContext = new VarContextNode(null, false);
-
- /// <summary>
- /// Adds a variable context.
- /// </summary>
- public void PushVarContext()
- {
- varContext = new VarContextNode(varContext, false);
- }
-
- /// <summary>
- /// Adds an opaque variable context, that is, one that blocks all previously pushed contexts.
- /// </summary>
- public void PushOpaqueVarContext()
- {
- varContext = new VarContextNode(varContext, true);
- }
-
- /// <summary>
- /// Requires there to be more than one variable context.
- /// </summary>
- public void PopVarContext()
- {
- assert varContext.ParentContext != null;
- varContext = varContext.ParentContext;
- }
-
- public void AddVariable(Variable! var, bool global)
- {
- if (FindVariable((!)var.Name, !global) != null)
- {
- Error(var, "more than one declaration of variable name: {0}", var.Name);
- }
- else
- {
- varContext.VarSymbols.Add(var.Name, var);
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named variable, or null if
- /// no such variable is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public Variable LookUpVariable(string! name)
- {
- return FindVariable(name, false);
- }
-
- Variable FindVariable(string! name, bool ignoreTopLevelVars)
- {
- VarContextNode c = varContext;
- bool lookOnlyForConstants = false;
- do {
- if (ignoreTopLevelVars && c.ParentContext == null) {
- // this is the top level and we're asked to ignore the top level; hence, we're done
- break;
- }
-
- Variable var = (Variable)c.VarSymbols[name];
- if (var != null && (!lookOnlyForConstants || var is Constant)) {
- return var;
- }
- // not at this level
-
- if (c.Opaque) {
- // from here on, only constants can be looked up
- lookOnlyForConstants = true;
- }
- c = c.ParentContext;
- } while (c != null);
-
- // not present in the relevant levels
- return null;
- }
-
- // ------------------------------ Functions/Procedures ------------------------------
-
- // uninterpreted function symbols, procedures
- Hashtable /*string->DeclWithFormals*/! funcdures = new Hashtable /*string->DeclWithFormals*/ ();
-
- public void AddProcedure(DeclWithFormals! proc)
- {
- if (funcdures[(!)proc.Name] != null)
- {
- Error(proc, "more than one declaration of function/procedure name: {0}", proc.Name);
- }
- else
- {
- funcdures.Add(proc.Name, proc);
- }
- }
-
- /// <summary>
- /// Returns the declaration of the named function/procedure, or null if
- /// no such function or procedure is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public DeclWithFormals LookUpProcedure(string! name)
- {
- return (DeclWithFormals)funcdures[name];
- }
-
- // ------------------------------ Blocks ------------------------------
-
- class ProcedureContext {
- public readonly Hashtable! /*string->Block!*/ Blocks;
- public readonly ProcedureContext Next;
- public ProcedureContext(ProcedureContext next) {
- Blocks = new Hashtable /*string->Block!*/ ();
- Next = next;
- }
- }
- /*maybe null*/ ProcedureContext procedureContext; // stack of procedure contexts
- public bool HasProcedureContext {
- get { return procedureContext != null; }
- }
-
- /// <summary>
- /// Pushes a new procedure context.
- /// </summary>
- public void PushProcedureContext()
- ensures HasProcedureContext;
- {
- procedureContext = new ProcedureContext(procedureContext);
- }
-
- /// <summary>
- /// Requires there to be a procedure context. Pops it.
- /// </summary>
- public void PopProcedureContext()
- requires HasProcedureContext;
- {
- assert procedureContext != null; // follows from precondition
- procedureContext = procedureContext.Next;
- }
-
- /// <summary>
- /// Requires there to be a procedure context.
- /// </summary>
- /// <param name="block"></param>
- public void AddBlock(Block! block)
- requires HasProcedureContext;
- {
- assert procedureContext != null; // follows from precondition
- Hashtable! /*string->Block!*/ blocks = procedureContext.Blocks;
- if (blocks[block.Label] != null)
- {
- Error(block, "more than one declaration of block name: {0}", block.Label);
- }
- else
- {
- blocks.Add(block.Label, block);
- }
- }
-
- /// <summary>
- /// Requires there to be a procedure context.
- /// Returns the declaration of the named block, or null if
- /// no such block is declared.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public Block LookUpBlock(string! name)
- requires HasProcedureContext;
- {
- assert procedureContext != null; // follows from precondition
- Hashtable! /*string->Block!*/ blocks = procedureContext.Blocks;
- return (Block)blocks[name];
- }
-
- // ------------------------------ Flags ------------------------------
-
- public enum State { StateLess, Single, Two }
- State stateMode = State.Single;
-
- /// <summary>
- /// To increase our confidence in that the caller knows what it's doing, we only allow
- /// the state mode to be changed in and out of the State.Single mode.
- /// </summary>
- public State StateMode {
- get {
- return stateMode;
- }
- set {
- assert value != stateMode;
- assert stateMode == State.Single || value == State.Single;
- expose (this) {
- stateMode = value;
- }
- }
- }
-
- bool triggerMode = false;
-
- /// <summary>
- /// Setting TriggerMode is allowed only if the setting has the effect of toggling the
- /// boolean. That is, TriggerMode can be set to true only if it previously was false,
- /// and TriggerMode can be set to false only if it previously was true.
- /// </summary>
- public bool TriggerMode
- {
- get
- {
- return triggerMode;
- }
- set
- {
- assert triggerMode != value;
- expose (this) {
- triggerMode = value;
- }
- }
- }
- }
-
- public class TypecheckingContext : CheckingContext
- {
- public IdentifierExprSeq Frame; // used in checking the assignment targets of implementation bodies
-
- public TypecheckingContext(IErrorSink errorSink)
- {
- base(errorSink);
- }
-
- public bool InFrame(Variable! v)
- requires Frame != null;
- {
- return exists{IdentifierExpr! ie in Frame; ie.Decl == v};
- }
- }
-}
diff --git a/Source/Core/Scanner.ssc b/Source/Core/Scanner.ssc
deleted file mode 100644
index 870720d3..00000000
--- a/Source/Core/Scanner.ssc
+++ /dev/null
@@ -1,726 +0,0 @@
-
-using System;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-using Microsoft.Contracts;
-using Microsoft.Boogie;
-using BoogiePL;
-
-
-namespace Microsoft.Boogie {
-
-//-----------------------------------------------------------------------------------
-// Buffer
-//-----------------------------------------------------------------------------------
-public class Buffer {
- // This Buffer supports the following cases:
- // 1) seekable stream (file)
- // a) whole stream in buffer
- // b) part of stream in buffer
- // 2) non seekable stream (network, console)
-
- public const int EOF = 65535 + 1; // char.MaxValue + 1;
- const int MIN_BUFFER_LENGTH = 1024; // 1KB
- const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
- byte[]! buf; // input buffer
- int bufStart; // position of first byte in buffer relative to input stream
- int bufLen; // length of buffer
- int fileLen; // length of input stream (may change if the stream is no file)
- int bufPos; // current position in buffer
- Stream! stream; // input stream (seekable)
- bool isUserStream; // was the stream opened by the user?
-
- [NotDelayed]
- public Buffer (Stream! s, bool isUserStream) {
- stream = s; this.isUserStream = isUserStream;
-
- int fl, bl;
- if (s.CanSeek) {
- fl = (int) s.Length;
- bl = fl < MAX_BUFFER_LENGTH ? fl : MAX_BUFFER_LENGTH; // Math.Min(fileLen, MAX_BUFFER_LENGTH);
- bufStart = Int32.MaxValue; // nothing in the buffer so far
- } else {
- fl = bl = bufStart = 0;
- }
-
- buf = new byte[(bl>0) ? bl : MIN_BUFFER_LENGTH];
- fileLen = fl; bufLen = bl;
- base();
- if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
- else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
- if (bufLen == fileLen && s.CanSeek) Close();
- }
-
- protected Buffer(Buffer! b) { // called in UTF8Buffer constructor
- buf = b.buf;
- bufStart = b.bufStart;
- bufLen = b.bufLen;
- fileLen = b.fileLen;
- bufPos = b.bufPos;
- stream = b.stream;
- // keep destructor from closing the stream
- //b.stream = null;
- isUserStream = b.isUserStream;
- // keep destructor from closing the stream
- b.isUserStream = true;
- }
-
- ~Buffer() { Close(); }
-
- protected void Close() {
- if (!isUserStream && stream != null) {
- stream.Close();
- //stream = null;
- }
- }
-
- public virtual int Read () {
- if (bufPos < bufLen) {
- return buf[bufPos++];
- } else if (Pos < fileLen) {
- Pos = Pos; // shift buffer start to Pos
- return buf[bufPos++];
- } else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
- return buf[bufPos++];
- } else {
- return EOF;
- }
- }
-
- public int Peek () {
- int curPos = Pos;
- int ch = Read();
- Pos = curPos;
- return ch;
- }
-
- public string! GetString (int beg, int end) {
- int len = 0;
- char[] buf = new char[end - beg];
- int oldPos = Pos;
- Pos = beg;
- while (Pos < end) buf[len++] = (char) Read();
- Pos = oldPos;
- return new String(buf, 0, len);
- }
-
- public int Pos {
- get { return bufPos + bufStart; }
- set {
- if (value >= fileLen && stream != null && !stream.CanSeek) {
- // Wanted position is after buffer and the stream
- // is not seek-able e.g. network or console,
- // thus we have to read the stream manually till
- // the wanted position is in sight.
- while (value >= fileLen && ReadNextStreamChunk() > 0);
- }
-
- if (value < 0 || value > fileLen) {
- throw new FatalError("buffer out of bounds access, position: " + value);
- }
-
- if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
- bufPos = value - bufStart;
- } else if (stream != null) { // must be swapped in
- stream.Seek(value, SeekOrigin.Begin);
- bufLen = stream.Read(buf, 0, buf.Length);
- bufStart = value; bufPos = 0;
- } else {
- // set the position to the end of the file, Pos will return fileLen.
- bufPos = fileLen - bufStart;
- }
- }
- }
-
- // Read the next chunk of bytes from the stream, increases the buffer
- // if needed and updates the fields fileLen and bufLen.
- // Returns the number of bytes read.
- private int ReadNextStreamChunk() {
- int free = buf.Length - bufLen;
- if (free == 0) {
- // in the case of a growing input stream
- // we can neither seek in the stream, nor can we
- // foresee the maximum length, thus we must adapt
- // the buffer size on demand.
- byte[] newBuf = new byte[bufLen * 2];
- Array.Copy(buf, newBuf, bufLen);
- buf = newBuf;
- free = bufLen;
- }
- int read = stream.Read(buf, bufLen, free);
- if (read > 0) {
- fileLen = bufLen = (bufLen + read);
- return read;
- }
- // end of stream reached
- return 0;
- }
-}
-
-//-----------------------------------------------------------------------------------
-// UTF8Buffer
-//-----------------------------------------------------------------------------------
-public class UTF8Buffer: Buffer {
- public UTF8Buffer(Buffer! b): base(b) {}
-
- public override int Read() {
- int ch;
- do {
- ch = base.Read();
- // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
- } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
- if (ch < 128 || ch == EOF) {
- // nothing to do, first 127 chars are the same in ascii and utf8
- // 0xxxxxxx or end of file character
- } else if ((ch & 0xF0) == 0xF0) {
- // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x07; ch = base.Read();
- int c2 = ch & 0x3F; ch = base.Read();
- int c3 = ch & 0x3F; ch = base.Read();
- int c4 = ch & 0x3F;
- ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
- } else if ((ch & 0xE0) == 0xE0) {
- // 1110xxxx 10xxxxxx 10xxxxxx
- int c1 = ch & 0x0F; ch = base.Read();
- int c2 = ch & 0x3F; ch = base.Read();
- int c3 = ch & 0x3F;
- ch = (((c1 << 6) | c2) << 6) | c3;
- } else if ((ch & 0xC0) == 0xC0) {
- // 110xxxxx 10xxxxxx
- int c1 = ch & 0x1F; ch = base.Read();
- int c2 = ch & 0x3F;
- ch = (c1 << 6) | c2;
- }
- return ch;
- }
-}
-
-//-----------------------------------------------------------------------------------
-// Scanner
-//-----------------------------------------------------------------------------------
-public class Scanner {
- const char EOL = '\n';
- const int eofSym = 0; /* pdt */
- const int maxT = 88;
- const int noSym = 88;
-
-
- public Buffer! buffer; // scanner buffer
-
- Token! t; // current token
- int ch; // current input character
- int pos; // byte position of current character
- int col; // column number of current character
- int line; // line number of current character
- int oldEols; // EOLs that appeared in a comment;
- static readonly Hashtable! start; // maps first token character to start state
-
- Token! tokens; // list of tokens already peeked (first token is a dummy)
- Token! pt; // current peek token
-
- char[]! tval = new char[128]; // text of current token
- int tlen; // length of current token
-
- private string! Filename;
- private Errors! errorHandler;
-
- static Scanner() {
- start = new Hashtable(128);
- for (int i = 35; i <= 36; ++i) start[i] = 2;
- for (int i = 39; i <= 39; ++i) start[i] = 2;
- for (int i = 46; i <= 46; ++i) start[i] = 2;
- for (int i = 63; i <= 63; ++i) start[i] = 2;
- for (int i = 65; i <= 90; ++i) start[i] = 2;
- for (int i = 94; i <= 122; ++i) start[i] = 2;
- for (int i = 126; i <= 126; ++i) start[i] = 2;
- for (int i = 48; i <= 57; ++i) start[i] = 9;
- for (int i = 34; i <= 34; ++i) start[i] = 6;
- start[92] = 1;
- start[59] = 10;
- start[40] = 11;
- start[41] = 12;
- start[58] = 47;
- start[44] = 13;
- start[91] = 14;
- start[93] = 15;
- start[60] = 48;
- start[62] = 49;
- start[123] = 16;
- start[125] = 50;
- start[61] = 51;
- start[42] = 17;
- start[8660] = 20;
- start[8658] = 22;
- start[8656] = 23;
- start[38] = 24;
- start[8743] = 26;
- start[124] = 52;
- start[8744] = 28;
- start[33] = 53;
- start[8800] = 32;
- start[8804] = 33;
- start[8805] = 34;
- start[43] = 54;
- start[45] = 36;
- start[47] = 37;
- start[37] = 38;
- start[172] = 39;
- start[8704] = 42;
- start[8707] = 43;
- start[955] = 44;
- start[8226] = 46;
- start[Buffer.EOF] = -1;
-
- }
-
- [NotDelayed]
- public Scanner (string! fileName, Errors! errorHandler) {
- this.errorHandler = errorHandler;
- pt = tokens = new Token(); // first token is a dummy
- t = new Token(); // dummy because t is a non-null field
- try {
- Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
- buffer = new Buffer(stream, false);
- Filename = fileName;
- base();
- Init();
- } catch (IOException) {
- throw new FatalError("Cannot open file " + fileName);
- }
- }
-
- [NotDelayed]
- public Scanner (Stream! s, Errors! errorHandler, string! fileName) {
- pt = tokens = new Token(); // first token is a dummy
- t = new Token(); // dummy because t is a non-null field
- buffer = new Buffer(s, true);
- this.errorHandler = errorHandler;
- this.Filename = fileName;
- base();
- Init();
- }
-
- void Init() {
- pos = -1; line = 1; col = 0;
- oldEols = 0;
- NextCh();
- if (ch == 0xEF) { // check optional byte order mark for UTF-8
- NextCh(); int ch1 = ch;
- NextCh(); int ch2 = ch;
- if (ch1 != 0xBB || ch2 != 0xBF) {
- throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
- }
- buffer = new UTF8Buffer(buffer); col = 0;
- NextCh();
- }
- pt = tokens = new Token(); // first token is a dummy
- }
-
- string! ReadToEOL(){
- int p = buffer.Pos;
- int ch = buffer.Read();
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- while (ch != EOL && ch != Buffer.EOF){
- ch = buffer.Read();
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- }
- string! s = buffer.GetString(p, buffer.Pos);
- return s;
- }
-
- void NextCh() {
- if (oldEols > 0) { ch = EOL; oldEols--; }
- else {
-// pos = buffer.Pos;
-// ch = buffer.Read(); col++;
-// // replace isolated '\r' by '\n' in order to make
-// // eol handling uniform across Windows, Unix and Mac
-// if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
-// if (ch == EOL) { line++; col = 0; }
-
- while (true) {
- pos = buffer.Pos;
- ch = buffer.Read(); col++;
- // replace isolated '\r' by '\n' in order to make
- // eol handling uniform across Windows, Unix and Mac
- if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
- if (ch == EOL) {
- line++; col = 0;
- } else if (ch == '#' && col == 1) {
- int prLine = line;
- int prColumn = 0;
-
- string! hashLine = ReadToEOL();
- col = 0;
- line++;
-
- hashLine = hashLine.TrimEnd(null);
- if (hashLine.StartsWith("line ") || hashLine == "line") {
- // parse #line pragma: #line num [filename]
- string h = hashLine.Substring(4).TrimStart(null);
- int x = h.IndexOf(' ');
- if (x == -1) {
- x = h.Length; // this will be convenient below when we look for a filename
- }
- try {
- int li = int.Parse(h.Substring(0, x));
-
- h = h.Substring(x).Trim();
-
- // act on #line
- line = li;
- if (h.Length != 0) {
- // a filename was specified
- Filename = h;
- }
- continue; // successfully parsed and acted on the #line pragma
-
- } catch (FormatException) {
- // just fall down through to produce an error message
- }
- this.errorHandler.SemErr(Filename, prLine, prColumn, "Malformed (#line num [filename]) pragma: #" + hashLine);
- continue;
- }
-
- this.errorHandler.SemErr(Filename, prLine, prColumn, "Unrecognized pragma: #" + hashLine);
- continue;
- }
- return;
- }
-
-
- }
-
- }
-
- void AddCh() {
- if (tlen >= tval.Length) {
- char[] newBuf = new char[2 * tval.Length];
- Array.Copy(tval, 0, newBuf, 0, tval.Length);
- tval = newBuf;
- }
- if (ch != Buffer.EOF) {
- tval[tlen++] = (char) ch;
- NextCh();
- }
- }
-
-
-
- bool Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
- NextCh();
- if (ch == '/') {
- NextCh();
- for(;;) {
- if (ch == 10) {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- } else if (ch == Buffer.EOF) return false;
- else NextCh();
- }
- } else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
- }
- return false;
- }
-
- bool Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
- NextCh();
- if (ch == '*') {
- NextCh();
- for(;;) {
- if (ch == '*') {
- NextCh();
- if (ch == '/') {
- level--;
- if (level == 0) { oldEols = line - line0; NextCh(); return true; }
- NextCh();
- }
- } else if (ch == '/') {
- NextCh();
- if (ch == '*') {
- level++; NextCh();
- }
- } else if (ch == Buffer.EOF) return false;
- else NextCh();
- }
- } else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
- }
- return false;
- }
-
-
- void CheckLiteral() {
- switch (t.val) {
- case "var": t.kind = 6; break;
- case "where": t.kind = 12; break;
- case "int": t.kind = 13; break;
- case "bool": t.kind = 14; break;
- case "const": t.kind = 19; break;
- case "unique": t.kind = 20; break;
- case "extends": t.kind = 21; break;
- case "complete": t.kind = 22; break;
- case "function": t.kind = 23; break;
- case "returns": t.kind = 24; break;
- case "axiom": t.kind = 27; break;
- case "type": t.kind = 28; break;
- case "procedure": t.kind = 30; break;
- case "implementation": t.kind = 31; break;
- case "modifies": t.kind = 32; break;
- case "free": t.kind = 33; break;
- case "requires": t.kind = 34; break;
- case "ensures": t.kind = 35; break;
- case "goto": t.kind = 36; break;
- case "return": t.kind = 37; break;
- case "if": t.kind = 38; break;
- case "else": t.kind = 39; break;
- case "while": t.kind = 40; break;
- case "invariant": t.kind = 41; break;
- case "break": t.kind = 43; break;
- case "assert": t.kind = 44; break;
- case "assume": t.kind = 45; break;
- case "havoc": t.kind = 46; break;
- case "call": t.kind = 48; break;
- case "forall": t.kind = 49; break;
- case "false": t.kind = 75; break;
- case "true": t.kind = 76; break;
- case "old": t.kind = 77; break;
- case "then": t.kind = 80; break;
- case "exists": t.kind = 82; break;
- case "lambda": t.kind = 84; break;
- default: break;
- }
- }
-
- Token! NextToken() {
- while (ch == ' ' ||
- ch >= 9 && ch <= 10 || ch == 13
- ) NextCh();
- if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
- int recKind = noSym;
- int recEnd = pos;
- t = new Token();
- t.pos = pos; t.col = col; t.line = line;
- t.filename = this.Filename;
- int state;
- if (start.ContainsKey(ch)) { state = (int) (!) start[ch]; }
- else { state = 0; }
- tlen = 0; AddCh();
-
- switch (state) {
- case -1: { t.kind = eofSym; break; } // NextCh already done
- case 0: {
- if (recKind != noSym) {
- tlen = recEnd - t.pos;
- SetScannerBehindT();
- }
- t.kind = recKind; break;
- } // NextCh already done
- case 1:
- if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
- else {goto case 0;}
- case 2:
- recEnd = pos; recKind = 1;
- if (ch >= '#' && ch <= '$' || ch == 39 || ch == '.' || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch >= '^' && ch <= 'z' || ch == '~') {AddCh(); goto case 2;}
- else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 3:
- if (ch == 'v') {AddCh(); goto case 4;}
- else {goto case 0;}
- case 4:
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
- else {goto case 0;}
- case 5:
- recEnd = pos; recKind = 2;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 5;}
- else {t.kind = 2; break;}
- case 6:
- if (ch == '"') {AddCh(); goto case 7;}
- else if (ch >= ' ' && ch <= '!' || ch >= '#' && ch <= '~') {AddCh(); goto case 6;}
- else {goto case 0;}
- case 7:
- {t.kind = 4; break;}
- case 8:
- recEnd = pos; recKind = 5;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 8;}
- else {t.kind = 5; break;}
- case 9:
- recEnd = pos; recKind = 3;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
- else if (ch == 'b') {AddCh(); goto case 3;}
- else if (ch == '.') {AddCh(); goto case 8;}
- else {t.kind = 3; break;}
- case 10:
- {t.kind = 7; break;}
- case 11:
- {t.kind = 8; break;}
- case 12:
- {t.kind = 9; break;}
- case 13:
- {t.kind = 11; break;}
- case 14:
- {t.kind = 15; break;}
- case 15:
- {t.kind = 16; break;}
- case 16:
- {t.kind = 25; break;}
- case 17:
- {t.kind = 42; break;}
- case 18:
- {t.kind = 47; break;}
- case 19:
- {t.kind = 50; break;}
- case 20:
- {t.kind = 51; break;}
- case 21:
- {t.kind = 52; break;}
- case 22:
- {t.kind = 53; break;}
- case 23:
- {t.kind = 55; break;}
- case 24:
- if (ch == '&') {AddCh(); goto case 25;}
- else {goto case 0;}
- case 25:
- {t.kind = 56; break;}
- case 26:
- {t.kind = 57; break;}
- case 27:
- {t.kind = 58; break;}
- case 28:
- {t.kind = 59; break;}
- case 29:
- {t.kind = 62; break;}
- case 30:
- {t.kind = 63; break;}
- case 31:
- {t.kind = 64; break;}
- case 32:
- {t.kind = 65; break;}
- case 33:
- {t.kind = 66; break;}
- case 34:
- {t.kind = 67; break;}
- case 35:
- {t.kind = 68; break;}
- case 36:
- {t.kind = 70; break;}
- case 37:
- {t.kind = 71; break;}
- case 38:
- {t.kind = 72; break;}
- case 39:
- {t.kind = 74; break;}
- case 40:
- {t.kind = 78; break;}
- case 41:
- {t.kind = 79; break;}
- case 42:
- {t.kind = 81; break;}
- case 43:
- {t.kind = 83; break;}
- case 44:
- {t.kind = 85; break;}
- case 45:
- {t.kind = 86; break;}
- case 46:
- {t.kind = 87; break;}
- case 47:
- recEnd = pos; recKind = 10;
- if (ch == '=') {AddCh(); goto case 18;}
- else if (ch == ':') {AddCh(); goto case 45;}
- else {t.kind = 10; break;}
- case 48:
- recEnd = pos; recKind = 17;
- if (ch == '=') {AddCh(); goto case 55;}
- else if (ch == ':') {AddCh(); goto case 31;}
- else {t.kind = 17; break;}
- case 49:
- recEnd = pos; recKind = 18;
- if (ch == '=') {AddCh(); goto case 29;}
- else {t.kind = 18; break;}
- case 50:
- recEnd = pos; recKind = 26;
- if (ch == '|') {AddCh(); goto case 41;}
- else {t.kind = 26; break;}
- case 51:
- recEnd = pos; recKind = 29;
- if (ch == '=') {AddCh(); goto case 56;}
- else {t.kind = 29; break;}
- case 52:
- if (ch == '|') {AddCh(); goto case 27;}
- else if (ch == '{') {AddCh(); goto case 40;}
- else {goto case 0;}
- case 53:
- recEnd = pos; recKind = 73;
- if (ch == '=') {AddCh(); goto case 30;}
- else {t.kind = 73; break;}
- case 54:
- recEnd = pos; recKind = 69;
- if (ch == '+') {AddCh(); goto case 35;}
- else {t.kind = 69; break;}
- case 55:
- recEnd = pos; recKind = 61;
- if (ch == '=') {AddCh(); goto case 57;}
- else {t.kind = 61; break;}
- case 56:
- recEnd = pos; recKind = 60;
- if (ch == '>') {AddCh(); goto case 21;}
- else {t.kind = 60; break;}
- case 57:
- recEnd = pos; recKind = 54;
- if (ch == '>') {AddCh(); goto case 19;}
- else {t.kind = 54; break;}
-
- }
- t.val = new String(tval, 0, tlen);
- return t;
- }
-
- private void SetScannerBehindT() {
- buffer.Pos = t.pos;
- NextCh();
- line = t.line; col = t.col;
- for (int i = 0; i < tlen; i++) NextCh();
- }
-
- // get the next token (possibly a token already seen during peeking)
- public Token! Scan () {
- if (tokens.next == null) {
- return NextToken();
- } else {
- pt = tokens = tokens.next;
- return tokens;
- }
- }
-
- // peek for the next token, ignore pragmas
- public Token! Peek () {
- do {
- if (pt.next == null) {
- pt.next = NextToken();
- }
- pt = pt.next;
- } while (pt.kind > maxT); // skip pragmas
-
- return pt;
- }
-
- // make sure that peeking starts at the current scan position
- public void ResetPeek () { pt = tokens; }
-
-} // end Scanner
-
-public delegate void ErrorProc(int n, string filename, int line, int col);
-
-
-} \ No newline at end of file
diff --git a/Source/Core/StandardVisitor.ssc b/Source/Core/StandardVisitor.ssc
deleted file mode 100644
index 10984ff3..00000000
--- a/Source/Core/StandardVisitor.ssc
+++ /dev/null
@@ -1,503 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------
-// BoogiePL - StandardVisitor.cs
-//---------------------------------------------------------------------------------------------
-
-using System.Collections.Generic;
-
-namespace Microsoft.Boogie
-{
- /// <summary>
- /// Base for all classes that process the Absy using the visitor pattern.
- /// </summary>
- public abstract class Visitor
- {
- /// <summary>
- /// Switches on node.NodeType to call a visitor method that has been specialized for node.
- /// </summary>
- /// <param name="a">The Absy node to be visited.</param>
- /// <returns> Returns null if node is null. Otherwise returns an updated node (possibly a different object).</returns>
- public abstract Absy! Visit (Absy! node);
-
- /// <summary>
- /// Transfers the state from one visitor to another. This enables separate visitor instances to cooperative process a single IR.
- /// </summary>
- public virtual void TransferStateTo(Visitor targetVisitor)
- {
- }
-
- public virtual ExprSeq! VisitExprSeq(ExprSeq! list)
- {
- for( int i = 0, n = list.Length; i < n; i++)
- list[i] = (Expr)this.Visit( (!) list[i]);
- return list;
- }
- }
-
- /// <summary>
- /// Walks an IR, mutuating it into a new form
- /// </summary>
- public abstract class StandardVisitor: Visitor
- {
- public Visitor callingVisitor;
-
- public StandardVisitor()
- {
- }
- public StandardVisitor(Visitor callingVisitor)
- {
- this.callingVisitor = callingVisitor;
- }
- public override Absy! Visit (Absy! node)
- {
- return node.StdDispatch(this);
- }
- public virtual AIVariableExpr! VisitAIVariableExpr(AIVariableExpr! node)
- {
- return node;
- }
- public virtual Cmd! VisitAssertCmd(AssertCmd! node)
- {
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Cmd! VisitAssignCmd(AssignCmd! node)
- {
- for (int i = 0; i < node.Lhss.Count; ++i) {
- node.Lhss[i] = (AssignLhs!)this.Visit(node.Lhss[i]);
- node.Rhss[i] = (Expr!)this.Visit(node.Rhss[i]);
- }
- return node;
- }
- public virtual Cmd! VisitAssumeCmd(AssumeCmd! node)
- {
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual AtomicRE! VisitAtomicRE(AtomicRE! node)
- {
- node.b = this.VisitBlock(node.b);
- return node;
- }
- public virtual Axiom! VisitAxiom(Axiom! node)
- {
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Type! VisitBasicType(BasicType! node)
- {
- return this.VisitType(node);
- }
- public virtual BvConcatExpr! VisitBvConcatExpr(BvConcatExpr! node)
- {
- node.E0 = this.VisitExpr(node.E0);
- node.E1 = this.VisitExpr(node.E1);
- return node;
- }
- public virtual Type! VisitBvType(BvType! node)
- {
- return this.VisitType(node);
- }
- public virtual Type! VisitBvTypeProxy(BvTypeProxy! node)
- {
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return (Type)this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
- public virtual Block! VisitBlock(Block! node)
- {
- node.Cmds = this.VisitCmdSeq(node.Cmds);
- node.TransferCmd = (TransferCmd)this.Visit((!)node.TransferCmd);
- return node;
- }
- public virtual Expr! VisitCodeExpr(CodeExpr! node)
- {
- node.LocVars = this.VisitVariableSeq(node.LocVars);
- node.Blocks = this.VisitBlockList(node.Blocks);
- return node;
- }
- public virtual BlockSeq! VisitBlockSeq(BlockSeq! blockSeq)
- {
- for (int i = 0, n = blockSeq.Length; i < n; i++)
- blockSeq[i] = this.VisitBlock( (!)blockSeq[i]);
- return blockSeq;
- }
- public virtual List<Block!>! VisitBlockList(List<Block!>! blocks)
- {
- for (int i = 0, n = blocks.Count; i < n; i++) {
- blocks[i] = this.VisitBlock(blocks[i]);
- }
- return blocks;
- }
- public virtual BoundVariable! VisitBoundVariable(BoundVariable! node)
- {
- node = (BoundVariable) this.VisitVariable(node);
- return node;
- }
- public virtual Cmd! VisitCallCmd(CallCmd! node)
- {
- for (int i = 0; i < node.Ins.Count; ++i)
- if (node.Ins[i] != null)
- node.Ins[i] = this.VisitExpr((!)node.Ins[i]);
- for (int i = 0; i < node.Outs.Count; ++i)
- if (node.Outs[i] != null)
- node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr((!)node.Outs[i]);
- return node;
- }
- public virtual Cmd! VisitCallForallCmd(CallForallCmd! node)
- {
- List<Expr> elist = new List<Expr>(node.Ins.Count);
- foreach (Expr arg in node.Ins) {
- if (arg == null) {
- elist.Add(null);
- } else {
- elist.Add(this.VisitExpr(arg));
- }
- }
- node.Ins = elist;
- node.Proc = this.VisitProcedure((!)node.Proc);
- return node;
- }
- public virtual CmdSeq! VisitCmdSeq(CmdSeq! cmdSeq)
- {
- for (int i = 0, n = cmdSeq.Length; i < n; i++)
- cmdSeq[i] = (Cmd) this.Visit( (!)cmdSeq[i]); // call general Visit so subtypes of Cmd get visited by their particular visitor
- return cmdSeq;
- }
- public virtual Choice! VisitChoice(Choice! node)
- {
- node.rs = this.VisitRESeq(node.rs);
- return node;
- }
- public virtual Cmd! VisitCommentCmd(CommentCmd! node)
- {
- return node;
- }
- public virtual Constant! VisitConstant(Constant! node)
- {
- return node;
- }
- public virtual CtorType! VisitCtorType(CtorType! node)
- {
- for (int i = 0; i < node.Arguments.Length; ++i)
- node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
- return node;
- }
- public virtual Declaration! VisitDeclaration(Declaration! node)
- {
- return node;
- }
- public virtual List<Declaration!>! VisitDeclarationList(List<Declaration!>! declarationList)
- {
- for (int i = 0, n = declarationList.Count; i < n; i++)
- declarationList[i] = (Declaration!) this.Visit(declarationList[i]);
- return declarationList;
- }
- public virtual DeclWithFormals! VisitDeclWithFormals(DeclWithFormals! node)
- {
- node.InParams = this.VisitVariableSeq(node.InParams);
- node.OutParams = this.VisitVariableSeq(node.OutParams);
- return node;
- }
- public virtual ExistsExpr! VisitExistsExpr(ExistsExpr! node)
- {
- node = (ExistsExpr) this.VisitQuantifierExpr(node);
- return node;
- }
- public virtual BvExtractExpr! VisitBvExtractExpr(BvExtractExpr! node)
- {
- node.Bitvector = this.VisitExpr(node.Bitvector);
- return node;
- }
- public virtual Expr! VisitExpr(Expr! node)
- {
- Expr e = (Expr) this.Visit(node);
- return e;
- }
- public override ExprSeq! VisitExprSeq(ExprSeq! exprSeq)
- {
- for (int i = 0, n = exprSeq.Length; i < n; i++)
- exprSeq[i] = this.VisitExpr( (!)exprSeq[i]);
- return exprSeq;
- }
- public virtual Requires! VisitRequires(Requires! @requires)
- {
- @requires.Condition = this.VisitExpr(@requires.Condition);
- return @requires;
- }
- public virtual RequiresSeq! VisitRequiresSeq(RequiresSeq! requiresSeq)
- {
- for (int i = 0, n = requiresSeq.Length; i < n; i++)
- requiresSeq[i] = this.VisitRequires(requiresSeq[i]);
- return requiresSeq;
- }
- public virtual Ensures! VisitEnsures(Ensures! @ensures)
- {
- @ensures.Condition = this.VisitExpr(@ensures.Condition);
- return @ensures;
- }
- public virtual EnsuresSeq! VisitEnsuresSeq(EnsuresSeq! ensuresSeq)
- {
- for (int i = 0, n = ensuresSeq.Length; i < n; i++)
- ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
- return ensuresSeq;
- }
- public virtual ForallExpr! VisitForallExpr(ForallExpr! node)
- {
- node = (ForallExpr) this.VisitQuantifierExpr(node);
- return node;
- }
- public virtual LambdaExpr! VisitLambdaExpr(LambdaExpr! node)
- {
- node = (LambdaExpr) this.VisitBinderExpr(node);
- return node;
- }
- public virtual Formal! VisitFormal(Formal! node)
- {
- return node;
- }
- public virtual Function! VisitFunction(Function! node)
- {
- node = (Function) this.VisitDeclWithFormals(node);
- if (node.Body != null)
- node.Body = this.VisitExpr(node.Body);
- return node;
- }
- public virtual GlobalVariable! VisitGlobalVariable(GlobalVariable! node)
- {
- node = (GlobalVariable) this.VisitVariable(node);
- return node;
- }
- public virtual GotoCmd! VisitGotoCmd(GotoCmd! node)
- {
- // do not visit the labelTargets, or control-flow loops will lead to a looping visitor
- return node;
- }
- public virtual Cmd! VisitHavocCmd(HavocCmd! node)
- {
- node.Vars = this.VisitIdentifierExprSeq(node.Vars);
- return node;
- }
- public virtual Expr! VisitIdentifierExpr(IdentifierExpr! node)
- {
- if (node.Decl != null)
- node.Decl = this.VisitVariable(node.Decl);
- return node;
- }
- public virtual IdentifierExprSeq! VisitIdentifierExprSeq(IdentifierExprSeq! identifierExprSeq)
- {
- for (int i = 0, n = identifierExprSeq.Length; i < n; i++)
- identifierExprSeq[i] = (IdentifierExpr) this.VisitIdentifierExpr( (!)identifierExprSeq[i]);
- return identifierExprSeq;
- }
- public virtual Implementation! VisitImplementation(Implementation! node)
- {
- node.LocVars = this.VisitVariableSeq(node.LocVars);
- node.Blocks = this.VisitBlockList(node.Blocks);
- node.Proc = this.VisitProcedure((!)node.Proc);
- node = (Implementation) this.VisitDeclWithFormals(node); // do this first or last?
- return node;
- }
- public virtual LiteralExpr! VisitLiteralExpr(LiteralExpr! node)
- {
- return node;
- }
-
- public virtual LocalVariable! VisitLocalVariable(LocalVariable! node)
- {
- return node;
- }
-
- public virtual AssignLhs! VisitMapAssignLhs(MapAssignLhs! node)
- {
- node.Map = (AssignLhs!)this.Visit(node.Map);
- for (int i = 0; i < node.Indexes.Count; ++i)
- node.Indexes[i] = (Expr!)this.Visit(node.Indexes[i]);
- return node;
- }
- public virtual MapType! VisitMapType(MapType! node)
- {
- // not doing anything about the bound variables ... maybe
- // these should be visited as well ...
- //
- // NOTE: when overriding this method, you have to make sure that
- // the bound variables of the map type are updated correctly
- for (int i = 0; i < node.Arguments.Length; ++i)
- node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
- node.Result = (Type!)this.Visit(node.Result);
- return node;
- }
- public virtual Type! VisitMapTypeProxy(MapTypeProxy! node)
- {
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return (Type)this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
-
- public virtual Expr! VisitNAryExpr(NAryExpr! node)
- {
- node.Args = this.VisitExprSeq(node.Args);
- return node;
- }
- public virtual Expr! VisitOldExpr(OldExpr! node)
- {
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Procedure! VisitProcedure(Procedure! node)
- {
- node.Ensures = this.VisitEnsuresSeq(node.Ensures);
- node.InParams = this.VisitVariableSeq(node.InParams);
- node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
- node.OutParams = this.VisitVariableSeq(node.OutParams);
- node.Requires = this.VisitRequiresSeq(node.Requires);
- return node;
- }
- public virtual Program! VisitProgram(Program! node)
- {
- node.TopLevelDeclarations = this.VisitDeclarationList(node.TopLevelDeclarations);
- return node;
- }
- public virtual BinderExpr! VisitBinderExpr(BinderExpr! node)
- {
- node.Body = this.VisitExpr(node.Body);
- node.Dummies = this.VisitVariableSeq(node.Dummies);
- //node.Type = this.VisitType(node.Type);
- return node;
- }
- public virtual QuantifierExpr! VisitQuantifierExpr(QuantifierExpr! node)
- {
- node = (QuantifierExpr!) this.VisitBinderExpr(node);
- if (node.Triggers != null) {
- node.Triggers = this.VisitTrigger(node.Triggers);
- }
- return node;
- }
- public virtual Cmd! VisitRE(RE! node)
- {
- return (Cmd) this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
- }
- public virtual RESeq! VisitRESeq(RESeq! reSeq)
- {
- for (int i = 0, n = reSeq.Length; i < n; i++)
- reSeq[i] = (RE) this.VisitRE( (!)reSeq[i]);
- return reSeq;
- }
- public virtual ReturnCmd! VisitReturnCmd(ReturnCmd! node)
- {
- return (ReturnCmd) this.VisitTransferCmd(node);
- }
- public virtual ReturnExprCmd! VisitReturnExprCmd(ReturnExprCmd! node)
- {
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Sequential! VisitSequential(Sequential! node)
- {
- node.first = (RE) this.VisitRE(node.first);
- node.second = (RE) this.VisitRE(node.second);
- return node;
- }
- public virtual AssignLhs! VisitSimpleAssignLhs(SimpleAssignLhs! node)
- {
- node.AssignedVariable =
- (IdentifierExpr) this.VisitIdentifierExpr(node.AssignedVariable);
- return node;
- }
- public virtual Cmd! VisitStateCmd(StateCmd! node)
- {
- node.Locals = this.VisitVariableSeq(node.Locals);
- node.Cmds = this.VisitCmdSeq(node.Cmds);
- return node;
- }
- public virtual TransferCmd! VisitTransferCmd(TransferCmd! node)
- {
- return node;
- }
- public virtual Trigger! VisitTrigger(Trigger! node)
- {
- Trigger origNext = node.Next;
- if (origNext != null) {
- Trigger newNext = this.VisitTrigger(origNext);
- if (newNext != origNext) {
- node = new Trigger(node.tok, node.Pos, node.Tr); // note: this creates sharing between the old and new Tr sequence
- node.Next = newNext;
- }
- }
- node.Tr = this.VisitExprSeq(node.Tr);
- return node;
- }
- // called by default for all nullary type constructors and type variables
- public virtual Type! VisitType(Type! node)
- {
- return node;
- }
- public virtual TypedIdent! VisitTypedIdent(TypedIdent! node)
- {
- node.Type = (Type)this.Visit(node.Type);
- return node;
- }
- public virtual Declaration! VisitTypeCtorDecl(TypeCtorDecl! node)
- {
- return this.VisitDeclaration(node);
- }
- public virtual Type! VisitTypeSynonymAnnotation(TypeSynonymAnnotation! node)
- {
- node.ExpandedType = (Type!)this.Visit(node.ExpandedType);
- for (int i = 0; i < node.Arguments.Length; ++i)
- node.Arguments[i] = (Type!)this.Visit(node.Arguments[i]);
- return node;
- }
- public virtual Declaration! VisitTypeSynonymDecl(TypeSynonymDecl! node)
- {
- return this.VisitDeclaration(node);
- }
- public virtual Type! VisitTypeVariable(TypeVariable! node)
- {
- return this.VisitType(node);
- }
- public virtual Type! VisitTypeProxy(TypeProxy! node)
- {
- // if the type proxy is instantiated with some more
- // specific type, we visit the instantiation
- if (node.ProxyFor != null)
- return (Type!)this.Visit(node.ProxyFor);
- return this.VisitType(node);
- }
- public virtual Type! VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier! node)
- {
- return this.VisitType(node);
- }
- public virtual Variable! VisitVariable(Variable! node)
- {
- node.TypedIdent = this.VisitTypedIdent(node.TypedIdent);
- return node;
- }
- public virtual VariableSeq! VisitVariableSeq(VariableSeq! variableSeq)
- {
- for (int i = 0, n = variableSeq.Length; i < n; i++)
- variableSeq[i] = this.VisitVariable( (!)variableSeq[i]);
- return variableSeq;
- }
- public virtual Cmd! VisitAssertEnsuresCmd(AssertEnsuresCmd! node)
- {
- node.Ensures = this.VisitEnsures(node.Ensures);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- public virtual Cmd! VisitAssertRequiresCmd(AssertRequiresCmd! node)
- {
- node.Requires = this.VisitRequires(node.Requires);
- node.Expr = this.VisitExpr(node.Expr);
- return node;
- }
- }
-}
diff --git a/Source/Core/TypeAmbiguitySeeker.ssc b/Source/Core/TypeAmbiguitySeeker.ssc
deleted file mode 100644
index fc7cf071..00000000
--- a/Source/Core/TypeAmbiguitySeeker.ssc
+++ /dev/null
@@ -1,95 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-
-// Visitor to search for types proxies that could not completely be
-// determined by type inference. If this happens, a warning is
-// generated and the proxies are instantiated in a more or less arbitrary
-// fashion.
-
-namespace Microsoft.Boogie
-{
-
- public class TypeAmbiguitySeeker : StandardVisitor {
-
- private readonly InTypeSeeker! inTypeSeeker = new InTypeSeeker ();
- private readonly TypecheckingContext! TC;
-
- public TypeAmbiguitySeeker(TypecheckingContext! tc) {
- TC = tc;
- }
-
- private void CheckTypeParams(Absy! node, TypeParamInstantiation! insts) {
- foreach (TypeVariable! var in insts.FormalTypeParams) {
- Type! inst = insts[var];
- inTypeSeeker.FoundAmbiguity = false;
- inTypeSeeker.Visit(inst);
- if (inTypeSeeker.FoundAmbiguity)
- TC.Warning(node,
- "type parameter {0} is ambiguous, instantiating to {1}",
- var, inst);
- }
- }
-
- public override Expr! VisitNAryExpr(NAryExpr! node)
- {
- CheckTypeParams(node, (!)node.TypeParameters);
- return base.VisitNAryExpr(node);
- }
-
- public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node) {
- CheckTypeParams(node, (!)node.TypeParameters);
- return base.VisitMapAssignLhs(node);
- }
- }
-
- internal class InTypeSeeker : StandardVisitor {
-
- internal bool FoundAmbiguity = false;
-
- // called when an uninstantiated proxy was found
- private Type! Instantiate(Type! node, Type! inst) {
- FoundAmbiguity = true;
- bool success = node.Unify(inst);
- assert success;
- return node;
- }
-
- public override Type! VisitTypeProxy(TypeProxy! node) {
- if (node.ProxyFor != null)
- return base.VisitTypeProxy(node);
-
- return Instantiate(node, Type.Int);
- }
-
- public override Type! VisitMapTypeProxy(MapTypeProxy! node) {
- if (node.ProxyFor != null)
- return base.VisitMapTypeProxy(node);
-
- TypeVariableSeq! typeParams = new TypeVariableSeq ();
- TypeSeq! arguments = new TypeSeq ();
- for (int i = 0; i < node.Arity; ++i) {
- TypeVariable! param = new TypeVariable (Token.NoToken, "arg" + i);
- typeParams.Add(param);
- arguments.Add(param);
- }
- TypeVariable! result = new TypeVariable (Token.NoToken, "res");
- typeParams.Add(result);
-
- Type! instantiation = new MapType (Token.NoToken, typeParams, arguments, result);
-
- return Instantiate(node, instantiation);
- }
-
- public override Type! VisitBvTypeProxy(BvTypeProxy! node) {
- if (node.ProxyFor != null)
- return base.VisitBvTypeProxy(node);
-
- return Instantiate(node, new BvType (node.MinBits));
- }
- }
-
-} \ No newline at end of file
diff --git a/Source/Core/Util.ssc b/Source/Core/Util.ssc
deleted file mode 100644
index 87323eb5..00000000
--- a/Source/Core/Util.ssc
+++ /dev/null
@@ -1,481 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-namespace Microsoft.Boogie
-{
- using System;
- using System.IO;
- using System.Collections;
- using Microsoft.Contracts;
-
- public class TokenTextWriter : IDisposable
- {
- string! filename;
- TextWriter! writer;
- bool writerOpenedHere = false;
- bool setTokens = true;
- int line = 1;
- int col;
-
- private const int indent_size = 2;
- protected static string! Indent (int level)
- {
- return new string(' ', (indent_size * level));
- }
-
-
- // Keywords, this array *must* be sorted
- public static readonly string[]! BplKeywords =
- {
- "assert",
- "assume",
- "axiom",
- "bool",
- "break",
- "call",
- "cast",
- "const",
- "else",
- "ensures",
- "exists",
- "false",
- "forall",
- "free",
- "function",
- "goto",
- "havoc",
- "if",
- "implementation",
- "int",
- "invariant",
- "modifies",
- "old",
- "procedure",
- "public",
- "requires",
- "return",
- "returns",
- "true",
- "type",
- "unique",
- "var",
- "where",
- "while",
- };
-
- private IToken! CurrentToken
- {
- get
- {
- Token token = new Token();
- token.filename = filename;
- token.line = line;
- token.col = col;
- return token;
- }
- }
-
- public void SetToken(Absy! absy)
- {
- this.SetToken(ref absy.tok);
- }
-
- public void SetToken(ref IToken! tok)
- {
- if (this.setTokens) {
- tok = this.CurrentToken;
- }
- }
-
- public static string! SanitizeIdentifier (string! name)
- {
- int index = Array.BinarySearch(TokenTextWriter.BplKeywords, name);
- if (index >= 0) {
- return "\\" + name;
- } else if (name.Length > 2 && name[0] == 'b' && name[1] == 'v') {
- int dummy;
- return int.TryParse(name.Substring(2), out dummy) ? "\\" + name : name;
- } else {
- return name;
- }
- }
-
- public TokenTextWriter(string! filename)
- {
- this.filename = filename;
- this.writer = new StreamWriter(filename);
- this.writerOpenedHere = true;
- base();
- }
-
- public TokenTextWriter(string! filename, TextWriter! writer, bool setTokens)
- {
- this.filename = filename;
- this.writer = writer;
- this.setTokens = setTokens;
- base();
- }
-
- public TokenTextWriter(string! filename, TextWriter! writer)
- {
- this.filename = filename;
- this.writer = writer;
- base();
- }
-
- public TokenTextWriter(TextWriter! writer)
- {
- this.filename = "<no file>";
- this.writer = writer;
- base();
- }
-
- public void Write(string! text)
- {
- this.writer.Write(text);
- this.col += text.Length;
- }
-
- public void WriteIndent(int level)
- {
- this.Write(Indent(level));
- }
-
- public void Write(string! text, params object[] args)
- {
- this.Write(string.Format(text, args));
- }
-
- public void Write(int level, string! text)
- {
- this.WriteIndent(level);
- this.Write(text);
- }
-
- public void Write(int level, string! text, params object[] args)
- {
- this.WriteIndent(level);
- this.Write(text, args);
- }
-
- public void Write(Absy! node, string! text)
- {
- this.SetToken(node);
- this.Write(text);
- }
-
- public void Write(Absy! node, string! text, params string[] args)
- {
- this.SetToken(node);
- this.Write(text, args);
- }
-
- public void Write(Absy! node, int level, string! text)
- {
- this.WriteIndent(level);
- this.SetToken(node);
- this.Write(text);
- }
-
- public void Write(Absy! node, int level, string! text, params object[] args)
- {
- this.WriteIndent(level);
- this.SetToken(node);
- this.Write(text, args);
- }
-
- public void WriteLine()
- {
- this.writer.WriteLine();
- this.line++;
- this.col = 0;
- }
-
- public void WriteLine(string! text)
- {
- this.writer.WriteLine(text);
- this.line++;
- this.col = 0;
- }
-
- public void WriteText(string! text) {
- int processed = 0;
- while (true) {
- int n = text.IndexOf('\n', processed);
- if (n == -1) {
- this.writer.Write(text);
- this.col += text.Length - processed;
- return;
- }
- processed = n + 1;
- this.line++;
- this.col = 0;
- }
- }
-
- public void WriteLine(string! text, params object[] args)
- {
- this.WriteLine(string.Format(text, args));
- }
-
- public void WriteLine(int level, string! text)
- {
- this.WriteIndent(level);
- this.WriteLine(text);
- }
-
- public void WriteLine(int level, string! text, params object[] args)
- {
- this.WriteIndent(level);
- this.WriteLine(text, args);
- }
-
- public void WriteLine(Absy! node, string! text)
- {
- this.SetToken(node);
- this.WriteLine(text);
- }
-
- public void WriteLine(Absy! node, int level, string! text)
- {
- this.SetToken(node);
- this.WriteLine(level, text);
- }
-
- public void WriteLine(Absy! node, int level, string! text, params object[] args)
- {
- this.SetToken(node);
- this.WriteLine(level, text, args);
- }
-
- public void Close()
- {
- this.writer.Close();
- }
-
- public void Dispose()
- {
- this.Close();
- }
- }
-
- public class Helpers {
- public static string! BeautifyBplString (string! s) {
- // strip "^" if it is the first character, change "$result" to "result"
- if (s.StartsWith("^") || s == "$result") {
- s = s.Substring(1);
- } else if (s.StartsWith("call")) {
- s = s.Substring(s.IndexOf('@') + 1);
- if (s.StartsWith("formal@")) {
- s = "(value of formal parameter: " + s.Substring(7) +")";
- }
- }
- // strip "$in" from the end of identifier names
- if (s.EndsWith("$in")) {
- return "(initial value of: " + s.Substring(0, s.Length-3) +")";
- } else {
- return s;
- }
- }
- public static string! PrettyPrintBplExpr (Expr! e) {
- // anything that is unknown will just be printed via ToString
- // OldExpr and QuantifierExpr, BvExtractExpr, BvConcatExpr are ignored for now
- // LiteralExpr is printed as itself by ToString
- if (e is IdentifierExpr) {
- string s = e.ToString();
- return Helpers.BeautifyBplString(s);
- }
- else if (e is NAryExpr) {
- NAryExpr ne = (NAryExpr) e;
- IAppliable fun = ne.Fun;
- ExprSeq eSeq = ne.Args;
- if (fun != null) {
- if ((fun.FunctionName == "$Length" || fun.FunctionName == "$StringLength" ) && eSeq.Length == 1) {
- Expr e0 = eSeq[0];
- if (e0 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- return s0 + ".Length";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$typeof" && eSeq.Length == 1) {
- Expr e0 = eSeq[0];
- if (e0 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- return "(the dynamic type of: " + s0 + ")";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "IntArrayGet" && eSeq.Length == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return s0 + "[" + s1 + "]";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$Is" && eSeq.Length == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return "(" + s0 + " == null || (" + s0 + " is " + s1 + "))";
- }
- //unexpected, just fall outside to the default
- } else if (fun.FunctionName == "$IsNotNull" && eSeq.Length == 2) {
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- return "(" + s0 + " is " + s1 +")";
- }
- //unexpected, just fall outside to the default
- } else if (fun is MapSelect && eSeq.Length <= 3) {
- // only maps with up to two arguments are supported right now (here)
- if (((!)eSeq[0]).ToString() == "$Heap") {
- //print Index0.Index1, unless Index1 is "$elements", then just print Index0
- string s0 = PrettyPrintBplExpr((!)eSeq[1]);
- if (eSeq.Length > 2) {
- string s1 = PrettyPrintBplExpr((!)eSeq[2]);
- if (s1 == "$elements") {
- return s0;
- } else {
- if (eSeq[2] is IdentifierExpr) {
- // strip the class name out of a fieldname
- s1 = s1.Substring(s1.LastIndexOf('.') + 1);
- }
- return s0 + "." + s1;
- }
- }
- }
- //unexpected, just fall outside to the default
- } else if (fun is Microsoft.Boogie.BinaryOperator && eSeq.Length == 2) {
- Microsoft.Boogie.BinaryOperator f = (Microsoft.Boogie.BinaryOperator) fun;
- Expr e0 = eSeq[0];
- Expr e1 = eSeq[1];
- if (e0 != null && e1 != null) {
- string s0 = PrettyPrintBplExpr(e0);
- string s1 = PrettyPrintBplExpr(e1);
- string op = "";
- switch (f.Op) {
- case Microsoft.Boogie.BinaryOperator.Opcode.Add:
- op = " + ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.And:
- op = " && ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Div:
- op = " / ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Eq:
- op = " == ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Ge:
- op = " >= ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Gt:
- op = " > ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Iff:
- op = " <==> ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Imp:
- op = " ==> ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Le:
- op = " <= ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Lt:
- op = " < ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Mod:
- op = " % ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Mul:
- op = " * ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Neq:
- op = " != ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Or:
- op = " || ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Sub:
- op = " - ";
- break;
- case Microsoft.Boogie.BinaryOperator.Opcode.Subtype:
- op = " <: ";
- break;
- default: op = " ";
- break;
- }
- return "(" + s0 + op + s1 + ")";
- }
- //unexpected, just fall outside to the default
- } else {
- string s = fun.FunctionName + "(";
- for (int i = 0; i < eSeq.Length; i++) {
- Expr ex = eSeq[i];
- assume ex != null;
- if (i>0) {
- s += ", ";
- }
- string t = PrettyPrintBplExpr(ex);
- if (t.StartsWith("(") && t.EndsWith(")")) {
- t = t.Substring(1, t.Length -2);
- }
- s += t;
- }
- s += ")";
- return s;
- //unexpected, just fall outside to the default
- }
- }
- }
-
- return e.ToString();
- }
-
- private static readonly DateTime StartUp = DateTime.Now;
-
- public static void ExtraTraceInformation(string! point) {
- if (CommandLineOptions.Clo.TraceTimes) {
- DateTime now = DateTime.Now;
- TimeSpan timeSinceStartUp = now - StartUp;
- Console.WriteLine(">>> {0} [{1} s]", point, timeSinceStartUp.TotalSeconds);
- }
- }
-
- // Substitute @PROC@ in a filename with the given descName
- public static string! SubstituteAtPROC(string! descName, string! fileName) {
- System.Text.StringBuilder! sb =
- new System.Text.StringBuilder(descName.Length);
- // quote the name, characters like ^ cause trouble in CMD
- // while $ could cause trouble in SH
- foreach (char c in descName) {
- if (Char.IsLetterOrDigit(c) || c == '.') {
- sb.Append(c);
- } else {
- sb.Append('_');
- }
- }
- string pn = sb.ToString();
- // We attempt to avoid filenames that are too long, but we only
- // do it by truncating the @PROC@ replacement, which leaves unchanged
- // any filename extension specified by the user. We base our
- // calculations on that there is at most one occurrence of @PROC@.
- if (180 <= fileName.Length - 6 + pn.Length) {
- pn = pn.Substring(0, max{180 - (fileName.Length - 6), 0}) + "-n" + sequenceNumber;
- sequenceNumber++;
- }
-
- return fileName.Replace("@PROC@", pn);
- }
-
- private static int sequenceNumber = 0;
-
- }
-}
diff --git a/Source/Core/VCExp.ssc b/Source/Core/VCExp.ssc
deleted file mode 100644
index 650b3145..00000000
--- a/Source/Core/VCExp.ssc
+++ /dev/null
@@ -1,191 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Text;
-using Microsoft.Contracts;
-using Microsoft.Basetypes;
-
-
-namespace Microsoft.Boogie {
-
- public class ProverOptions
- {
- public class OptionException : Exception {
- public OptionException(string! msg) { base(msg); }
- }
-
- public string/*?*/ LogFilename = null;
- public bool AppendLogFile = false;
- public bool SeparateLogFiles = false;
- // Say (DBG_WAS_VALID) or (DBG_WAS_INVALID) after query
- public bool ForceLogStatus = false;
- public int TimeLimit = 0;
- public int MemoryLimit = 0;
- public CommandLineOptions.BvHandling BitVectors = CommandLineOptions.BvHandling.None;
- public int Verbosity = 0;
-
- private string! stringRepr = "";
-
- [Pure]
- public override string! ToString()
- {
- return stringRepr;
- }
-
- // The usual thing to override.
- protected virtual bool Parse(string! opt)
- {
- return ParseString(opt, "LOG_FILE", ref LogFilename) ||
- ParseBool(opt, "APPEND_LOG_FILE", ref AppendLogFile) ||
- ParseBool(opt, "FORCE_LOG_STATUS", ref ForceLogStatus) ||
- ParseInt(opt, "MEMORY_LIMIT", ref MemoryLimit) ||
- ParseInt(opt, "VERBOSITY", ref Verbosity) ||
- ParseInt(opt, "TIME_LIMIT", ref TimeLimit);
- // || base.Parse(opt)
- }
-
- public virtual void Parse(List<string!>! opts)
- {
- StringBuilder! sb = new StringBuilder(stringRepr);
- foreach (string! opt in opts) {
- if (!Parse(opt)) {
- ReportError("Unrecognised prover option: " + opt);
- }
- sb.Append(opt).Append(" ");
- }
- stringRepr = sb.ToString();
- PostParse();
- }
-
- protected virtual void PostParse()
- {
- if (LogFilename != null && LogFilename.Contains("@PROC@")) {
- SeparateLogFiles = true;
- }
- }
-
- protected void ReportError(string! msg)
- {
- throw new OptionException(msg);
- }
-
- protected virtual bool ParseString(string! opt, string! name, ref string field)
- {
- if (opt.Length >= name.Length && opt.StartsWith(name)) {
- if (opt.Length == name.Length) {
- field = "";
- return true;
- } else if (opt[name.Length] == '=') {
- field = opt.Substring(name.Length + 1);
- return true;
- }
- }
- return false;
- }
-
- protected virtual bool ParseBool(string! opt, string! name, ref bool field)
- {
- string tmp = null;
- if (ParseString(opt, name, ref tmp))
- switch (((!)tmp).ToLower()) {
- case "1":
- case "true":
- case "":
- field = true;
- return true;
- case "0":
- case "false":
- field = false;
- return true;
- default:
- ReportError("Invalid Boolean option \"" + opt + "\"");
- return false;
- }
- return false;
- }
-
- protected virtual bool ParseInt(string! opt, string! name, ref int field)
- {
- string tmp = null;
- int t2;
- if (ParseString(opt, name, ref tmp)) {
- if (int.TryParse((!)tmp, out t2)) {
- field = t2;
- return true;
- } else {
- ReportError("Invalid integer option \"" + opt + "\"");
- }
- }
- return false;
- }
-
- static int sequenceNumber = 0;
- public virtual TextWriter? OpenLog(string/*?*/ descName)
- {
- if (LogFilename != null) {
- string! filename = LogFilename;
- if (descName != null)
- filename = Helpers.SubstituteAtPROC(descName, filename);
- return new StreamWriter(filename, AppendLogFile);
- } else {
- return null;
- }
- }
- }
-
- public abstract class ProverFactory
- {
- // Really returns ProverInterface.
- //public abstract object! SpawnProver(ProverOptions! options, object! ctxt);
- public abstract object SpawnProver(ProverOptions options, object ctxt);
-
- // Really returns ProverContext
- public abstract object! NewProverContext(ProverOptions! options);
-
- public virtual ProverOptions! BlankProverOptions()
- {
- return new ProverOptions();
- }
-
- // return true if the prover supports DAG AST as opposed to LET AST
- public virtual bool SupportsDags
- {
- get { return false; }
- }
-
- public virtual CommandLineOptions.VCVariety DefaultVCVariety
- {
- get
- ensures result != CommandLineOptions.VCVariety.Unspecified;
- { return CommandLineOptions.VCVariety.Dag; }
- }
-
- public virtual void Close()
- {
- }
-
- public static ProverFactory! Load(string! proverName)
- ensures result.IsNew && Microsoft.Contracts.Owner.New(result);
- {
- string! path;
- if (proverName.IndexOf("/") > 0 || proverName.IndexOf("\\") > 0) {
- path = proverName;
- } else {
- string! codebase = (!) System.IO.Path.GetDirectoryName(
- (!)System.Reflection.Assembly.GetExecutingAssembly().Location);
- path = System.IO.Path.Combine(codebase, "Provers." + proverName + ".dll");
- }
- Assembly asm = (!)Assembly.LoadFrom(path);
- string name = (!)asm.GetName().Name;
- System.Type factoryType = (!)asm.GetType("Microsoft.Boogie." + name.Replace("Provers.", "") + ".Factory");
- return (ProverFactory!)Activator.CreateInstance(factoryType);
- }
- }
-}
diff --git a/Source/Core/Xml.ssc b/Source/Core/Xml.ssc
deleted file mode 100644
index e0583793..00000000
--- a/Source/Core/Xml.ssc
+++ /dev/null
@@ -1,291 +0,0 @@
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.IO;
-using System.Xml;
-using System.Collections.Generic;
-using Microsoft.Contracts;
-using Cci = System.Compiler;
-
-namespace Microsoft.Boogie
-{
-
- public class XmlSink {
- string! filename;
- [Rep] XmlWriter wr;
- public bool IsOpen {
- get { return wr != null; }
- }
-
- public XmlSink(string! filename) {
- this.filename = filename;
- }
-
- /// <summary>
- /// Returns null on success, in which case the caller should eventually invoke Close.
- /// Returns an error string on failure.
- /// </summary>
- public string Open()
- modifies this.*;
- ensures IsOpen;
- {
- if (wr != null) {
- Close();
- }
- expose (this) {
- XmlWriterSettings settings = new XmlWriterSettings();
- settings.Indent = true;
- wr = XmlWriter.Create(filename, settings);
- wr.WriteStartDocument();
- wr.WriteStartElement("boogie");
- wr.WriteAttributeString("version", CommandLineOptions.VersionNumber);
- wr.WriteAttributeString("commandLine", Environment.CommandLine);
- }
- return null; // success
- }
-
- public void Close()
- modifies this.*;
- {
- if (wr != null) {
- expose (this) {
- wr.WriteEndDocument();
- wr.Close();
- wr = null;
- }
- }
- }
-
- const string DateTimeFormatString = "u";
-
- public void WriteStartMethod(string! methodName, DateTime startTime)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("method");
- wr.WriteAttributeString("name", methodName);
- wr.WriteAttributeString("startTime", startTime.ToString(DateTimeFormatString));
- }
- }
-
- public void WriteEndMethod(string! outcome, DateTime endTime, TimeSpan elapsed)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("conclusion");
- wr.WriteAttributeString("endTime", endTime.ToString(DateTimeFormatString));
- wr.WriteAttributeString("duration", elapsed.TotalSeconds.ToString());
- wr.WriteAttributeString("outcome", outcome);
-
- wr.WriteEndElement(); // outcome
- wr.WriteEndElement(); // method
- }
- }
-
- public void WriteError(string! message, IToken! errorToken, IToken relatedToken, BlockSeq trace)
- requires IsOpen && (trace == null || Owner.Different(this, trace));
- modifies this.*, errorToken.*, relatedToken.*, trace.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose(this){
- wr.WriteStartElement("error");
- wr.WriteAttributeString("message", message);
- WriteTokenAttributes(errorToken);
- if (relatedToken != null)
- {
- wr.WriteStartElement("related");
- WriteTokenAttributes(relatedToken);
- wr.WriteEndElement();
- }
- if (trace != null)
- {
- wr.WriteStartElement("trace");
- {
- foreach (object bo in trace)
- invariant wr != null;
- {
- assume bo is Block;
- Block b = (Block)bo;
- wr.WriteStartElement("traceNode");
- {
- WriteTokenAttributes(b.tok);
- wr.WriteAttributeString("label", b.Label);
- }
- wr.WriteEndElement();
- }
- wr.WriteEndElement();
- }
- }
- wr.WriteEndElement();
- }
- }
-
- public void WriteError(string! message, Cci.Node! offendingNode, BlockSeq trace)
- requires IsOpen && Owner.Different(this, offendingNode);
- requires trace == null || Owner.Different(this, trace);
- modifies this.*, offendingNode.*, trace.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose(this){
- wr.WriteStartElement("error");
- wr.WriteAttributeString("message", message);
- WriteTokenAttributes(offendingNode);
- if (trace != null)
- {
- wr.WriteStartElement("trace");
- {
- foreach (object bo in trace)
- invariant wr != null;
- {
- assume bo is Block;
- Block b = (Block)bo;
- wr.WriteStartElement("traceNode");
- {
- this.WriteTokenAttributes(b.tok);
- wr.WriteAttributeString("label", b.Label);
- }
- wr.WriteEndElement();
- }
- wr.WriteEndElement();
- }
- }
- wr.WriteEndElement();
- }
- }
-
- [Inside]
- private void WriteTokenAttributes(IToken tok)
- requires wr != null && wr.IsPeerConsistent;
- modifies this.0, wr.*;
- {
- if (tok != null && tok.filename != null)
- {
- wr.WriteAttributeString("file", tok.filename);
- wr.WriteAttributeString("line", tok.line.ToString());
- wr.WriteAttributeString("column", tok.col.ToString());
- }
- }
-
- [Inside]
- private void WriteTokenAttributes(Cci.Node! node)
- requires wr != null && wr.IsPeerConsistent;
- modifies this.0, wr.*;
- {
- assert wr != null;
- if (node.SourceContext.Document != null)
- {
- wr.WriteAttributeString("file", node.SourceContext.Document.Name);
- wr.WriteAttributeString("line", node.SourceContext.StartLine.ToString());
- wr.WriteAttributeString("column", node.SourceContext.StartColumn.ToString());
- }
- }
-
- public void WriteStartInference(string! inferenceName)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("inference");
- wr.WriteAttributeString("name", inferenceName);
- }
- }
-
- public void WriteEndInference()
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteEndElement(); // inference
- }
- }
-
- public void WriteContractParaAssignment(string! varName, string val)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("assignment");
- wr.WriteAttributeString("name", varName);
- wr.WriteAttributeString("value", val);
- wr.WriteEndElement();
- }
- }
-
- public void WriteStartFile(string! filename)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("file");
- wr.WriteAttributeString("name", filename);
- }
- }
-
- public void WriteEndFile()
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteEndElement();
- }
- }
-
- public void WriteFileFragment(string! fragment)
- requires IsOpen;
- modifies this.*;
- ensures IsOpen;
- {
- assert wr != null;
- expose (this) {
- wr.WriteStartElement("fileFragment");
- wr.WriteAttributeString("name", fragment);
- wr.WriteEndElement();
- }
- }
- }
-
- public class XmlFileScope : IDisposable {
- [Peer] [SpecPublic] XmlSink sink;
-
- [Captured]
- public XmlFileScope(XmlSink? sink, string! filename)
- requires sink != null ==> sink.IsOpen;
- modifies sink.*;
- {
- if (sink != null) {
- sink.WriteStartFile(filename); // invoke this method while "sink" is still peer consistent
- Owner.AssignSame(this, sink);
- this.sink = sink;
- }
- }
-
- public void Dispose()
- {
- if (sink != null) {
- assume sink.IsOpen;
- sink.WriteEndFile();
- }
- }
- }
-}