PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/Dafny/Compiler.cs

#
C# | 1811 lines | 1518 code | 128 blank | 165 comment | 458 complexity | eb503766fce7457a6e4c4ed70bd06a20 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  4. //
  5. //-----------------------------------------------------------------------------
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Numerics;
  9. using System.IO;
  10. using System.Diagnostics.Contracts;
  11. using Bpl = Microsoft.Boogie;
  12. using System.Text;
  13. namespace Microsoft.Dafny {
  14. public class Compiler {
  15. public Compiler(TextWriter wr) {
  16. Contract.Requires(wr != null);
  17. this.wr = wr;
  18. }
  19. [ContractInvariantMethod]
  20. void ObjectInvariant()
  21. {
  22. Contract.Invariant(wr!=null);
  23. }
  24. TextWriter wr;
  25. public int ErrorCount;
  26. void Error(string msg, params object[] args) {
  27. Contract.Requires(msg != null);
  28. Contract.Requires(args != null);
  29. string s = string.Format("Compilation error: " + msg, args);
  30. Console.WriteLine(s);
  31. wr.WriteLine("/* {0} */", s);
  32. ErrorCount++;
  33. }
  34. void ReadRuntimeSystem() {
  35. string codebase = cce.NonNull( System.IO.Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
  36. string path = System.IO.Path.Combine(codebase, "DafnyRuntime.cs");
  37. using (TextReader rd = new StreamReader(new FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read)))
  38. {
  39. while (true) {
  40. string s = rd.ReadLine();
  41. if (s == null)
  42. return;
  43. wr.WriteLine(s);
  44. }
  45. }
  46. }
  47. readonly int IndentAmount = 2;
  48. void Indent(int ind) {
  49. string spaces = " ";
  50. for (; spaces.Length < ind; ind -= spaces.Length) {
  51. wr.Write(spaces);
  52. }
  53. wr.Write(spaces.Substring(0, ind));
  54. }
  55. public void Compile(Program program) {Contract.Requires(program != null);
  56. wr.WriteLine("// Dafny program {0} compiled into C#", program.Name);
  57. wr.WriteLine();
  58. ReadRuntimeSystem();
  59. CompileBuiltIns(program.BuiltIns);
  60. foreach (ModuleDecl m in program.Modules) {
  61. if (m.IsGhost) {
  62. // the purpose of a ghost module is to skip compilation
  63. continue;
  64. }
  65. int indent = 0;
  66. if (!m.IsDefaultModule) {
  67. wr.WriteLine("namespace @{0} {{", m.Name);
  68. indent += IndentAmount;
  69. }
  70. foreach (TopLevelDecl d in m.TopLevelDecls) {
  71. wr.WriteLine();
  72. if (d is ArbitraryTypeDecl) {
  73. var at = (ArbitraryTypeDecl)d;
  74. Error("Arbitrary type ('{0}') cannot be compiled", at.Name);
  75. } else if (d is DatatypeDecl) {
  76. DatatypeDecl dt = (DatatypeDecl)d;
  77. Indent(indent);
  78. wr.Write("public abstract class Base_{0}", dt.Name);
  79. if (dt.TypeArgs.Count != 0) {
  80. wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
  81. }
  82. wr.WriteLine(" { }");
  83. CompileDatatypeConstructors(dt, indent);
  84. CompileDatatypeStruct(dt, indent);
  85. } else {
  86. ClassDecl cl = (ClassDecl)d;
  87. Indent(indent);
  88. wr.Write("public class @{0}", cl.Name);
  89. if (cl.TypeArgs.Count != 0) {
  90. wr.Write("<{0}>", TypeParameters(cl.TypeArgs));
  91. }
  92. wr.WriteLine(" {");
  93. CompileClassMembers(cl, indent+IndentAmount);
  94. Indent(indent); wr.WriteLine("}");
  95. }
  96. }
  97. if (!m.IsDefaultModule) {
  98. wr.WriteLine("}} // end of namespace {0}", m.Name);
  99. }
  100. }
  101. }
  102. void CompileBuiltIns(BuiltIns builtIns) {
  103. wr.WriteLine("namespace Dafny {");
  104. Indent(IndentAmount);
  105. wr.WriteLine("public partial class Helpers {");
  106. foreach (var decl in builtIns.SystemModule.TopLevelDecls) {
  107. if (decl is ArrayClassDecl) {
  108. int dims = ((ArrayClassDecl)decl).Dims;
  109. // public static T[,] InitNewArray2<T>(BigInteger size0, BigInteger size1) {
  110. Indent(3 * IndentAmount);
  111. wr.Write("public static T[");
  112. RepeatWrite(wr, dims, "", ",");
  113. wr.Write("] InitNewArray{0}<T>(", dims);
  114. RepeatWrite(wr, dims, "BigInteger size{0}", ", ");
  115. wr.WriteLine(") {");
  116. // int s0 = (int)size0;
  117. for (int i = 0; i < dims; i++) {
  118. Indent(4 * IndentAmount);
  119. wr.WriteLine("int s{0} = (int)size{0};", i);
  120. }
  121. // T[,] a = new T[s0, s1];
  122. Indent(4 * IndentAmount);
  123. wr.Write("T[");
  124. RepeatWrite(wr, dims, "", ",");
  125. wr.Write("] a = new T[");
  126. RepeatWrite(wr, dims, "s{0}", ",");
  127. wr.WriteLine("];");
  128. // BigInteger[,] b = a as BigInteger[,];
  129. Indent(4 * IndentAmount);
  130. wr.Write("BigInteger[");
  131. RepeatWrite(wr, dims, "", ",");
  132. wr.Write("] b = a as BigInteger[");
  133. RepeatWrite(wr, dims, "", ",");
  134. wr.WriteLine("];");
  135. // if (b != null) {
  136. Indent(4 * IndentAmount);
  137. wr.WriteLine("if (b != null) {");
  138. // BigInteger z = new BigInteger(0);
  139. Indent(5 * IndentAmount);
  140. wr.WriteLine("BigInteger z = new BigInteger(0);");
  141. // for (int i0 = 0; i0 < s0; i0++)
  142. // for (int i1 = 0; i1 < s1; i1++)
  143. for (int i = 0; i < dims; i++) {
  144. Indent((5+i) * IndentAmount);
  145. wr.WriteLine("for (int i{0} = 0; i{0} < s{0}; i{0}++)", i);
  146. }
  147. // b[i0,i1] = z;
  148. Indent((5+dims) * IndentAmount);
  149. wr.Write("b[");
  150. RepeatWrite(wr, dims, "i{0}", ",");
  151. wr.WriteLine("] = z;");
  152. // }
  153. Indent(4 * IndentAmount);
  154. wr.WriteLine("}");
  155. // return a;
  156. Indent(4 * IndentAmount);
  157. wr.WriteLine("return a;");
  158. // }
  159. Indent(3 * IndentAmount);
  160. wr.WriteLine("}"); // end of method
  161. }
  162. }
  163. Indent(IndentAmount);
  164. wr.WriteLine("}"); // end of class Helpers
  165. wr.WriteLine("}"); // end of namespace
  166. }
  167. static void RepeatWrite(TextWriter wr, int times, string template, string separator) {
  168. Contract.Requires(1 <= times);
  169. string s = "";
  170. for (int i = 0; i < times; i++) {
  171. wr.Write(s);
  172. wr.Write(template, i);
  173. s = separator;
  174. }
  175. }
  176. void CompileDatatypeConstructors(DatatypeDecl dt, int indent)
  177. {Contract.Requires(dt != null);
  178. foreach (DatatypeCtor ctor in dt.Ctors) {
  179. // class Dt_Ctor<T,U> : Base_Dt<T> {
  180. // Fields;
  181. // public Dt_Ctor(arguments) {
  182. // Fields = arguments;
  183. // }
  184. // public override bool Equals(object other) {
  185. // var oth = other as Dt_Dtor;
  186. // return oth != null && equals(_field0, oth._field0) && ... ;
  187. // }
  188. // public override int GetHashCode() {
  189. // return base.GetHashCode(); // surely this can be improved
  190. // }
  191. // }
  192. Indent(indent);
  193. wr.Write("public class {0}", DtCtorName(ctor));
  194. if (dt.TypeArgs.Count != 0) {
  195. wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
  196. }
  197. wr.Write(" : Base_{0}", dt.Name);
  198. if (dt.TypeArgs.Count != 0) {
  199. wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
  200. }
  201. wr.WriteLine(" {");
  202. int ind = indent + IndentAmount;
  203. int i = 0;
  204. foreach (Formal arg in ctor.Formals) {
  205. if (!arg.IsGhost) {
  206. Indent(ind);
  207. wr.WriteLine("public readonly {0} @{1};", TypeName(arg.Type), FormalName(arg, i));
  208. i++;
  209. }
  210. }
  211. Indent(ind);
  212. wr.Write("public {0}(", DtCtorName(ctor));
  213. WriteFormals("", ctor.Formals);
  214. wr.WriteLine(") {");
  215. i = 0;
  216. foreach (Formal arg in ctor.Formals) {
  217. if (!arg.IsGhost) {
  218. Indent(ind + IndentAmount);
  219. wr.WriteLine("this.@{0} = @{0};", FormalName(arg, i));
  220. i++;
  221. }
  222. }
  223. Indent(ind); wr.WriteLine("}");
  224. // Equals method
  225. Indent(ind); wr.WriteLine("public override bool Equals(object other) {");
  226. Indent(ind + IndentAmount);
  227. wr.Write("var oth = other as {0}", DtCtorName(ctor));
  228. if (dt.TypeArgs.Count != 0) {
  229. wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
  230. }
  231. wr.WriteLine(";");
  232. Indent(ind + IndentAmount);
  233. wr.Write("return oth != null");
  234. i = 0;
  235. foreach (Formal arg in ctor.Formals) {
  236. if (!arg.IsGhost) {
  237. string nm = FormalName(arg, i);
  238. if (arg.Type.IsDatatype || arg.Type.IsTypeParameter) {
  239. wr.Write(" && this.@{0}.Equals(oth.@{0})", nm);
  240. } else {
  241. wr.Write(" && this.@{0} == oth.@{0}", nm);
  242. }
  243. i++;
  244. }
  245. }
  246. wr.WriteLine(";");
  247. Indent(ind); wr.WriteLine("}");
  248. // GetHashCode method
  249. Indent(ind); wr.WriteLine("public override int GetHashCode() {");
  250. Indent(ind + IndentAmount); wr.WriteLine("return base.GetHashCode(); // surely this can be improved");
  251. Indent(ind); wr.WriteLine("}");
  252. Indent(indent); wr.WriteLine("}");
  253. }
  254. }
  255. void CompileDatatypeStruct(DatatypeDecl dt, int indent) {
  256. Contract.Requires(dt != null);
  257. // public struct Dt<T> {
  258. // Base_Dt<T> d;
  259. // public Base_Dt<T> _D {
  260. // get { if (d == null) { d = Default; } return d; }
  261. // }
  262. // public Dt(Base_Dt<T> d) { this.d = d; }
  263. // public static Base_Dt<T> Default {
  264. // get { return ...; }
  265. // }
  266. // public override bool Equals(object other) {
  267. // return other is Dt<T> && _D.Equals(((Dt<T>)other)._D);
  268. // }
  269. // public override int GetHashCode() { return _D.GetHashCode(); }
  270. //
  271. // public bool _Ctor0 { get { return _D is Dt_Ctor0; } }
  272. // ...
  273. //
  274. // public T0 dtor_Dtor0 { get { return ((DT_Ctor)_D).@Dtor0; } }
  275. // ...
  276. // }
  277. string DtT = dt.Name;
  278. string DtT_TypeArgs = "";
  279. if (dt.TypeArgs.Count != 0) {
  280. DtT_TypeArgs = "<" + TypeParameters(dt.TypeArgs) + ">";
  281. DtT += DtT_TypeArgs;
  282. }
  283. Indent(indent);
  284. wr.WriteLine("public struct @{0} {{", DtT);
  285. int ind = indent + IndentAmount;
  286. Indent(ind);
  287. wr.WriteLine("Base_{0} d;", DtT);
  288. Indent(ind);
  289. wr.WriteLine("public Base_{0} _D {{", DtT);
  290. Indent(ind + IndentAmount);
  291. wr.WriteLine("get { if (d == null) { d = Default; } return d; }");
  292. Indent(ind); wr.WriteLine("}");
  293. Indent(ind);
  294. wr.WriteLine("public @{0}(Base_{1} d) {{ this.d = d; }}", dt.Name, DtT);
  295. Indent(ind);
  296. wr.WriteLine("public static Base_{0} Default {{", DtT);
  297. Indent(ind + IndentAmount);
  298. wr.Write("get { return ");
  299. wr.Write("new {0}", DtCtorName(cce.NonNull(dt.DefaultCtor)));
  300. if (dt.TypeArgs.Count != 0) {
  301. wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
  302. }
  303. wr.Write("(");
  304. string sep = "";
  305. foreach (Formal f in dt.DefaultCtor.Formals) {
  306. if (!f.IsGhost) {
  307. wr.Write("{0}{1}", sep, DefaultValue(f.Type));
  308. sep = ", ";
  309. }
  310. }
  311. wr.Write(")");
  312. wr.WriteLine("; }");
  313. Indent(ind); wr.WriteLine("}");
  314. Indent(ind); wr.WriteLine("public override bool Equals(object other) {");
  315. Indent(ind + IndentAmount);
  316. wr.WriteLine("return other is @{0} && _D.Equals(((@{0})other)._D);", DtT);
  317. Indent(ind); wr.WriteLine("}");
  318. Indent(ind);
  319. wr.WriteLine("public override int GetHashCode() { return _D.GetHashCode(); }");
  320. // query properties
  321. foreach (var ctor in dt.Ctors) {
  322. // public bool _Ctor0 { get { return _D is Dt_Ctor0; } }
  323. Indent(ind);
  324. wr.WriteLine("public bool _{0} {{ get {{ return _D is {1}_{0}{2}; }} }}", ctor.Name, dt.Name, DtT_TypeArgs);
  325. }
  326. // destructors
  327. foreach (var ctor in dt.Ctors) {
  328. foreach (var arg in ctor.Formals) {
  329. if (arg.HasName) {
  330. // public T0 @Dtor0 { get { return ((DT_Ctor)_D).@Dtor0; } }
  331. Indent(ind);
  332. wr.WriteLine("public {0} dtor_{1} {{ get {{ return (({2}_{3}{4})_D).@{1}; }} }}", TypeName(arg.Type), arg.Name, dt.Name, ctor.Name, DtT_TypeArgs);
  333. }
  334. }
  335. }
  336. Indent(indent);
  337. wr.WriteLine("}");
  338. }
  339. int WriteFormals(string sep, List<Formal/*!*/>/*!*/ formals)
  340. {
  341. Contract.Requires(sep != null);
  342. Contract.Requires(cce.NonNullElements(formals));
  343. int i = 0;
  344. foreach (Formal arg in formals) {
  345. if (!arg.IsGhost) {
  346. string name = FormalName(arg, i);
  347. wr.Write("{0}{1}{2} @{3}", sep, arg.InParam ? "" : "out ", TypeName(arg.Type), name);
  348. sep = ", ";
  349. i++;
  350. }
  351. }
  352. return i; // the number of formals written
  353. }
  354. string FormalName(Formal formal, int i) {
  355. Contract.Requires(formal != null);
  356. Contract.Ensures(Contract.Result<string>() != null);
  357. return formal.HasName ? formal.Name : "_a" + i;
  358. }
  359. string DtCtorName(DatatypeCtor ctor) {
  360. Contract.Requires(ctor != null);Contract.Ensures(Contract.Result<string>() != null);
  361. return cce.NonNull(ctor.EnclosingDatatype).Name + "_" + ctor.Name;
  362. }
  363. public bool HasMain(Program program) {
  364. foreach (var module in program.Modules) {
  365. foreach (var decl in module.TopLevelDecls) {
  366. var c = decl as ClassDecl;
  367. if (c != null) {
  368. foreach (var member in c.Members) {
  369. var m = member as Method;
  370. if (m != null) {
  371. if (!m.IsGhost && m.Name == "Main" && m.Ins.Count == 0 && m.Outs.Count == 0) {
  372. return true;
  373. }
  374. }
  375. }
  376. }
  377. }
  378. }
  379. return false;
  380. }
  381. void CompileClassMembers(ClassDecl c, int indent)
  382. {
  383. Contract.Requires(c != null);
  384. foreach (MemberDecl member in c.Members) {
  385. if (member is Field) {
  386. Field f = (Field)member;
  387. if (!f.IsGhost) {
  388. Indent(indent);
  389. wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.Name, DefaultValue(f.Type));
  390. }
  391. } else if (member is Function) {
  392. Function f = (Function)member;
  393. if (f.IsGhost) {
  394. // nothing to compile
  395. } else if (f.Body == null) {
  396. Error("Function {0} has no body", f.FullName);
  397. } else {
  398. Indent(indent);
  399. wr.Write("public {0}{1} @{2}", f.IsStatic ? "static " : "", TypeName(f.ResultType), f.Name);
  400. if (f.TypeArgs.Count != 0) {
  401. wr.Write("<{0}>", TypeParameters(f.TypeArgs));
  402. }
  403. wr.Write("(");
  404. WriteFormals("", f.Formals);
  405. wr.WriteLine(") {");
  406. CompileReturnBody(f.Body, indent + IndentAmount);
  407. Indent(indent); wr.WriteLine("}");
  408. }
  409. } else if (member is Method) {
  410. Method m = (Method)member;
  411. if (!m.IsGhost) {
  412. Indent(indent);
  413. wr.Write("public {0}void @{1}", m.IsStatic ? "static " : "", m.Name);
  414. if (m.TypeArgs.Count != 0) {
  415. wr.Write("<{0}>", TypeParameters(m.TypeArgs));
  416. }
  417. wr.Write("(");
  418. int nIns = WriteFormals("", m.Ins);
  419. WriteFormals(nIns == 0 ? "" : ", ", m.Outs);
  420. wr.WriteLine(")");
  421. Indent(indent); wr.WriteLine("{");
  422. foreach (Formal p in m.Outs) {
  423. if (!p.IsGhost) {
  424. Indent(indent + IndentAmount);
  425. wr.WriteLine("@{0} = {1};", p.Name, DefaultValue(p.Type));
  426. }
  427. }
  428. if (m.Body == null) {
  429. Error("Method {0} has no body", m.FullName);
  430. } else {
  431. TrStmtList(m.Body.Body, indent);
  432. }
  433. Indent(indent); wr.WriteLine("}");
  434. // allow the Main method to be an instance method
  435. if (m.Name == "Main" && m.Ins.Count == 0 && m.Outs.Count == 0) {
  436. Indent(indent);
  437. wr.WriteLine("public static void Main(string[] args) {");
  438. Contract.Assert(m.EnclosingClass == c);
  439. Indent(indent + IndentAmount);
  440. wr.Write("@{0} b = new @{0}", c.Name);
  441. if (c.TypeArgs.Count != 0) {
  442. // instantiate every parameter, it doesn't particularly matter how
  443. wr.Write("<");
  444. string sep = "";
  445. for (int i = 0; i < c.TypeArgs.Count; i++) {
  446. wr.Write("{0}int", sep);
  447. sep = ", ";
  448. }
  449. wr.Write(">");
  450. }
  451. wr.WriteLine("();");
  452. Indent(indent + IndentAmount); wr.WriteLine("b.Main();");
  453. Indent(indent); wr.WriteLine("}");
  454. }
  455. }
  456. } else {
  457. Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member
  458. }
  459. }
  460. }
  461. void CompileReturnBody(Expression body, int indent) {
  462. body = body.Resolved;
  463. if (body is MatchExpr) {
  464. MatchExpr me = (MatchExpr)body;
  465. // Type source = e;
  466. // if (source._D is Dt_Ctor0) {
  467. // FormalType f0 = ((Dt_Ctor0)source._D).a0;
  468. // ...
  469. // return Body0;
  470. // } else if (...) {
  471. // ...
  472. // } else if (true) {
  473. // ...
  474. // }
  475. SpillLetVariableDecls(me.Source, indent);
  476. string source = "_source" + tmpVarCount;
  477. tmpVarCount++;
  478. Indent(indent);
  479. wr.Write("{0} {1} = ", TypeName(cce.NonNull(me.Source.Type)), source);
  480. TrExpr(me.Source);
  481. wr.WriteLine(";");
  482. if (me.Cases.Count == 0) {
  483. // the verifier would have proved we never get here; still, we need some code that will compile
  484. Indent(indent);
  485. wr.WriteLine("throw new System.Exception();");
  486. } else {
  487. int i = 0;
  488. foreach (MatchCaseExpr mc in me.Cases) {
  489. MatchCasePrelude(source, cce.NonNull(mc.Ctor), mc.Arguments, i, me.Cases.Count, indent + IndentAmount);
  490. CompileReturnBody(mc.Body, indent + IndentAmount);
  491. i++;
  492. }
  493. Indent(indent); wr.WriteLine("}");
  494. }
  495. } else {
  496. SpillLetVariableDecls(body, indent);
  497. Indent(indent);
  498. wr.Write("return ");
  499. TrExpr(body);
  500. wr.WriteLine(";");
  501. }
  502. }
  503. void SpillLetVariableDecls(Expression expr, int indent) {
  504. Contract.Requires(0 <= indent);
  505. if (expr == null) {
  506. // allow "null" as an argument; nothing to do
  507. return;
  508. }
  509. if (expr is LetExpr) {
  510. var e = (LetExpr)expr;
  511. foreach (var v in e.Vars) {
  512. Indent(indent);
  513. wr.WriteLine("{0} @{1};", TypeName(v.Type), v.Name);
  514. }
  515. }
  516. foreach (var ee in expr.SubExpressions) {
  517. SpillLetVariableDecls(ee, indent);
  518. }
  519. }
  520. // ----- Type ---------------------------------------------------------------------------------
  521. readonly string DafnySetClass = "Dafny.Set";
  522. readonly string DafnyMultiSetClass = "Dafny.MultiSet";
  523. readonly string DafnySeqClass = "Dafny.Sequence";
  524. string TypeName(Type type)
  525. {
  526. Contract.Requires(type != null);
  527. Contract.Ensures(Contract.Result<string>() != null);
  528. while (true) {
  529. TypeProxy tp = type as TypeProxy;
  530. if (tp == null) {
  531. break;
  532. } else if (tp.T == null) {
  533. // unresolved proxy; just treat as ref, since no particular type information is apparently needed for this type
  534. return "object";
  535. } else {
  536. type = tp.T;
  537. }
  538. }
  539. if (type is BoolType) {
  540. return "bool";
  541. } else if (type is IntType) {
  542. return "BigInteger";
  543. } else if (type is ObjectType) {
  544. return "object";
  545. } else if (type.IsArrayType) {
  546. ArrayClassDecl at = type.AsArrayType;
  547. Contract.Assert(at != null); // follows from type.IsArrayType
  548. Type elType = UserDefinedType.ArrayElementType(type);
  549. string name = TypeName(elType) + "[";
  550. for (int i = 1; i < at.Dims; i++) {
  551. name += ",";
  552. }
  553. return name + "]";
  554. } else if (type is UserDefinedType) {
  555. UserDefinedType udt = (UserDefinedType)type;
  556. string s = "@" + udt.FullName;
  557. if (udt.TypeArgs.Count != 0) {
  558. if (Contract.Exists(udt.TypeArgs, argType =>argType is ObjectType)) {
  559. Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost");
  560. }
  561. s += "<" + TypeNames(udt.TypeArgs) + ">";
  562. }
  563. return s;
  564. } else if (type is SetType) {
  565. Type argType = ((SetType)type).Arg;
  566. if (argType is ObjectType) {
  567. Error("compilation of set<object> is not supported; consider introducing a ghost");
  568. }
  569. return DafnySetClass + "<" + TypeName(argType) + ">";
  570. } else if (type is SeqType) {
  571. Type argType = ((SeqType)type).Arg;
  572. if (argType is ObjectType) {
  573. Error("compilation of seq<object> is not supported; consider introducing a ghost");
  574. }
  575. return DafnySeqClass + "<" + TypeName(argType) + ">";
  576. } else if (type is MultiSetType) {
  577. Type argType = ((MultiSetType)type).Arg;
  578. if (argType is ObjectType) {
  579. Error("compilation of seq<object> is not supported; consider introducing a ghost");
  580. }
  581. return DafnyMultiSetClass + "<" + TypeName(argType) + ">";
  582. } else {
  583. Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
  584. }
  585. }
  586. string/*!*/ TypeNames(List<Type/*!*/>/*!*/ types) {
  587. Contract.Requires(cce.NonNullElements(types));
  588. Contract.Ensures(Contract.Result<string>() != null);
  589. string s = "";
  590. string sep = "";
  591. foreach (Type t in types) {
  592. s += sep + TypeName(t);
  593. sep = ",";
  594. }
  595. return s;
  596. }
  597. string/*!*/ TypeParameters(List<TypeParameter/*!*/>/*!*/ targs) {
  598. Contract.Requires(cce.NonNullElements(targs));
  599. Contract.Ensures(Contract.Result<string>() != null);
  600. string s = "";
  601. string sep = "";
  602. foreach (TypeParameter tp in targs) {
  603. s += sep + "@" + tp.Name;
  604. sep = ",";
  605. }
  606. return s;
  607. }
  608. string DefaultValue(Type type)
  609. {
  610. Contract.Requires(type != null);
  611. Contract.Ensures(Contract.Result<string>() != null);
  612. while (true) {
  613. TypeProxy tp = type as TypeProxy;
  614. if (tp == null) {
  615. break;
  616. } else if (tp.T == null) {
  617. // unresolved proxy; just treat as ref, since no particular type information is apparently needed for this type
  618. return "null";
  619. } else {
  620. type = tp.T;
  621. }
  622. }
  623. if (type is BoolType) {
  624. return "false";
  625. } else if (type is IntType) {
  626. return "new BigInteger(0)";
  627. } else if (type.IsRefType) {
  628. return string.Format("({0})null", TypeName(type));
  629. } else if (type.IsDatatype) {
  630. UserDefinedType udt = (UserDefinedType)type;
  631. string s = "@" + udt.Name;
  632. if (udt.TypeArgs.Count != 0) {
  633. s += "<" + TypeNames(udt.TypeArgs) + ">";
  634. }
  635. return string.Format("new {0}({0}.Default)", s);
  636. } else if (type.IsTypeParameter) {
  637. UserDefinedType udt = (UserDefinedType)type;
  638. return "default(@" + udt.Name + ")";
  639. } else if (type is SetType) {
  640. return DafnySetClass + "<" + TypeName(((SetType)type).Arg) + ">.Empty";
  641. } else if (type is MultiSetType) {
  642. return DafnyMultiSetClass + "<" + TypeName(((MultiSetType)type).Arg) + ">.Empty";
  643. } else if (type is SeqType) {
  644. return DafnySeqClass + "<" + TypeName(((SeqType)type).Arg) + ">.Empty";
  645. } else {
  646. Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
  647. }
  648. }
  649. // ----- Stmt ---------------------------------------------------------------------------------
  650. void CheckHasNoAssumes(Statement stmt) {
  651. Contract.Requires(stmt != null);
  652. if (stmt is AssumeStmt) {
  653. Error("an assume statement cannot be compiled (line {0})", stmt.Tok.line);
  654. } else if (stmt is BlockStmt) {
  655. foreach (Statement s in ((BlockStmt)stmt).Body) {
  656. CheckHasNoAssumes(s);
  657. }
  658. } else if (stmt is IfStmt) {
  659. IfStmt s = (IfStmt)stmt;
  660. CheckHasNoAssumes(s.Thn);
  661. if (s.Els != null) {
  662. CheckHasNoAssumes(s.Els);
  663. }
  664. } else if (stmt is AlternativeStmt) {
  665. foreach (var alternative in ((AlternativeStmt)stmt).Alternatives) {
  666. foreach (Statement s in alternative.Body) {
  667. CheckHasNoAssumes(s);
  668. }
  669. }
  670. } else if (stmt is WhileStmt) {
  671. WhileStmt s = (WhileStmt)stmt;
  672. CheckHasNoAssumes(s.Body);
  673. } else if (stmt is AlternativeLoopStmt) {
  674. foreach (var alternative in ((AlternativeLoopStmt)stmt).Alternatives) {
  675. foreach (Statement s in alternative.Body) {
  676. CheckHasNoAssumes(s);
  677. }
  678. }
  679. } else if (stmt is ParallelStmt) {
  680. var s = (ParallelStmt)stmt;
  681. CheckHasNoAssumes(s.Body);
  682. } else if (stmt is MatchStmt) {
  683. MatchStmt s = (MatchStmt)stmt;
  684. foreach (MatchCaseStmt mc in s.Cases) {
  685. foreach (Statement bs in mc.Body) {
  686. CheckHasNoAssumes(bs);
  687. }
  688. }
  689. }
  690. }
  691. void TrStmt(Statement stmt, int indent)
  692. {
  693. Contract.Requires(stmt != null);
  694. if (stmt.IsGhost) {
  695. CheckHasNoAssumes(stmt);
  696. return;
  697. }
  698. if (stmt is PrintStmt) {
  699. PrintStmt s = (PrintStmt)stmt;
  700. foreach (Attributes.Argument arg in s.Args) {
  701. SpillLetVariableDecls(arg.E, indent);
  702. Indent(indent);
  703. wr.Write("System.Console.Write(");
  704. if (arg.S != null) {
  705. wr.Write("\"{0}\"", arg.S);
  706. } else {
  707. Contract.Assert(arg.E != null);
  708. TrExpr(arg.E);
  709. }
  710. wr.WriteLine(");");
  711. }
  712. } else if (stmt is BreakStmt) {
  713. var s = (BreakStmt)stmt;
  714. Indent(indent);
  715. wr.WriteLine("goto after_{0};", s.TargetStmt.Labels.UniqueId);
  716. } else if (stmt is ReturnStmt) {
  717. var s = (ReturnStmt)stmt;
  718. if (s.hiddenUpdate != null)
  719. TrStmt(s.hiddenUpdate, indent);
  720. Indent(indent); wr.WriteLine("return;");
  721. } else if (stmt is UpdateStmt) {
  722. var s = (UpdateStmt)stmt;
  723. var resolved = s.ResolvedStatements;
  724. if (resolved.Count == 1) {
  725. TrStmt(resolved[0], indent);
  726. } else {
  727. // multi-assignment
  728. Contract.Assert(s.Lhss.Count == resolved.Count);
  729. Contract.Assert(s.Rhss.Count == resolved.Count);
  730. var lvalues = new List<string>();
  731. var rhss = new List<string>();
  732. for (int i = 0; i < resolved.Count; i++) {
  733. if (!resolved[i].IsGhost) {
  734. var lhs = s.Lhss[i];
  735. var rhs = s.Rhss[i];
  736. if (!(rhs is HavocRhs)) {
  737. lvalues.Add(CreateLvalue(lhs, indent));
  738. string target = "_rhs" + tmpVarCount;
  739. tmpVarCount++;
  740. rhss.Add(target);
  741. TrRhs("var " + target, null, rhs, indent);
  742. }
  743. }
  744. }
  745. Contract.Assert(lvalues.Count == rhss.Count);
  746. for (int i = 0; i < lvalues.Count; i++) {
  747. Indent(indent);
  748. wr.WriteLine("{0} = {1};", lvalues[i], rhss[i]);
  749. }
  750. }
  751. } else if (stmt is AssignStmt) {
  752. AssignStmt s = (AssignStmt)stmt;
  753. Contract.Assert(!(s.Lhs is SeqSelectExpr) || ((SeqSelectExpr)s.Lhs).SelectOne); // multi-element array assignments are not allowed
  754. TrRhs(null, s.Lhs, s.Rhs, indent);
  755. } else if (stmt is VarDecl) {
  756. TrVarDecl((VarDecl)stmt, true, indent);
  757. } else if (stmt is CallStmt) {
  758. CallStmt s = (CallStmt)stmt;
  759. TrCallStmt(s, null, indent);
  760. } else if (stmt is BlockStmt) {
  761. Indent(indent); wr.WriteLine("{");
  762. TrStmtList(((BlockStmt)stmt).Body, indent);
  763. Indent(indent); wr.WriteLine("}");
  764. } else if (stmt is IfStmt) {
  765. IfStmt s = (IfStmt)stmt;
  766. if (s.Guard == null) {
  767. // we can compile the branch of our choice
  768. if (s.Els == null) {
  769. // let's compile the "else" branch, since that involves no work
  770. // (still, let's leave a marker in the source code to indicate that this is what we did)
  771. Indent(indent);
  772. wr.WriteLine("if (!false) { }");
  773. } else {
  774. // let's compile the "then" branch
  775. Indent(indent);
  776. wr.WriteLine("if (true)");
  777. TrStmt(s.Thn, indent);
  778. }
  779. } else {
  780. SpillLetVariableDecls(s.Guard, indent);
  781. Indent(indent); wr.Write("if (");
  782. TrExpr(s.Guard);
  783. wr.WriteLine(")");
  784. TrStmt(s.Thn, indent);
  785. if (s.Els != null) {
  786. Indent(indent); wr.WriteLine("else");
  787. TrStmt(s.Els, indent);
  788. }
  789. }
  790. } else if (stmt is AlternativeStmt) {
  791. var s = (AlternativeStmt)stmt;
  792. foreach (var alternative in s.Alternatives) {
  793. SpillLetVariableDecls(alternative.Guard, indent);
  794. }
  795. Indent(indent);
  796. foreach (var alternative in s.Alternatives) {
  797. wr.Write("if (");
  798. TrExpr(alternative.Guard);
  799. wr.WriteLine(") {");
  800. TrStmtList(alternative.Body, indent);
  801. Indent(indent);
  802. wr.Write("} else ");
  803. }
  804. wr.WriteLine("{ /*unreachable alternative*/ }");
  805. } else if (stmt is WhileStmt) {
  806. WhileStmt s = (WhileStmt)stmt;
  807. if (s.Guard == null) {
  808. Indent(indent);
  809. wr.WriteLine("while (false) { }");
  810. } else {
  811. SpillLetVariableDecls(s.Guard, indent);
  812. Indent(indent);
  813. wr.Write("while (");
  814. TrExpr(s.Guard);
  815. wr.WriteLine(")");
  816. TrStmt(s.Body, indent);
  817. }
  818. } else if (stmt is AlternativeLoopStmt) {
  819. var s = (AlternativeLoopStmt)stmt;
  820. if (s.Alternatives.Count != 0) {
  821. Indent(indent);
  822. wr.WriteLine("while (true) {");
  823. int ind = indent + IndentAmount;
  824. foreach (var alternative in s.Alternatives) {
  825. SpillLetVariableDecls(alternative.Guard, ind);
  826. }
  827. Indent(ind);
  828. foreach (var alternative in s.Alternatives) {
  829. wr.Write("if (");
  830. TrExpr(alternative.Guard);
  831. wr.WriteLine(") {");
  832. TrStmtList(alternative.Body, ind);
  833. Indent(ind);
  834. wr.Write("} else ");
  835. }
  836. wr.WriteLine("{ break; }");
  837. Indent(indent);
  838. wr.WriteLine("}");
  839. }
  840. } else if (stmt is ParallelStmt) {
  841. var s = (ParallelStmt)stmt;
  842. if (s.Kind != ParallelStmt.ParBodyKind.Assign) {
  843. // Call and Proof have no side effects, so they can simply be optimized away.
  844. return;
  845. } else if (s.BoundVars.Count == 0) {
  846. // the bound variables just spell out a single point, so the parallel statement is equivalent to one execution of the body
  847. TrStmt(s.Body, indent);
  848. return;
  849. }
  850. var s0 = (AssignStmt)s.S0;
  851. if (s0.Rhs is HavocRhs) {
  852. // The parallel statement says to havoc a bunch of things. This can be efficiently compiled
  853. // into doing nothing.
  854. return;
  855. }
  856. var rhs = ((ExprRhs)s0.Rhs).Expr;
  857. // Compile:
  858. // parallel (w,x,y,z | Range(w,x,y,z)) {
  859. // LHS(w,x,y,z) := RHS(w,x,y,z);
  860. // }
  861. // where w,x,y,z have types seq<W>,set<X>,int,bool and LHS has L-1 top-level subexpressions
  862. // (that is, L denotes the number of top-level subexpressions of LHS plus 1),
  863. // into:
  864. // var ingredients = new List< L-Tuple >();
  865. // foreach (W w in sq.UniqueElements) {
  866. // foreach (X x in st.Elements) {
  867. // for (BigInteger y = Lo; j < Hi; j++) {
  868. // for (bool z in Helper.AllBooleans) {
  869. // if (Range(w,x,y,z)) {
  870. // ingredients.Add(new L-Tuple( LHS0(w,x,y,z), LHS1(w,x,y,z), ..., RHS(w,x,y,z) ));
  871. // }
  872. // }
  873. // }
  874. // }
  875. // }
  876. // foreach (L-Tuple l in ingredients) {
  877. // LHS[ l0, l1, l2, ..., l(L-2) ] = l(L-1);
  878. // }
  879. //
  880. // Note, because the .NET Tuple class only supports up to 8 components, the compiler implementation
  881. // here supports arrays only up to 6 dimensions. This does not seem like a serious practical limitation.
  882. // However, it may be more noticeable if the parallel statement supported parallel assignments in its
  883. // body. To support cases where tuples would need more than 8 components, .NET Tuple's would have to
  884. // be nested.
  885. // Temporary names
  886. string ingredients = "_ingredients" + tmpVarCount;
  887. string tup = "_tup" + tmpVarCount;
  888. tmpVarCount++;
  889. // Compute L
  890. int L;
  891. string tupleTypeArgs;
  892. if (s0.Lhs is FieldSelectExpr) {
  893. var lhs = (FieldSelectExpr)s0.Lhs;
  894. L = 2;
  895. tupleTypeArgs = TypeName(lhs.Obj.Type);
  896. } else if (s0.Lhs is SeqSelectExpr) {
  897. var lhs = (SeqSelectExpr)s0.Lhs;
  898. L = 3;
  899. // note, we might as well do the BigInteger-to-int cast for array indices here, before putting things into the Tuple rather than when they are extracted from the Tuple
  900. tupleTypeArgs = TypeName(lhs.Seq.Type) + ",int";
  901. } else {
  902. var lhs = (MultiSelectExpr)s0.Lhs;
  903. L = 2 + lhs.Indices.Count;
  904. if (8 < L) {
  905. Error("compiler currently does not support assignments to more-than-6-dimensional arrays in parallel statements");
  906. return;
  907. }
  908. tupleTypeArgs = TypeName(lhs.Array.Type);
  909. for (int i = 0; i < lhs.Indices.Count; i++) {
  910. // note, we might as well do the BigInteger-to-int cast for array indices here, before putting things into the Tuple rather than when they are extracted from the Tuple
  911. tupleTypeArgs += ",int";
  912. }
  913. }
  914. tupleTypeArgs += "," + TypeName(rhs.Type);
  915. // declare and construct "ingredients"
  916. Indent(indent);
  917. wr.WriteLine("var {0} = new List<System.Tuple<{1}>>();", ingredients, tupleTypeArgs);
  918. var n = s.BoundVars.Count;
  919. Contract.Assert(s.Bounds.Count == n);
  920. for (int i = 0; i < n; i++) {
  921. var ind = indent + i * IndentAmount;
  922. var bound = s.Bounds[i];
  923. var bv = s.BoundVars[i];
  924. if (bound is QuantifierExpr.BoolBoundedPool) {
  925. Indent(ind);
  926. wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.Name);
  927. } else if (bound is QuantifierExpr.IntBoundedPool) {
  928. var b = (QuantifierExpr.IntBoundedPool)bound;
  929. SpillLetVariableDecls(b.LowerBound, ind);
  930. SpillLetVariableDecls(b.UpperBound, ind);
  931. Indent(ind);
  932. wr.Write("for (var @{0} = ", bv.Name);
  933. TrExpr(b.LowerBound);
  934. wr.Write("; @{0} < ", bv.Name);
  935. TrExpr(b.UpperBound);
  936. wr.Write("; @{0}++) {{ ", bv.Name);
  937. } else if (bound is QuantifierExpr.SetBoundedPool) {
  938. var b = (QuantifierExpr.SetBoundedPool)bound;
  939. SpillLetVariableDecls(b.Set, ind);
  940. Indent(ind);
  941. wr.Write("foreach (var @{0} in (", bv.Name);
  942. TrExpr(b.Set);
  943. wr.Write(").Elements) { ");
  944. } else if (bound is QuantifierExpr.SeqBoundedPool) {
  945. var b = (QuantifierExpr.SeqBoundedPool)bound;
  946. SpillLetVariableDecls(b.Seq, ind);
  947. Indent(ind);
  948. wr.Write("foreach (var @{0} in (", bv.Name);
  949. TrExpr(b.Seq);
  950. wr.Write(").UniqueElements) { ");
  951. } else {
  952. Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type
  953. }
  954. wr.WriteLine();
  955. }
  956. // if (range) {
  957. // ingredients.Add(new L-Tuple( LHS0(w,x,y,z), LHS1(w,x,y,z), ..., RHS(w,x,y,z) ));
  958. // }
  959. SpillLetVariableDecls(s.Range, indent + n * IndentAmount);
  960. Indent(indent + n * IndentAmount);
  961. wr.Write("if ");
  962. TrParenExpr(s.Range);
  963. wr.WriteLine(" {");
  964. var indFinal = indent + (n + 1) * IndentAmount;
  965. SpillLetVariableDecls(s0.Lhs, indFinal);
  966. SpillLetVariableDecls(rhs, indFinal);
  967. Indent(indFinal);
  968. wr.Write("{0}.Add(new System.Tuple<{1}>(", ingredients, tupleTypeArgs);
  969. if (s0.Lhs is FieldSelectExpr) {
  970. var lhs = (FieldSelectExpr)s0.Lhs;
  971. TrExpr(lhs.Obj);
  972. } else if (s0.Lhs is SeqSelectExpr) {
  973. var lhs = (SeqSelectExpr)s0.Lhs;
  974. TrExpr(lhs.Seq);
  975. wr.Write(", (int)(");
  976. TrExpr(lhs.E0);
  977. wr.Write(")");
  978. } else {
  979. var lhs = (MultiSelectExpr)s0.Lhs;
  980. TrExpr(lhs.Array);
  981. for (int i = 0; i < lhs.Indices.Count; i++) {
  982. wr.Write(", (int)(");
  983. TrExpr(lhs.Indices[i]);
  984. wr.Write(")");
  985. }
  986. wr.WriteLine("] = {0}.Item{1};", tup, L);
  987. }
  988. wr.Write(", ");
  989. TrExpr(rhs);
  990. wr.WriteLine("));");
  991. Indent(indent + n * IndentAmount);
  992. wr.WriteLine("}");
  993. for (int i = n; 0 <= --i; ) {
  994. Indent(indent + i * IndentAmount);
  995. wr.WriteLine("}");
  996. }
  997. // foreach (L-Tuple l in ingredients) {
  998. // LHS[ l0, l1, l2, ..., l(L-2) ] = l(L-1);
  999. // }
  1000. Indent(indent);
  1001. wr.WriteLine("foreach (var {0} in {1}) {{", tup, ingredients);
  1002. Indent(indent + IndentAmount);
  1003. if (s0.Lhs is FieldSelectExpr) {
  1004. var lhs = (FieldSelectExpr)s0.Lhs;
  1005. wr.WriteLine("{0}.Item1.@{1} = {0}.Item2;", tup, lhs.FieldName);
  1006. } else if (s0.Lhs is SeqSelectExpr) {
  1007. var lhs = (SeqSelectExpr)s0.Lhs;
  1008. wr.WriteLine("{0}.Item1[{0}.Item2] = {0}.Item3;", tup);
  1009. } else {
  1010. var lhs = (MultiSelectExpr)s0.Lhs;
  1011. wr.Write("{0}.Item1[");
  1012. string sep = "";
  1013. for (int i = 0; i < lhs.Indices.Count; i++) {
  1014. wr.Write("{0}{1}.Item{2}", sep, tup, i + 2);
  1015. sep = ", ";
  1016. }
  1017. wr.WriteLine("] = {0}.Item{1};", tup, L);
  1018. }
  1019. Indent(indent);
  1020. wr.WriteLine("}");
  1021. } else if (stmt is MatchStmt) {
  1022. MatchStmt s = (MatchStmt)stmt;
  1023. // Type source = e;
  1024. // if (source._D is Dt_Ctor0) {
  1025. // FormalType f0 = ((Dt_Ctor0)source._D).a0;
  1026. // ...
  1027. // Body0;
  1028. // } else if (...) {
  1029. // ...
  1030. // } else if (true) {
  1031. // ...
  1032. // }
  1033. if (s.Cases.Count != 0) {
  1034. SpillLetVariableDecls(s.Source, indent);
  1035. string source = "_source" + tmpVarCount;
  1036. tmpVarCount++;
  1037. Indent(indent);
  1038. wr.Write("{0} {1} = ", TypeName(cce.NonNull(s.Source.Type)), source);
  1039. TrExpr(s.Source);
  1040. wr.WriteLine(";");
  1041. int i = 0;
  1042. foreach (MatchCaseStmt mc in s.Cases) {
  1043. MatchCasePrelude(source, cce.NonNull(mc.Ctor), mc.Arguments, i, s.Cases.Count, indent);
  1044. TrStmtList(mc.Body, indent);
  1045. i++;
  1046. }
  1047. Indent(indent); wr.WriteLine("}");
  1048. }
  1049. } else if (stmt is ConcreteSyntaxStatement) {
  1050. var s = (ConcreteSyntaxStatement)stmt;
  1051. foreach (var ss in s.ResolvedStatements) {
  1052. TrStmt(ss, indent);
  1053. }
  1054. } else {
  1055. Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement
  1056. }
  1057. }
  1058. string CreateLvalue(Expression lhs, int indent) {
  1059. lhs = lhs.Resolved;
  1060. SpillLetVariableDecls(lhs, indent);
  1061. if (lhs is IdentifierExpr) {
  1062. var ll = (IdentifierExpr)lhs;
  1063. return "@" + ll.Var.Name;
  1064. } else if (lhs is FieldSelectExpr) {
  1065. var ll = (FieldSelectExpr)lhs;
  1066. string obj = "_obj" + tmpVarCount;
  1067. tmpVarCount++;
  1068. Indent(indent);
  1069. wr.Write("var {0} = ", obj);
  1070. TrExpr(ll.Obj);
  1071. wr.WriteLine(";");
  1072. return string.Format("{0}.@{1}", obj, ll.Field.Name);
  1073. } else if (lhs is SeqSelectExpr) {
  1074. var ll = (SeqSelectExpr)lhs;
  1075. string arr = "_arr" + tmpVarCount;
  1076. string index = "_index" + tmpVarCount;
  1077. tmpVarCount++;
  1078. Indent(indent);
  1079. wr.Write("var {0} = ", arr);
  1080. TrExpr(ll.Seq);
  1081. wr.WriteLine(";");
  1082. Indent(indent);
  1083. wr.Write("var {0} = ", index);
  1084. TrExpr(ll.E0);
  1085. wr.WriteLine(";");
  1086. return string.Format("{0}[(int){1}]", arr, index);
  1087. } else {
  1088. var ll = (MultiSelectExpr)lhs;
  1089. string arr = "_arr" + tmpVarCount;
  1090. Indent(indent);
  1091. wr.Write("var {0} = ", arr);
  1092. TrExpr(ll.Array);
  1093. wr.WriteLine(";");
  1094. string fullString = arr + "[";
  1095. string sep = "";
  1096. int i = 0;
  1097. foreach (var idx in ll.Indices) {
  1098. string index = "_index" + i + "_" + tmpVarCount;
  1099. Indent(indent);
  1100. wr.Write("var {0} = ", index);
  1101. TrExpr(idx);
  1102. wr.WriteLine(";");
  1103. fullString += sep + "(int)" + index;
  1104. sep = ", ";
  1105. i++;
  1106. }
  1107. tmpVarCount++;
  1108. return fullString + "]";
  1109. }
  1110. }
  1111. void TrRhs(string target, Expression targetExpr, AssignmentRhs rhs, int indent) {
  1112. Contract.Requires((target == null) != (targetExpr == null));
  1113. SpillLetVariableDecls(targetExpr, indent);
  1114. var tRhs = rhs as TypeRhs;
  1115. if (tRhs != null && tRhs.InitCall != null) {
  1116. string nw = "_nw" + tmpVarCount;
  1117. tmpVarCount++;
  1118. Indent(indent);
  1119. wr.Write("var {0} = ", nw);
  1120. TrAssignmentRhs(rhs); // in this case, this call will not require us to spill any let variables first
  1121. wr.WriteLine(";");
  1122. TrCallStmt(tRhs.InitCall, nw, indent);
  1123. Indent(indent);
  1124. if (target != null) {
  1125. wr.Write(target);
  1126. } else {
  1127. TrExpr(targetExpr);
  1128. }
  1129. wr.WriteLine(" = {0};", nw);
  1130. } else if (rhs is HavocRhs) {
  1131. // do nothing
  1132. } else {
  1133. if (rhs is ExprRhs) {
  1134. SpillLetVariableDecls(((ExprRhs)rhs).Expr, indent);
  1135. } else if (tRhs != null && tRhs.ArrayDimensions != null) {
  1136. foreach (Expression dim in tRhs.ArrayDimensions) {
  1137. SpillLetVariableDecls(dim, indent);
  1138. }
  1139. }
  1140. Indent(indent);
  1141. if (target != null) {
  1142. wr.Write(target);
  1143. } else {
  1144. TrExpr(targetExpr);
  1145. }
  1146. wr.Write(" = ");
  1147. TrAssignmentRhs(rhs);
  1148. wr.WriteLine(";");
  1149. }
  1150. }
  1151. void TrCallStmt(CallStmt s, string receiverReplacement, int indent) {
  1152. Contract.Requires(s != null);
  1153. Contract.Assert(s.Method != null); // follows from the fact that stmt has been successfully resolved
  1154. var lvalues = new List<string>();
  1155. Contract.Assert(s.Lhs.Count == s.Method.Outs.Count);
  1156. for (int i = 0; i < s.Method.Outs.Count; i++) {
  1157. Formal p = s.Method.Outs[i];
  1158. if (!p.IsGhost) {
  1159. lvalues.Add(CreateLvalue(s.Lhs[i], indent));
  1160. }
  1161. }
  1162. var outTmps = new List<string>();
  1163. for (int i = 0; i < s.Method.Outs.Count; i++) {
  1164. Formal p = s.Method.Outs[i];
  1165. if (!p.IsGhost) {
  1166. string target = "_out" + tmpVarCount;
  1167. tmpVarCount++;
  1168. outTmps.Add(target);
  1169. Indent(indent);
  1170. wr.WriteLine("{0} {1};", TypeName(s.Lhs[i].Type), target);
  1171. }
  1172. }
  1173. Contract.Assert(lvalues.Count == outTmps.Count);
  1174. for (int i = 0; i < s.Method.Ins.Count; i++) {
  1175. Formal p = s.Method.Ins[i];
  1176. if (!p.IsGhost) {
  1177. SpillLetVariableDecls(s.Args[i], indent);
  1178. }
  1179. }
  1180. if (receiverReplacement != null) {
  1181. Indent(indent);
  1182. wr.Write("@" + receiverReplacement);
  1183. } else if (s.Method.IsStatic) {
  1184. Indent(indent);
  1185. wr.Write(TypeName(cce.NonNull(s.Receiver.Type)));
  1186. } else {
  1187. SpillLetVariableDecls(s.Receiver, indent);
  1188. Indent(indent);
  1189. TrParenExpr(s.Receiver);
  1190. }
  1191. wr.Write(".@{0}(", s.Method.Name);
  1192. string sep = "";
  1193. for (int i = 0; i < s.Method.Ins.Count; i++) {
  1194. Formal p = s.Method.Ins[i];
  1195. if (!p.IsGhost) {
  1196. wr.Write(sep);
  1197. TrExpr(s.Args[i]);
  1198. sep = ", ";
  1199. }
  1200. }
  1201. foreach (var outTmp in outTmps) {
  1202. wr.Write("{0}out {1}", sep, outTmp);
  1203. sep = ", ";
  1204. }
  1205. wr.WriteLine(");");
  1206. // assign to the actual LHSs
  1207. for (int j = 0; j < lvalues.Count; j++) {
  1208. Indent(indent);
  1209. wr.WriteLine("{0} = {1};", lvalues[j], outTmps[j]);
  1210. }
  1211. }
  1212. int tmpVarCount = 0;
  1213. /// <summary>
  1214. /// Before calling TrAssignmentRhs(rhs), the caller must have spilled the let variables declared in "rhs".
  1215. /// </summary>
  1216. void TrAssignmentRhs(AssignmentRhs rhs) {
  1217. Contract.Requires(rhs != null);
  1218. Contract.Requires(!(rhs is HavocRhs));
  1219. if (rhs is ExprRhs) {
  1220. ExprRhs e = (ExprRhs)rhs;
  1221. TrExpr(e.Expr);
  1222. } else {
  1223. TypeRhs tp = (TypeRhs)rhs;
  1224. if (tp.ArrayDimensions == null) {
  1225. wr.Write("new {0}()", TypeName(tp.EType));
  1226. } else {
  1227. if (tp.EType is IntType || tp.EType.IsTypeParameter) {
  1228. // Because the default constructor for BigInteger does not generate a valid BigInteger, we have
  1229. // to excplicitly initialize the elements of an integer array. This is all done in a helper routine.
  1230. wr.Write("Dafny.Helpers.InitNewArray{0}<{1}>", tp.ArrayDimensions.Count, TypeName(tp.EType));
  1231. string prefix = "(";
  1232. foreach (Expression dim in tp.ArrayDimensions) {
  1233. wr.Write(prefix);
  1234. TrExpr(dim);
  1235. prefix = ", ";
  1236. }
  1237. wr.Write(")");
  1238. } else {
  1239. wr.Write("new {0}", TypeName(tp.EType));
  1240. string prefix = "[";
  1241. foreach (Expression dim in tp.ArrayDimensions) {
  1242. wr.Write("{0}(int)", prefix);
  1243. TrExpr(dim);
  1244. prefix = ", ";
  1245. }
  1246. wr.Write("]");
  1247. }
  1248. }
  1249. }
  1250. }
  1251. void TrStmtList(List<Statement/*!*/>/*!*/ stmts, int indent) {Contract.Requires(cce.NonNullElements(stmts));
  1252. foreach (Statement ss in stmts) {
  1253. TrStmt(ss, indent + IndentAmount);
  1254. if (ss.Labels != null) {
  1255. Indent(indent); // labels are not indented as much as the statements
  1256. wr.WriteLine("after_{0}: ;", ss.Labels.UniqueId);
  1257. }
  1258. }
  1259. }
  1260. void TrVarDecl(VarDecl s, bool alwaysInitialize, int indent) {
  1261. Contract.Requires(s != null);
  1262. if (s.IsGhost) {
  1263. // only emit non-ghosts (we get here only for local variables introduced implicitly by call statements)
  1264. return;
  1265. }
  1266. Indent(indent);
  1267. wr.Write("{0} @{1}", TypeName(s.Type), s.Name);
  1268. if (alwaysInitialize) {
  1269. // produce a default value
  1270. wr.WriteLine(" = {0};", DefaultValue(s.Type));
  1271. } else {
  1272. wr.WriteLine(";");
  1273. }
  1274. }
  1275. void MatchCasePrelude(string source, DatatypeCtor ctor, List<BoundVar/*!*/>/*!*/ arguments, int caseIndex, int caseCount, int indent) {
  1276. Contract.Requires(source != null);
  1277. Contract.Requires(ctor != null);
  1278. Contract.Requires(cce.NonNullElements(arguments));
  1279. // if (source._D is Dt_Ctor0) {
  1280. // FormalType f0 = ((Dt_Ctor0)source._D).a0;
  1281. // ...
  1282. Indent(indent);
  1283. wr.Write("{0}if (", caseIndex == 0 ? "" : "} else ");
  1284. if (caseIndex == caseCount - 1) {
  1285. wr.Write("true");
  1286. } else {
  1287. wr.Write("{0}._D is {1}", source, DtCtorName(ctor));
  1288. }
  1289. wr.WriteLine(") {");
  1290. int k = 0; // number of processe…

Large files files are truncated, but you can click here to view the full file