PageRenderTime 69ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/Backend/AST/Expression.cs

https://bitbucket.org/AdamMil/boaold
C# | 1257 lines | 1047 code | 179 blank | 31 comment | 176 complexity | 0c4058fd0348a7115351e9912ce9c7a9 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. Boa is the reference implementation for a language similar to Python,
  3. also called Boa. This implementation is both interpreted and compiled,
  4. targeting the Microsoft .NET Framework.
  5. http://www.adammil.net/
  6. Copyright (C) 2004-2005 Adam Milazzo
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. using System;
  20. using System.Collections;
  21. using System.Reflection;
  22. using System.Reflection.Emit;
  23. using Boa.Runtime;
  24. namespace Boa.AST
  25. {
  26. // TODO: implement decimal: http://python.org/peps/pep-0327.html
  27. // TODO: implement other stuff here: http://python.org/2.4/highlights.html
  28. // TODO: implement sets
  29. // FIXME: allow generator functions/expressions to access closed variables
  30. // eg: def fun(n): return (i+n for i in range(10)) # should be able to access 'n' after return
  31. // TODO: implement interpreted generator functions/expressions
  32. #region Expression
  33. public abstract class Expression : Node
  34. { public virtual void Assign(object value, Frame frame) { throw new NotSupportedException("Assign: "+GetType()); }
  35. public virtual void Delete(Frame frame) { throw new NotSupportedException("Delete: "+GetType()); }
  36. public abstract void Emit(CodeGenerator cg);
  37. public virtual void EmitSet(CodeGenerator cg) { throw new NotSupportedException("EmitSet: "+GetType()); }
  38. public virtual void EmitDel(CodeGenerator cg) { throw new NotSupportedException("EmitDel: "+GetType()); }
  39. public abstract object Evaluate(Frame frame);
  40. public override object GetValue()
  41. { if(!IsConstant) throw new InvalidOperationException();
  42. return Evaluate(null);
  43. }
  44. }
  45. #endregion
  46. #region AndExpression
  47. public class AndExpression : BinaryExpression
  48. { public AndExpression(Expression lhs, Expression rhs) { LHS=lhs; RHS=rhs; SetLocation(lhs); }
  49. public override void Emit(CodeGenerator cg)
  50. { if(IsConstant) cg.EmitConstant(GetValue());
  51. else if(LHS.IsConstant && Ops.IsTrue(LHS.GetValue())) RHS.Emit(cg);
  52. else
  53. { LHS.Emit(cg);
  54. cg.ILG.Emit(OpCodes.Dup);
  55. cg.EmitIsTrue();
  56. Label lab = cg.ILG.DefineLabel();
  57. cg.ILG.Emit(OpCodes.Brfalse, lab);
  58. cg.ILG.Emit(OpCodes.Pop);
  59. RHS.Emit(cg);
  60. cg.ILG.MarkLabel(lab);
  61. }
  62. }
  63. public override object Evaluate(Frame frame)
  64. { object value = LHS.Evaluate(frame);
  65. return Ops.IsTrue(value) ? RHS.Evaluate(frame) : value;
  66. }
  67. public override void Optimize()
  68. { IsConstant = LHS.IsConstant ? Ops.IsTrue(LHS.GetValue()) ? RHS.IsConstant : true : false;
  69. }
  70. public override void ToCode(System.Text.StringBuilder sb, int indent)
  71. { LHS.ToCode(sb, 0);
  72. sb.Append(" && ");
  73. RHS.ToCode(sb, 0);
  74. }
  75. }
  76. #endregion
  77. #region AttrExpression
  78. public class AttrExpression : Expression
  79. { public AttrExpression(Expression o, string attr) { Object=o; Attribute=attr; }
  80. public override void Assign(object value, Frame frame) { Ops.SetAttr(value, Object.Evaluate(frame), Attribute); }
  81. public override void Delete(Frame frame) { Ops.DelAttr(Object.Evaluate(frame), Attribute); }
  82. public override void Emit(CodeGenerator cg)
  83. { Object.Emit(cg);
  84. cg.EmitString(Attribute);
  85. cg.EmitCall(typeof(Ops), "GetAttr", new Type[] { typeof(object), typeof(string) });
  86. }
  87. public override void EmitDel(CodeGenerator cg)
  88. { Object.Emit(cg);
  89. cg.EmitString(Attribute);
  90. cg.EmitCall(typeof(Ops), "DelAttr", new Type[] { typeof(object), typeof(string) });
  91. }
  92. public override void EmitSet(CodeGenerator cg)
  93. { Object.Emit(cg);
  94. cg.EmitString(Attribute);
  95. cg.EmitCall(typeof(Ops), "SetAttr", new Type[] { typeof(object), typeof(object), typeof(string) });
  96. }
  97. public override object Evaluate(Frame frame) { return Ops.GetAttr(Object.Evaluate(frame), Attribute); }
  98. public override void ToCode(System.Text.StringBuilder sb, int indent)
  99. { Object.ToCode(sb, 0);
  100. sb.Append('.');
  101. sb.Append(Attribute);
  102. }
  103. public override void Walk(IWalker w)
  104. { if(w.Walk(this)) Object.Walk(w);
  105. w.PostWalk(this);
  106. }
  107. public Expression Object;
  108. public string Attribute;
  109. }
  110. #endregion
  111. #region BinaryExpression
  112. public abstract class BinaryExpression : Expression
  113. { public override void Optimize() { IsConstant = LHS.IsConstant && RHS.IsConstant; }
  114. public override void Walk(IWalker w)
  115. { if(w.Walk(this))
  116. { LHS.Walk(w);
  117. RHS.Walk(w);
  118. }
  119. w.PostWalk(this);
  120. }
  121. public Expression LHS, RHS;
  122. }
  123. #endregion
  124. #region BinaryOpExpression
  125. public class BinaryOpExpression : BinaryExpression
  126. { public BinaryOpExpression(BinaryOperator op, Expression lhs, Expression rhs)
  127. { Op=op; LHS=lhs; RHS=rhs;
  128. SetLocation(lhs);
  129. }
  130. public override void Emit(CodeGenerator cg)
  131. { if(IsConstant) cg.EmitConstant(GetValue());
  132. else
  133. { LHS.Emit(cg);
  134. RHS.Emit(cg);
  135. Op.Emit(cg);
  136. }
  137. }
  138. public override object Evaluate(Frame frame) { return Op.Evaluate(LHS.Evaluate(frame), RHS.Evaluate(frame)); }
  139. public override void ToCode(System.Text.StringBuilder sb, int indent)
  140. { LHS.ToCode(sb, 0);
  141. sb.Append(Op.ToString());
  142. RHS.ToCode(sb, 0);
  143. }
  144. BinaryOperator Op;
  145. }
  146. #endregion
  147. #region CallExpression
  148. public class CallExpression : Expression
  149. { public CallExpression(Expression target, Argument[] args) { Arguments=args; Target=target; }
  150. public override void Emit(CodeGenerator cg)
  151. { int numlist=0, numdict=0, numruns=0, numnamed=0, runlen=0;
  152. for(int i=0; i<Arguments.Length; i++)
  153. switch(Arguments[i].Type)
  154. { case ArgType.Normal:
  155. if(Arguments[i].Name==null) runlen++;
  156. else numnamed++;
  157. break;
  158. case ArgType.List:
  159. if(runlen>0) { numruns++; runlen=0; }
  160. numlist++;
  161. break;
  162. case ArgType.Dict: numdict++; break;
  163. }
  164. if(runlen>0) { numruns++; runlen=0; }
  165. if(numnamed>0) numruns++;
  166. numruns += numlist + numdict;
  167. Target.Emit(cg);
  168. if(numlist==0 && numdict==0)
  169. { if(numnamed==0)
  170. { if(Arguments.Length==0) cg.EmitCall(typeof(Ops), "Call0", new Type[] { typeof(object) });
  171. else if(Arguments.Length==1)
  172. { Arguments[0].Expression.Emit(cg);
  173. cg.EmitCall(typeof(Ops), "Call1", new Type[] { typeof(object), typeof(object) });
  174. }
  175. else
  176. { EmitRun(cg, Arguments.Length, 0, Arguments.Length);
  177. cg.EmitCall(typeof(Ops), "Call", new Type[] { typeof(object), typeof(object[]) });
  178. }
  179. }
  180. else
  181. { EmitRun(cg, Arguments.Length-numnamed, 0, Arguments.Length);
  182. EmitNamed(cg, numnamed);
  183. cg.EmitCall(typeof(Ops), "Call",
  184. new Type[] { typeof(object), typeof(object[]), typeof(string[]), typeof(object[]) });
  185. }
  186. }
  187. else // TODO: is it worth optimizing constant list args?
  188. { ConstructorInfo ci = typeof(CallArg).GetConstructor(new Type[] { typeof(object), typeof(int) });
  189. int ri=0, rsi=0;
  190. cg.EmitNewArray(typeof(CallArg), numruns);
  191. for(int i=0; i<Arguments.Length; i++) // first we'll do positional arguments
  192. { if(Arguments[i].Name!=null || Arguments[i].Type==ArgType.Dict) continue;
  193. if(Arguments[i].Type==ArgType.Normal) runlen++;
  194. else
  195. { if(runlen>0)
  196. { cg.ILG.Emit(OpCodes.Dup);
  197. cg.EmitInt(ri++);
  198. cg.ILG.Emit(OpCodes.Ldelema, typeof(CallArg));
  199. if(runlen>1)
  200. { EmitRun(cg, runlen, rsi, i);
  201. cg.EmitInt(runlen);
  202. cg.ILG.Emit(OpCodes.Box, typeof(int));
  203. }
  204. else
  205. { for(; rsi<i; rsi++) if(Arguments[rsi].Name==null) { Arguments[rsi].Expression.Emit(cg); break; }
  206. cg.ILG.Emit(OpCodes.Ldnull);
  207. }
  208. cg.EmitNew(ci);
  209. cg.ILG.Emit(OpCodes.Stobj, typeof(CallArg));
  210. }
  211. cg.ILG.Emit(OpCodes.Dup);
  212. cg.EmitInt(ri++);
  213. cg.ILG.Emit(OpCodes.Ldelema, typeof(CallArg));
  214. Arguments[i].Expression.Emit(cg);
  215. cg.EmitFieldGet(typeof(CallArg), "ListType");
  216. cg.EmitNew(ci);
  217. cg.ILG.Emit(OpCodes.Stobj, typeof(CallArg));
  218. runlen=0; rsi=i+1;
  219. }
  220. }
  221. if(runlen>0)
  222. { cg.ILG.Emit(OpCodes.Dup);
  223. cg.EmitInt(ri++);
  224. cg.ILG.Emit(OpCodes.Ldelema, typeof(CallArg));
  225. if(runlen>1)
  226. { EmitRun(cg, runlen, rsi, Arguments.Length);
  227. cg.EmitInt(runlen);
  228. cg.ILG.Emit(OpCodes.Box, typeof(int));
  229. }
  230. else
  231. { for(; rsi<Arguments.Length; rsi++)
  232. if(Arguments[rsi].Name==null) { Arguments[rsi].Expression.Emit(cg); break; }
  233. cg.ILG.Emit(OpCodes.Ldnull);
  234. }
  235. cg.EmitNew(ci);
  236. cg.ILG.Emit(OpCodes.Stobj, typeof(CallArg));
  237. }
  238. if(numnamed>0) // then named arguments
  239. { cg.ILG.Emit(OpCodes.Dup);
  240. cg.EmitInt(ri++);
  241. cg.ILG.Emit(OpCodes.Ldelema, typeof(CallArg));
  242. EmitNamed(cg, numnamed);
  243. cg.EmitNew(ci);
  244. cg.ILG.Emit(OpCodes.Stobj, typeof(CallArg));
  245. }
  246. for(int i=0; i<Arguments.Length; i++)
  247. if(Arguments[i].Type==ArgType.Dict)
  248. { cg.ILG.Emit(OpCodes.Dup);
  249. cg.EmitInt(ri++);
  250. cg.ILG.Emit(OpCodes.Ldelema, typeof(CallArg));
  251. Arguments[i].Expression.Emit(cg);
  252. cg.EmitFieldGet(typeof(CallArg), "DictType");
  253. cg.EmitNew(ci);
  254. cg.ILG.Emit(OpCodes.Stobj, typeof(CallArg));
  255. }
  256. cg.EmitCall(typeof(Ops), "Call", new Type[] { typeof(object), typeof(CallArg[]) });
  257. }
  258. }
  259. public override object Evaluate(Frame frame)
  260. { object callee = Target.Evaluate(frame);
  261. if(Arguments.Length==0) return Ops.Call0(callee);
  262. int numlist=0, numdict=0, numruns=0, numnamed=0, runlen=0;
  263. for(int i=0; i<Arguments.Length; i++)
  264. switch(Arguments[i].Type)
  265. { case ArgType.Normal:
  266. if(Arguments[i].Name==null) runlen++;
  267. else numnamed++;
  268. break;
  269. case ArgType.List:
  270. if(runlen>0) { numruns++; runlen=0; }
  271. numlist++;
  272. break;
  273. case ArgType.Dict: numdict++; break;
  274. }
  275. if(runlen>0) { numruns++; runlen=0; }
  276. if(numnamed>0) numruns++;
  277. numruns += numlist + numdict;
  278. if(numlist==0 && numdict==0)
  279. { if(numnamed==0)
  280. { object[] args = Arguments.Length==0 ? Misc.EmptyArray
  281. : EvaluateRun(frame, Arguments.Length, 0, Arguments.Length);
  282. return Ops.Call(callee, args);
  283. }
  284. else
  285. { string[] names;
  286. object[] values;
  287. EvaluateNamed(frame, numnamed, out names, out values);
  288. return Ops.Call(callee, EvaluateRun(frame, Arguments.Length-numnamed, 0, Arguments.Length), names, values);
  289. }
  290. }
  291. else // TODO: is it worth optimizing constant list args?
  292. { int ri=0, rsi=0;
  293. CallArg[] cargs = new CallArg[numruns];
  294. for(int i=0; i<Arguments.Length; i++) // first we'll do positional arguments
  295. { if(Arguments[i].Name!=null || Arguments[i].Type==ArgType.Dict) continue;
  296. if(Arguments[i].Type==ArgType.Normal) runlen++;
  297. else
  298. { if(runlen>1) cargs[ri++] = new CallArg(EvaluateRun(frame, runlen, rsi, i), runlen);
  299. else if(runlen==1)
  300. { for(; rsi<i; rsi++)
  301. if(Arguments[rsi].Name==null)
  302. { cargs[ri++] = new CallArg(Arguments[rsi].Expression.Evaluate(frame), null);
  303. break;
  304. }
  305. }
  306. cargs[ri++] = new CallArg(Arguments[i].Expression.Evaluate(frame), CallArg.ListType);
  307. runlen=0; rsi=i+1;
  308. }
  309. }
  310. if(runlen>1) cargs[ri++] = new CallArg(EvaluateRun(frame, runlen, rsi, Arguments.Length), runlen);
  311. else if(runlen==1) cargs[ri++] = new CallArg(Arguments[rsi].Expression.Evaluate(frame), null);
  312. if(numnamed>0) // then named arguments
  313. { string[] names;
  314. object[] values;
  315. EvaluateNamed(frame, numnamed, out names, out values);
  316. cargs[ri++] = new CallArg(names, values);
  317. }
  318. if(numdict>0)
  319. for(int i=0; i<Arguments.Length; i++)
  320. if(Arguments[i].Type==ArgType.Dict)
  321. cargs[ri++] = new CallArg(Arguments[i].Expression.Evaluate(frame), CallArg.DictType);
  322. return Ops.Call(callee, cargs);
  323. }
  324. }
  325. public override void ToCode(System.Text.StringBuilder sb, int indent)
  326. { Target.ToCode(sb, 0);
  327. sb.Append('(');
  328. for(int i=0; i<Arguments.Length; i++)
  329. { if(i!=0) sb.Append(", ");
  330. Arguments[i].ToCode(sb);
  331. }
  332. sb.Append(')');
  333. }
  334. public override void Walk(IWalker w)
  335. { if(w.Walk(this))
  336. { Target.Walk(w);
  337. for(int i=0; i<Arguments.Length; i++) if(Arguments[i].Expression!=null) Arguments[i].Expression.Walk(w);
  338. }
  339. w.PostWalk(this);
  340. }
  341. public Argument[] Arguments;
  342. public Expression Target;
  343. void EmitNamed(CodeGenerator cg, int num)
  344. { cg.EmitNewArray(typeof(string), num);
  345. for(int i=0,ai=0; i<Arguments.Length; i++)
  346. if(Arguments[i].Name!=null)
  347. { cg.ILG.Emit(OpCodes.Dup);
  348. cg.EmitInt(ai++);
  349. cg.EmitString(Arguments[i].Name);
  350. cg.ILG.Emit(OpCodes.Stelem_Ref);
  351. }
  352. cg.EmitNewArray(typeof(object), num);
  353. for(int i=0,ai=0; i<Arguments.Length; i++)
  354. if(Arguments[i].Name!=null)
  355. { cg.ILG.Emit(OpCodes.Dup);
  356. cg.EmitInt(ai++);
  357. Arguments[i].Expression.Emit(cg);
  358. cg.ILG.Emit(OpCodes.Stelem_Ref);
  359. }
  360. }
  361. void EmitRun(CodeGenerator cg, int length, int start, int end)
  362. { if(length==0) { cg.ILG.Emit(OpCodes.Ldnull); return; }
  363. cg.EmitNewArray(typeof(object), length);
  364. for(int ai=0; ai<length; start++)
  365. if(Arguments[start].Type==ArgType.Normal && Arguments[start].Name==null)
  366. { cg.ILG.Emit(OpCodes.Dup);
  367. cg.EmitInt(ai++);
  368. Arguments[start].Expression.Emit(cg);
  369. cg.ILG.Emit(OpCodes.Stelem_Ref);
  370. }
  371. }
  372. void EvaluateNamed(Frame frame, int num, out string[] names, out object[] values)
  373. { names = new string[num];
  374. values = new object[num];
  375. for(int i=0,ai=0; i<Arguments.Length; i++)
  376. if(Arguments[i].Name!=null)
  377. { names[ai] = Arguments[i].Name;
  378. values[ai] = Arguments[i].Expression.Evaluate(frame);
  379. ai++;
  380. }
  381. }
  382. object[] EvaluateRun(Frame frame, int length, int start, int end)
  383. { if(length==0) return null;
  384. object[] values = new object[length];
  385. for(int ai=0; ai<length; start++)
  386. if(Arguments[start].Type==ArgType.Normal && Arguments[start].Name==null)
  387. values[ai++] = Arguments[start].Expression.Evaluate(frame);
  388. return values;
  389. }
  390. }
  391. #endregion
  392. #region CompareExpression
  393. public class CompareExpression : Expression
  394. { public CompareExpression(Expression[] exprs, BinaryOperator[] ops)
  395. { Expressions=exprs; Ops=ops; SetLocation(exprs[0]);
  396. }
  397. public override void Emit(CodeGenerator cg)
  398. { if(IsConstant) cg.EmitConstant(GetValue());
  399. else
  400. { Slot tmp = cg.AllocLocalTemp(typeof(object));
  401. MethodInfo istrue = typeof(Ops).GetMethod("IsTrue");
  402. Label end = cg.ILG.DefineLabel();
  403. int i=0;
  404. Expressions[0].Emit(cg);
  405. Expressions[1].Emit(cg);
  406. cg.ILG.Emit(OpCodes.Dup);
  407. tmp.EmitSet(cg);
  408. while(true)
  409. { Ops[i].Emit(cg);
  410. if(++i==Ops.Length) break;
  411. cg.ILG.Emit(OpCodes.Dup);
  412. cg.EmitCall(istrue);
  413. cg.ILG.Emit(OpCodes.Brfalse, end);
  414. cg.ILG.Emit(OpCodes.Pop);
  415. tmp.EmitGet(cg);
  416. Expressions[i+1].Emit(cg);
  417. if(i<Ops.Length-1)
  418. { cg.ILG.Emit(OpCodes.Dup);
  419. tmp.EmitSet(cg);
  420. }
  421. }
  422. cg.ILG.MarkLabel(end);
  423. cg.FreeLocalTemp(tmp);
  424. }
  425. }
  426. public override object Evaluate(Frame frame)
  427. { object a=Expressions[0].Evaluate(frame), b=Expressions[1].Evaluate(frame);
  428. int i=0;
  429. while(true)
  430. { if(!Boa.Runtime.Ops.IsTrue(Ops[i].Evaluate(a, b))) return Boa.Runtime.Ops.FALSE;
  431. a = b;
  432. if(++i==Ops.Length) break;
  433. b = Expressions[i+1].Evaluate(frame);
  434. }
  435. return Boa.Runtime.Ops.TRUE;
  436. }
  437. public override void Optimize()
  438. { bool isconst = true;
  439. for(int i=0; i<Expressions.Length; i++) if(!Expressions[i].IsConstant) { isconst=false; break; }
  440. IsConstant = isconst;
  441. }
  442. public override void ToCode(System.Text.StringBuilder sb, int indent)
  443. { Expressions[0].ToCode(sb, 0);
  444. for(int i=0; i<Ops.Length; )
  445. { sb.Append(Ops[i].ToString());
  446. Expressions[++i].ToCode(sb, 0);
  447. }
  448. }
  449. public override void Walk(IWalker w)
  450. { if(w.Walk(this)) foreach(Expression e in Expressions) e.Walk(w);
  451. w.PostWalk(this);
  452. }
  453. public Expression[] Expressions;
  454. public BinaryOperator[] Ops;
  455. }
  456. #endregion
  457. #region ConstantExpression
  458. public class ConstantExpression : Expression
  459. { public ConstantExpression(object value) { Value=value; IsConstant=true; }
  460. public override void Emit(CodeGenerator cg) { cg.EmitConstant(Value); }
  461. public override object Evaluate(Frame frame) { return Value; }
  462. public override void ToCode(System.Text.StringBuilder sb, int indent)
  463. { if(Value==null) sb.Append("null");
  464. else if(Value is bool) sb.Append((bool)Value ? "true" : "false");
  465. else if(Value is string) sb.Append(StringOps.Escape((string)Value));
  466. else sb.Append(Value);
  467. }
  468. public object Value;
  469. }
  470. #endregion
  471. #region GeneratorExpression
  472. public class GeneratorExpression : ListGenExpression
  473. { public GeneratorExpression(Expression item, ListCompFor[] fors) : base(item, fors) { IsGenerator=true; }
  474. public override void Emit(CodeGenerator cg)
  475. { TypeGenerator tg = cg.TypeGenerator.DefineNestedType(TypeAttributes.Sealed, "ge$f"+Misc.NextIndex,
  476. typeof(Generator));
  477. CodeGenerator nc = tg.DefineMethodOverride(typeof(Generator), "InnerNext", true);
  478. Label yield = nc.ILG.DefineLabel();
  479. Name[] args = new Name[1] { new Name("genarg$", Scope.Local) };
  480. Slot argslot;
  481. nc.IsGenerator = true;
  482. nc.Namespace = new FieldNamespace(cg.Namespace, "_", nc, new ThisSlot(tg.TypeBuilder));
  483. nc.Namespace.SetArgs(args, 0, nc.MethodBase);
  484. argslot = nc.Namespace.GetSlotForSet(args[0]);
  485. nc.EmitPosition(this); // TODO: make sure this is done elsewhere, too
  486. nc.ILG.BeginExceptionBlock();
  487. FieldInfo jump = typeof(Generator).GetField("jump", BindingFlags.Instance|BindingFlags.NonPublic);
  488. nc.ILG.Emit(OpCodes.Ldarg_0);
  489. nc.EmitFieldGet(jump);
  490. nc.EmitInt(0);
  491. nc.ILG.Emit(OpCodes.Ceq);
  492. nc.ILG.Emit(OpCodes.Brtrue, yield);
  493. nc.ILG.Emit(OpCodes.Ldarg_0);
  494. nc.EmitInt(0);
  495. nc.EmitFieldSet(jump);
  496. base.YieldLabel = yield;
  497. EmitFors(nc, argslot);
  498. nc.ILG.BeginCatchBlock(typeof(StopIterationException));
  499. nc.ILG.EndExceptionBlock();
  500. nc.ILG.Emit(OpCodes.Ldc_I4_0);
  501. nc.EmitReturn();
  502. nc.Finish();
  503. cg.EmitNew(tg.TypeBuilder.DefineDefaultConstructor(MethodAttributes.Public));
  504. cg.ILG.Emit(OpCodes.Dup);
  505. Fors[0].List.Emit(cg);
  506. cg.EmitCall(typeof(Ops), "GetEnumerator", new Type[] { typeof(object) });
  507. cg.EmitFieldSet(((FieldSlot)argslot).Info);
  508. }
  509. public override object Evaluate(Frame frame)
  510. { throw new NotImplementedException();
  511. }
  512. public override void ToCode(System.Text.StringBuilder sb, int indent)
  513. { sb.Append('(');
  514. base.ToCode(sb, 0);
  515. sb.Append(')');
  516. }
  517. }
  518. #endregion
  519. #region HashExpression
  520. // TODO: check for duplicate entries
  521. public class HashExpression : Expression
  522. { public HashExpression() : this(new DictionaryEntry[0]) { }
  523. public HashExpression(DictionaryEntry[] entries) { Entries=entries; }
  524. public override void Emit(CodeGenerator cg)
  525. { if(IsConstant)
  526. { cg.EmitConstant(GetValue());
  527. cg.EmitCall(typeof(Dict), "Clone");
  528. }
  529. else
  530. { MethodInfo mi = typeof(Dict).GetMethod("set_Item");
  531. cg.EmitNew(typeof(Dict));
  532. foreach(DictionaryEntry e in Entries)
  533. { cg.ILG.Emit(OpCodes.Dup);
  534. ((Expression)e.Key).Emit(cg);
  535. ((Expression)e.Value).Emit(cg);
  536. cg.EmitCall(mi);
  537. }
  538. }
  539. }
  540. public override object Evaluate(Frame frame)
  541. { Dict dict = new Dict();
  542. foreach(DictionaryEntry e in Entries)
  543. dict[((Expression)e.Key).Evaluate(frame)] = ((Expression)e.Value).Evaluate(frame);
  544. return dict;
  545. }
  546. public override void Optimize()
  547. { foreach(DictionaryEntry de in Entries)
  548. if(!((Expression)de.Key).IsConstant || !((Expression)de.Value).IsConstant) return;
  549. IsConstant = true;
  550. }
  551. public override void ToCode(System.Text.StringBuilder sb, int indent)
  552. { sb.Append('{');
  553. for(int i=0; i<Entries.Length; i++)
  554. { if(i!=0) sb.Append(", ");
  555. ((Expression)Entries[i].Key).ToCode(sb, 0);
  556. sb.Append(':');
  557. ((Expression)Entries[i].Value).ToCode(sb, 0);
  558. }
  559. sb.Append('}');
  560. }
  561. public DictionaryEntry[] Entries;
  562. }
  563. #endregion
  564. #region IndexExpression
  565. public class IndexExpression : Expression
  566. { public IndexExpression(Expression obj, Expression index) { Object=obj; Index=index; }
  567. public override void Assign(object value, Frame frame)
  568. { Ops.SetIndex(value, Object.Evaluate(frame), Index.Evaluate(frame));
  569. }
  570. public override void Delete(Frame frame) { Ops.DelIndex(Object.Evaluate(frame), Index.Evaluate(frame)); }
  571. public override void Emit(CodeGenerator cg)
  572. { if(IsConstant) cg.EmitConstant(GetValue());
  573. else
  574. { Object.Emit(cg);
  575. Index.Emit(cg);
  576. cg.EmitCall(typeof(Ops), "GetIndex");
  577. }
  578. }
  579. public override void EmitDel(CodeGenerator cg)
  580. { Object.Emit(cg);
  581. Index.Emit(cg);
  582. cg.EmitCall(typeof(Ops), "DelIndex");
  583. }
  584. public override void EmitSet(CodeGenerator cg)
  585. { Object.Emit(cg);
  586. Index.Emit(cg);
  587. cg.EmitCall(typeof(Ops), "SetIndex");
  588. }
  589. public override object Evaluate(Frame frame) { return Ops.GetIndex(Object.Evaluate(frame), Index.Evaluate(frame)); }
  590. public override void Optimize() { IsConstant = Object.IsConstant && Index.IsConstant; }
  591. public override void ToCode(System.Text.StringBuilder sb, int indent)
  592. { Object.ToCode(sb, 0);
  593. sb.Append('[');
  594. Index.ToCode(sb, 0);
  595. sb.Append(']');
  596. }
  597. public override void Walk(IWalker w)
  598. { if(w.Walk(this))
  599. { Object.Walk(w);
  600. Index.Walk(w);
  601. }
  602. w.PostWalk(this);
  603. }
  604. public Expression Object, Index;
  605. }
  606. #endregion
  607. #region InExpression
  608. public class InExpression : BinaryExpression
  609. { public InExpression(Expression lhs, Expression rhs, bool not) { LHS=lhs; RHS=rhs; Not=not; }
  610. public override void Emit(CodeGenerator cg)
  611. { if(IsConstant) cg.EmitConstant(GetValue());
  612. else
  613. { LHS.Emit(cg);
  614. RHS.Emit(cg);
  615. cg.EmitBool(Not);
  616. cg.EmitCall(typeof(Ops), "IsIn");
  617. }
  618. }
  619. public override object Evaluate(Frame frame) { return Ops.IsIn(LHS.Evaluate(frame), RHS.Evaluate(frame), Not); }
  620. public override void ToCode(System.Text.StringBuilder sb, int indent)
  621. { LHS.ToCode(sb, 0);
  622. sb.Append(Not ? " not in " : " in ");
  623. RHS.ToCode(sb, 0);
  624. }
  625. public bool Not;
  626. }
  627. #endregion
  628. #region LambdaExpression
  629. public class LambdaExpression : Expression
  630. { public LambdaExpression(Parameter[] parms, Statement body)
  631. { if(body is ExpressionStatement) body = new ReturnStatement(((ExpressionStatement)body).Expression);
  632. else if(body is Suite)
  633. { Suite suite = (Suite)body;
  634. if(suite.Statements.Length==1 && suite.Statements[0] is ExpressionStatement)
  635. body = new ReturnStatement(((ExpressionStatement)suite.Statements[0]).Expression);
  636. }
  637. Function = new BoaFunction(this, parms, body);
  638. }
  639. public override void Emit(CodeGenerator cg) { Function.Emit(cg); }
  640. public override object Evaluate(Frame frame) { return Function.MakeFunction(frame); }
  641. public override void ToCode(System.Text.StringBuilder sb, int indent)
  642. { sb.Append(Function.Parameters.Length==0 ? "lambda" : "lambda ");
  643. for(int i=0; i<Function.Parameters.Length; i++)
  644. { if(i!=0) sb.Append(", ");
  645. Function.Parameters[i].ToCode(sb);
  646. }
  647. sb.Append(": ");
  648. if(Function.Body is Suite)
  649. { Suite suite = (Suite)Function.Body;
  650. for(int i=0; i<suite.Statements.Length; i++)
  651. { if(i!=0) sb.Append("; ");
  652. suite.Statements[i].ToCode(sb, 0);
  653. }
  654. }
  655. else Function.Body.ToCode(sb, 0);
  656. }
  657. public override void Walk(IWalker w) { Function.Walk(w); }
  658. public BoaFunction Function;
  659. }
  660. #endregion
  661. #region ListExpression
  662. public class ListExpression : Expression
  663. { public ListExpression() : this(new Expression[0]) { }
  664. public ListExpression(Expression[] expressions) { Expressions=expressions; }
  665. public override void Emit(CodeGenerator cg)
  666. { if(IsConstant)
  667. { cg.EmitConstant(GetValue());
  668. cg.EmitCall(typeof(List), "Clone");
  669. }
  670. else
  671. { MethodInfo mi = typeof(List).GetMethod("append");
  672. cg.EmitInt(Expressions.Length);
  673. cg.EmitNew(typeof(List), new Type[] { typeof(int) });
  674. foreach(Expression e in Expressions)
  675. { cg.ILG.Emit(OpCodes.Dup);
  676. e.Emit(cg);
  677. cg.EmitCall(mi);
  678. }
  679. }
  680. }
  681. public override object Evaluate(Frame frame)
  682. { List list = new List(Expressions.Length);
  683. foreach(Expression e in Expressions) list.append(e.Evaluate(frame));
  684. return list;
  685. }
  686. public override void Optimize()
  687. { foreach(Expression e in Expressions) if(!e.IsConstant) return;
  688. IsConstant = true;
  689. }
  690. public override void ToCode(System.Text.StringBuilder sb, int indent)
  691. { sb.Append('[');
  692. for(int i=0; i<Expressions.Length; i++)
  693. { if(i!=0) sb.Append(", ");
  694. Expressions[i].ToCode(sb, 0);
  695. }
  696. sb.Append(']');
  697. }
  698. public Expression[] Expressions;
  699. }
  700. #endregion
  701. #region ListCompExpression
  702. public class ListCompExpression : ListGenExpression
  703. { public ListCompExpression(Expression item, ListCompFor[] fors) : base(item, fors) { }
  704. public override void Emit(CodeGenerator cg)
  705. { if(IsConstant) cg.EmitConstant(GetValue());
  706. else
  707. { Slot list = cg.AllocLocalTemp(typeof(List), true);
  708. cg.EmitNew(typeof(List), Type.EmptyTypes);
  709. list.EmitSet(cg);
  710. // FIXME: this should catch StopIteration, but try blocks empty the evaluation stack...
  711. // cg.ILG.BeginExceptionBlock();
  712. EmitFors(cg, list);
  713. // cg.ILG.BeginCatchBlock(typeof(StopIterationException));
  714. // cg.ILG.EndExceptionBlock();
  715. list.EmitGet(cg);
  716. cg.FreeLocalTemp(list);
  717. }
  718. }
  719. public override object Evaluate(Frame frame)
  720. { List list = new List();
  721. try { EvaluateFor(frame, list, 0); } catch(StopIterationException) { }
  722. return list;
  723. }
  724. public override void Optimize()
  725. { // TODO: implement this
  726. }
  727. public override void ToCode(System.Text.StringBuilder sb, int indent)
  728. { sb.Append('[');
  729. base.ToCode(sb, 0);
  730. sb.Append(']');
  731. }
  732. void EvaluateFor(Frame frame, List list, int n)
  733. { ConstantExpression ce = new ConstantExpression(null);
  734. AssignStatement ass = new AssignStatement(Fors[n].Names, ce);
  735. IEnumerator e = Ops.GetEnumerator(Fors[n].List.Evaluate(frame));
  736. bool last = n==Fors.Length-1;
  737. while(e.MoveNext())
  738. { ce.Value = e.Current;
  739. ass.Execute(frame);
  740. if(Fors[n].Test==null || Ops.IsTrue(Fors[n].Test.Evaluate(frame)))
  741. { if(last) list.append(Item.Evaluate(frame));
  742. else EvaluateFor(frame, list, n+1);
  743. }
  744. }
  745. }
  746. }
  747. #endregion
  748. #region ListGenExpression
  749. public abstract class ListGenExpression : Expression
  750. { public ListGenExpression(Expression item, ListCompFor[] fors)
  751. { Item=item; Fors=fors;
  752. Name[] names = NameFinder.Find(item);
  753. foreach(Name itemname in names)
  754. foreach(ListCompFor f in fors)
  755. { NameExpression n = f.Names as NameExpression;
  756. if(n==null)
  757. { TupleExpression te = (TupleExpression)f.Names;
  758. foreach(NameExpression ne in te.Expressions)
  759. if(ne.Name.String==itemname.String) { itemname.Scope=Scope.Temporary; break; }
  760. }
  761. else if(n.Name.String==itemname.String) itemname.Scope=Scope.Temporary;
  762. }
  763. }
  764. public override void ToCode(System.Text.StringBuilder sb, int indent)
  765. { Item.ToCode(sb, 0);
  766. for(int i=0; i<Fors.Length; i++) Fors[i].ToCode(sb);
  767. }
  768. public override void Walk(IWalker w)
  769. { if(w.Walk(this))
  770. { Item.Walk(w);
  771. foreach(ListCompFor f in Fors)
  772. { f.List.Walk(w);
  773. if(f.Test!=null) f.Test.Walk(w);
  774. }
  775. }
  776. w.PostWalk(this);
  777. }
  778. public Expression Item;
  779. public ListCompFor[] Fors;
  780. protected void EmitFor(CodeGenerator cg, Slot slot, int n)
  781. { AssignStatement ass = new AssignStatement(Fors[n].Names);
  782. Label next = cg.ILG.DefineLabel(), end = cg.ILG.DefineLabel();
  783. Slot e = cg.AllocLocalTemp(typeof(IEnumerator), true);
  784. if(!IsGenerator || n>0)
  785. { Fors[n].List.Emit(cg);
  786. cg.EmitCall(typeof(Ops), "GetEnumerator", new Type[] { typeof(object) });
  787. }
  788. else slot.EmitGet(cg);
  789. e.EmitSet(cg);
  790. cg.Namespace.BeginScope(Misc.ToNameArray(Fors[n].Names), true);
  791. cg.ILG.MarkLabel(next);
  792. e.EmitGet(cg);
  793. cg.EmitCall(typeof(IEnumerator), "MoveNext");
  794. cg.ILG.Emit(OpCodes.Brfalse, end);
  795. e.EmitGet(cg);
  796. cg.EmitPropGet(typeof(IEnumerator), "Current");
  797. ass.Emit(cg);
  798. if(Fors[n].Test!=null)
  799. { Fors[n].Test.Emit(cg);
  800. cg.EmitIsTrue();
  801. cg.ILG.Emit(OpCodes.Brfalse, next);
  802. }
  803. if(n==Fors.Length-1)
  804. { if(IsGenerator)
  805. { cg.ILG.Emit(OpCodes.Ldarg_1);
  806. Item.Emit(cg);
  807. cg.ILG.Emit(OpCodes.Stind_Ref);
  808. cg.ILG.Emit(OpCodes.Ldc_I4_1);
  809. cg.EmitReturn();
  810. cg.ILG.MarkLabel(YieldLabel);
  811. }
  812. else
  813. { slot.EmitGet(cg);
  814. Item.Emit(cg);
  815. cg.EmitCall(typeof(List), "append");
  816. }
  817. }
  818. else EmitFor(cg, slot, n+1);
  819. cg.ILG.Emit(OpCodes.Br, next);
  820. cg.ILG.MarkLabel(end);
  821. cg.Namespace.EndScope();
  822. cg.FreeLocalTemp(e);
  823. }
  824. protected void EmitFors(CodeGenerator cg, Slot slot) { EmitFor(cg, slot, 0); }
  825. protected Label YieldLabel;
  826. protected bool IsGenerator;
  827. }
  828. #endregion
  829. #region NameExpression
  830. public class NameExpression : Expression
  831. { public NameExpression(string name) { Name=new Name(name); }
  832. public NameExpression(Name name) { Name=name; }
  833. public override void Assign(object value, Frame frame) { frame.Set(Name.String, value); }
  834. public override void Delete(Frame frame) { frame.Delete(Name.String); }
  835. public override void Emit(CodeGenerator cg) { cg.EmitGet(Name); }
  836. public override void EmitDel(CodeGenerator cg) { cg.EmitDel(Name); }
  837. public override void EmitSet(CodeGenerator cg) { cg.EmitSet(Name); }
  838. public override object Evaluate(Frame frame) { return frame.Get(Name.String); }
  839. public override void ToCode(System.Text.StringBuilder sb, int indent) { sb.Append(Name.String); }
  840. public Name Name;
  841. }
  842. #endregion
  843. #region OrExpression
  844. public class OrExpression : BinaryExpression
  845. { public OrExpression(Expression lhs, Expression rhs) { LHS=lhs; RHS=rhs; SetLocation(lhs); }
  846. public override void Emit(CodeGenerator cg)
  847. { if(IsConstant) cg.EmitConstant(GetValue());
  848. else if(LHS.IsConstant && !Ops.IsTrue(LHS.GetValue())) RHS.Emit(cg);
  849. else
  850. { LHS.Emit(cg);
  851. cg.ILG.Emit(OpCodes.Dup);
  852. cg.EmitIsTrue();
  853. Label lab = cg.ILG.DefineLabel();
  854. cg.ILG.Emit(OpCodes.Brtrue, lab);
  855. cg.ILG.Emit(OpCodes.Pop);
  856. RHS.Emit(cg);
  857. cg.ILG.MarkLabel(lab);
  858. }
  859. }
  860. public override object Evaluate(Frame frame)
  861. { object value = LHS.Evaluate(frame);
  862. return Ops.IsTrue(value) ? value : RHS.Evaluate(frame);
  863. }
  864. public override void Optimize()
  865. { IsConstant = LHS.IsConstant ? Ops.IsTrue(LHS.GetValue()) ? true : RHS.IsConstant : false;
  866. }
  867. public override void ToCode(System.Text.StringBuilder sb, int indent)
  868. { LHS.ToCode(sb, 0);
  869. sb.Append(" || ");
  870. RHS.ToCode(sb, 0);
  871. }
  872. }
  873. #endregion
  874. #region ParenExpression
  875. public class ParenExpression : Expression
  876. { public ParenExpression(Expression e) { Expression=e; }
  877. public override void Assign(object value, Frame frame) { Expression.Assign(value, frame); }
  878. public override void Delete(Frame frame) { Expression.Delete(frame); }
  879. public override void Emit(CodeGenerator cg) { Expression.Emit(cg); }
  880. public override void EmitDel(CodeGenerator cg) { Expression.EmitDel(cg); }
  881. public override void EmitSet(CodeGenerator cg) { Expression.EmitSet(cg); }
  882. public override object Evaluate(Frame frame) { return Expression.Evaluate(frame); }
  883. public override void Optimize() { IsConstant = Expression.IsConstant; }
  884. public override void ToCode(System.Text.StringBuilder sb, int indent)
  885. { sb.Append('(');
  886. Expression.ToCode(sb, 0);
  887. sb.Append(')');
  888. }
  889. public override void Walk(IWalker w)
  890. { if(w.Walk(this)) Expression.Walk(w);
  891. w.PostWalk(this);
  892. }
  893. public Expression Expression;
  894. }
  895. #endregion
  896. #region ReprExpression
  897. public class ReprExpression : Expression
  898. { public ReprExpression(Expression expr) { Expression=expr; }
  899. public override void Emit(CodeGenerator cg)
  900. { if(IsConstant) cg.EmitConstant(GetValue());
  901. else
  902. { Expression.Emit(cg);
  903. cg.EmitCall(typeof(Ops), "Repr");
  904. }
  905. }
  906. public override object Evaluate(Frame frame) { return Ops.Repr(Expression.Evaluate(frame)); }
  907. public override void Optimize() { IsConstant = Expression.IsConstant; }
  908. public override void ToCode(System.Text.StringBuilder sb, int indent)
  909. { sb.Append('`');
  910. Expression.ToCode(sb, 0);
  911. sb.Append('`');
  912. }
  913. public override void Walk(IWalker w)
  914. { if(w.Walk(this)) Expression.Walk(w);
  915. w.PostWalk(this);
  916. }
  917. public Expression Expression;
  918. }
  919. #endregion
  920. #region SliceExpression
  921. public class SliceExpression : Expression
  922. { public SliceExpression(Expression start, Expression stop) : this(start, stop, null) { }
  923. public SliceExpression(Expression start, Expression stop, Expression step) { Start=start; Stop=stop; Step=step; }
  924. public override void Emit(CodeGenerator cg)
  925. { if(IsConstant) cg.EmitConstant(GetValue());
  926. else
  927. { cg.EmitExpression(Start);
  928. cg.EmitExpression(Stop);
  929. cg.EmitExpression(Step);
  930. cg.EmitNew(typeof(Slice), new Type[] { typeof(object), typeof(object), typeof(object) });
  931. }
  932. }
  933. public override object Evaluate(Frame frame)
  934. { return new Slice(Start==null ? null : Start.Evaluate(frame), Stop==null ? null : Stop.Evaluate(frame),
  935. Step ==null ? null : Step.Evaluate(frame));
  936. }
  937. public override void Optimize()
  938. { IsConstant = (Start==null || Start.IsConstant) && (Stop==null || Stop.IsConstant) &&
  939. (Step==null || Step.IsConstant);
  940. }
  941. public override void ToCode(System.Text.StringBuilder sb, int indent)
  942. { Start.ToCode(sb, 0);
  943. sb.Append(':');
  944. if(Stop!=null) Stop.ToCode(sb, 0);
  945. if(Step!=null)
  946. { sb.Append(':');
  947. Step.ToCode(sb, 0);
  948. }
  949. }
  950. public override void Walk(IWalker w)
  951. { if(w.Walk(this))
  952. { if(Start!=null) Start.Walk(w);
  953. if(Stop!=null) Stop.Walk(w);
  954. if(Step!=null) Step.Walk(w);
  955. }
  956. w.PostWalk(this);
  957. }
  958. public Expression Start, Stop, Step;
  959. }
  960. #endregion
  961. #region TernaryExpression
  962. public class TernaryExpression : Expression
  963. { public TernaryExpression(Expression test, Expression ifTrue, Expression ifFalse)
  964. { Test=test; IfTrue=ifTrue; IfFalse=ifFalse;
  965. }
  966. public override void Emit(CodeGenerator cg)
  967. { if(IsConstant) cg.EmitConstant(GetValue());
  968. else
  969. { Label end = cg.ILG.DefineLabel(), iff = cg.ILG.DefineLabel();
  970. Test.Emit(cg);
  971. cg.EmitIsTrue();
  972. cg.ILG.Emit(OpCodes.Brfalse, iff);
  973. IfTrue.Emit(cg);
  974. cg.ILG.Emit(OpCodes.Br, end);
  975. cg.ILG.MarkLabel(iff);
  976. IfFalse.Emit(cg);
  977. cg.ILG.MarkLabel(end);
  978. }
  979. }
  980. public override object Evaluate(Frame frame)
  981. { return Ops.IsTrue(Test.Evaluate(frame)) ? IfTrue.Evaluate(frame) : IfFalse.Evaluate(frame);
  982. }
  983. public override void Optimize()
  984. { if(Test.IsConstant)
  985. { bool isTrue = Ops.IsTrue(Test.GetValue());
  986. IsConstant = isTrue && IfTrue.IsConstant || !isTrue && IfFalse.IsConstant;
  987. }
  988. else IsConstant = false;
  989. }
  990. public override void ToCode(System.Text.StringBuilder sb, int indent)
  991. { Test.ToCode(sb, 0);
  992. sb.Append(" ? ");
  993. IfTrue.ToCode(sb, 0);
  994. sb.Append(" : ");
  995. IfFalse.ToCode(sb, 0);
  996. }
  997. public override void Walk(IWalker w)
  998. { if(w.Walk(this))
  999. { Test.Walk(w);
  1000. IfTrue.Walk(w);
  1001. IfFalse.Walk(w);
  1002. }
  1003. w.PostWalk(this);
  1004. }
  1005. public Expression Test, IfTrue, IfFalse;
  1006. }
  1007. #endregion
  1008. #region TupleExpression
  1009. public class TupleExpression : Expression
  1010. { public TupleExpression() : this(new Expression[0]) { }
  1011. public TupleExpression(Expression[] expressions) { Expressions=expressions; }
  1012. public override void Assign(object value, Frame frame)
  1013. { IEnumerator e = Ops.PrepareTupleAssignment(value, Expressions.Length);
  1014. for(int i=0; i<Expressions.Length; i++)
  1015. { e.MoveNext();
  1016. Expressions[i].Assign(e.Current, frame);
  1017. }
  1018. }
  1019. public override void EmitDel(CodeGenerator cg) { foreach(Expression e in Expressions) e.EmitDel(cg); }
  1020. public override void Emit(CodeGenerator cg)
  1021. { if(IsConstant) cg.EmitConstant(GetValue());
  1022. else
  1023. { cg.EmitObjectArray(Expressions);
  1024. cg.EmitNew(typeof(Tuple), new Type[] { typeof(object[]) });
  1025. }
  1026. }
  1027. public override object Evaluate(Frame frame)
  1028. { object[] arr = new object[Expressions.Length];
  1029. for(int i=0; i<arr.Length; i++) arr[i] = Expressions[i].Evaluate(frame);
  1030. return new Tuple(arr);
  1031. }
  1032. public override void Optimize()
  1033. { foreach(Expression e in Expressions) if(!e.IsConstant) return;
  1034. IsConstant = true;
  1035. }
  1036. public override void ToCode(System.Text.StringBuilder sb, int indent)
  1037. { sb.Append('(');
  1038. for(int i=0; i<Expressions.Length; i++)
  1039. { if(i!=0) sb.Append(", ");
  1040. Expressions[i].ToCode(sb, 0);
  1041. }
  1042. if(Expressions.Length==1) sb.Append(',');
  1043. sb.Append(')');
  1044. }
  1045. public override void Walk(IWalker w)
  1046. { if(w.Walk(this)) foreach(Expression e in Expressions) e.Walk(w);
  1047. w.PostWalk(this);
  1048. }
  1049. public Expression[] Expressions;
  1050. }
  1051. #endregion
  1052. #region UnaryExpression
  1053. public class UnaryExpression : Expression
  1054. { public UnaryExpression(Expression expr, UnaryOperator op) { Expression=expr; Op=op; }
  1055. public override object Evaluate(Frame frame) { return Op.Evaluate(Expression.Evaluate(frame)); }
  1056. public override void Emit(CodeGenerator cg)
  1057. { if(IsConstant) cg.EmitConstant(GetValue());
  1058. else
  1059. { Expression.Emit(cg);
  1060. Op.Emit(cg);
  1061. }
  1062. }
  1063. public override void Optimize() { IsConstant=Expression.IsConstant; }
  1064. public override void ToCode(System.Text.StringBuilder sb, int indent)
  1065. { sb.Append(Op.ToString());
  1066. Expression.ToCode(sb, 0);
  1067. }
  1068. public override void Walk(IWalker w)
  1069. { if(w.Walk(this)) Expression.Walk(w);
  1070. w.PostWalk(this);
  1071. }
  1072. public Expression Expression;
  1073. public UnaryOperator Op;
  1074. }
  1075. #endregion
  1076. } // namespace Boa.AST