PageRenderTime 55ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 2ms

/lib/CodeGen.cs

http://github.com/sorear/niecza
C# | 4727 lines | 4240 code | 385 blank | 102 comment | 885 complexity | 2cb1760051616a05e216acc2c6e32958 MD5 | raw file
Possible License(s): AGPL-3.0

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

  1. // This is the new CLR backend. The old one generated C# from Perl, which
  2. // was slow and gave us the limitations of C#; this one aims to be faster.
  3. // Also, by making the Perl code emit a portable format, it makes future
  4. // portability work easier.
  5. using System;
  6. using System.Reflection;
  7. using System.Reflection.Emit;
  8. using System.Collections.Generic;
  9. using System.Collections;
  10. using System.Text;
  11. using System.IO;
  12. using Niecza;
  13. using Mono.Terminal;
  14. namespace Niecza.CLRBackend {
  15. // The portable format is a subset of JSON, and is currently read
  16. // into a matching internal form.
  17. static class JScalar {
  18. public static string[] SA(int cut, object x) {
  19. object[] arr = (object[]) x;
  20. string[] r = new string[ arr.Length - cut ];
  21. for (int i = 0; i < r.Length; i++)
  22. r[i] = S(arr[i+cut]);
  23. return r;
  24. }
  25. public static int[] IA(int cut, object x) {
  26. object[] arr = (object[]) x;
  27. int[] r = new int[ arr.Length - cut ];
  28. for (int i = 0; i < r.Length; i++)
  29. r[i] = I(arr[i+cut]);
  30. return r;
  31. }
  32. public static T[] A<T>(int cut, object x, Func<object, T> rdr) {
  33. object[] arr = (object[]) x;
  34. T[] r = new T[ arr.Length - cut ];
  35. for (int i = 0; i < r.Length; i++)
  36. r[i] = rdr(arr[i+cut]);
  37. return r;
  38. }
  39. public static bool B(object x) {
  40. string s = S(x);
  41. if (s == "1") return true;
  42. if (s == "0" || s == "") return false;
  43. throw new ArgumentException(s);
  44. }
  45. public static int I(object x) { return (int)N(x); }
  46. public static double N(object x) { return Utils.S2N((string)x); }
  47. public static int IN(object x) { return x == null ? -1 : (int)N(x); }
  48. public static string S(object x) { return x == null ? null : ((string)x); }
  49. }
  50. class Reader {
  51. static char GetHexQuad(char[] s, int ix) {
  52. int acc = 0;
  53. for (int i = 0; i < 4; i++) {
  54. acc <<= 4;
  55. int ch = (int)s[ix+i];
  56. acc += (ch>=(int)'a'&&ch<=(int)'f') ? (ch + 10 - (int)'a') :
  57. (ch>=(int)'A'&&ch<=(int)'F') ? (ch + 10 - (int)'A') :
  58. (ch - (int)'0');
  59. }
  60. return (char)acc;
  61. }
  62. public static object Read(string inputx, object[] refs) {
  63. char[] input = inputx.ToCharArray();
  64. int ilen = input.Length;
  65. int start, write;
  66. int ix = 0;
  67. List<List<object>> containers = new List<List<object>>();
  68. char i;
  69. while (true) {
  70. i = input[ix];
  71. if (i == '\t' || i == ' ' || i == '\r' || i == '\n' ||
  72. i == ',' || i == ':') {
  73. ix++;
  74. continue;
  75. }
  76. if (i == '[' || i == '{') {
  77. containers.Add(new List<object>());
  78. ix++;
  79. continue;
  80. }
  81. if (i == ']' || i == '}') {
  82. object[] r = containers[containers.Count - 1].ToArray();
  83. containers.RemoveAt(containers.Count - 1);
  84. if (containers.Count == 0) return r;
  85. containers[containers.Count - 1].Add(r);
  86. ix++;
  87. continue;
  88. }
  89. if (i == 'n' && ilen >= ix + 4 &&
  90. input[ix+1] == 'u' && input[ix+2] == 'l' &&
  91. input[ix+3] == 'l') {
  92. containers[containers.Count - 1].Add(null);
  93. ix += 4;
  94. continue;
  95. }
  96. if (i == '"') {
  97. ix++;
  98. start = ix;
  99. write = ix;
  100. while (true) {
  101. i = input[ix];
  102. if (i == '\\') {
  103. switch (input[ix+1]) {
  104. case '/': i = '/'; break;
  105. case '\\': i = '\\'; break;
  106. case '"': i = '"'; break;
  107. case 't': i = '\t'; break;
  108. case 'r': i = '\r'; break;
  109. case 'n': i = '\n'; break;
  110. case 'f': i = '\f'; break;
  111. case 'b': i = '\b'; break;
  112. case 'u': i = GetHexQuad(input, ix+2); ix += 4; break;
  113. }
  114. ix += 2;
  115. input[write++] = i;
  116. } else if (i == '"') {
  117. break;
  118. } else {
  119. input[write++] = i;
  120. ix++;
  121. }
  122. }
  123. ix++;
  124. containers[containers.Count - 1].Add(new string(input, start, write - start));
  125. continue;
  126. }
  127. start = ix;
  128. while (true) {
  129. i = input[ix];
  130. if (i == ',' || i == '\r' || i == '\t' || i == '\n' ||
  131. i == ' ' || i == ']' || i == '}')
  132. break;
  133. ix++;
  134. }
  135. if (input[start] == '!') {
  136. string str = new string(input, start+1, ix - start - 1);
  137. containers[containers.Count - 1].Add(refs[int.Parse(str)]);
  138. } else {
  139. containers[containers.Count - 1].Add(new string(input, start, ix - start));
  140. }
  141. }
  142. }
  143. }
  144. // Extra info needed beyond what ILGenerator alone provides. Note
  145. // that switch generation is done in another pass.
  146. class CgContext {
  147. public ILGenerator il;
  148. public TypeBuilder tb;
  149. public int next_case;
  150. public Label[] cases;
  151. public int num_cases;
  152. public Dictionary<string,int> named_cases
  153. = new Dictionary<string,int>();
  154. public Dictionary<string,Label> named_labels
  155. = new Dictionary<string,Label>();
  156. public string[] let_names = new string[0];
  157. public Type[] let_types = new Type[0];
  158. public LocalBuilder ospill, sspill, pspill, nspill;
  159. public List<int> lineStack = new List<int>();
  160. public List<int> lineBuffer = new List<int>();
  161. public List<int> ehspanBuffer = new List<int>();
  162. public List<string> ehlabelBuffer = new List<string>();
  163. public List<LocalBuilder> scratches = new List<LocalBuilder>();
  164. public void make_ospill() {
  165. if (ospill == null)
  166. ospill = il.DeclareLocal(Tokens.Variable);
  167. }
  168. public void make_sspill() {
  169. if (sspill == null)
  170. sspill = il.DeclareLocal(Tokens.Variable);
  171. }
  172. public void save_line() {
  173. lineBuffer.Add(lineStack.Count == 0 ? 0 : lineStack[lineStack.Count - 1]);
  174. }
  175. public void EmitDataArray(Type ty, int ct, byte[] vec) {
  176. EmitInt(ct);
  177. // the mono JIT checks for this exact sequence
  178. il.Emit(OpCodes.Newarr, ty);
  179. if (vec.Length != 0) {
  180. FieldBuilder fb = tb.DefineInitializedData(
  181. "A" + (EmitUnit.Current.nextid++), vec, 0);
  182. il.Emit(OpCodes.Dup);
  183. il.Emit(OpCodes.Ldtoken, fb);
  184. il.Emit(OpCodes.Call, typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray"));
  185. }
  186. }
  187. // logic stolen from mcs
  188. public void EmitInt(int i) {
  189. switch (i) {
  190. case -1: il.Emit(OpCodes.Ldc_I4_M1); break;
  191. case 0: il.Emit(OpCodes.Ldc_I4_0); break;
  192. case 1: il.Emit(OpCodes.Ldc_I4_1); break;
  193. case 2: il.Emit(OpCodes.Ldc_I4_2); break;
  194. case 3: il.Emit(OpCodes.Ldc_I4_3); break;
  195. case 4: il.Emit(OpCodes.Ldc_I4_4); break;
  196. case 5: il.Emit(OpCodes.Ldc_I4_5); break;
  197. case 6: il.Emit(OpCodes.Ldc_I4_6); break;
  198. case 7: il.Emit(OpCodes.Ldc_I4_7); break;
  199. case 8: il.Emit(OpCodes.Ldc_I4_8); break;
  200. default:
  201. if (i >= -128 && i < 127) {
  202. il.Emit(OpCodes.Ldc_I4_S, (sbyte) i);
  203. } else {
  204. il.Emit(OpCodes.Ldc_I4, i);
  205. }
  206. break;
  207. }
  208. }
  209. /* this too */
  210. public void EmitLong(long l) {
  211. if (l >= int.MinValue && l <= int.MaxValue) {
  212. EmitInt((int)l);
  213. il.Emit(OpCodes.Conv_I8);
  214. } else if (l >= 0 && l <= uint.MaxValue) {
  215. EmitInt((int)l);
  216. il.Emit(OpCodes.Conv_U8);
  217. } else {
  218. il.Emit(OpCodes.Ldc_I8, l);
  219. }
  220. }
  221. public void EmitPreSetlex(int ix) {
  222. if (ix >= (Tokens.NumInt32 + Tokens.NumInline)) {
  223. il.Emit(OpCodes.Ldfld, Tokens.Frame_lexn);
  224. EmitInt(ix - (Tokens.NumInt32 + Tokens.NumInline));
  225. }
  226. }
  227. public void EmitSetlex(int ix, Type t) {
  228. if (ix >= Tokens.NumInt32 && t.IsValueType)
  229. il.Emit(OpCodes.Box, t);
  230. if (ix >= (Tokens.NumInt32 + Tokens.NumInline)) {
  231. il.Emit(OpCodes.Stelem_Ref);
  232. } else if (ix >= Tokens.NumInt32) {
  233. il.Emit(OpCodes.Stfld,
  234. Tokens.Frame_lexobj[ix - Tokens.NumInt32]);
  235. } else {
  236. il.Emit(OpCodes.Stfld, Tokens.Frame_lexi32[ix]);
  237. }
  238. }
  239. public void EmitGetlex(int ix, Type t) {
  240. if (ix >= (Tokens.NumInt32 + Tokens.NumInline)) {
  241. il.Emit(OpCodes.Ldfld, Tokens.Frame_lexn);
  242. EmitInt(ix - (Tokens.NumInt32 + Tokens.NumInline));
  243. il.Emit(OpCodes.Ldelem_Ref);
  244. } else if (ix >= Tokens.NumInt32) {
  245. il.Emit(OpCodes.Ldfld,
  246. Tokens.Frame_lexobj[ix - Tokens.NumInt32]);
  247. } else {
  248. il.Emit(OpCodes.Ldfld, Tokens.Frame_lexi32[ix]);
  249. }
  250. if (ix >= Tokens.NumInt32 &&
  251. (Config.CGVerifiable || t.IsValueType)) {
  252. il.Emit(OpCodes.Unbox_Any, t);
  253. }
  254. }
  255. }
  256. sealed class Tokens {
  257. public static readonly Type Void = typeof(void);
  258. public static readonly Type String = typeof(string);
  259. public static readonly Type Boolean = typeof(bool);
  260. public static readonly Type Int16 = typeof(short);
  261. public static readonly Type Int32 = typeof(int);
  262. public static readonly Type Int64 = typeof(long);
  263. public static readonly Type UInt32 = typeof(uint);
  264. public static readonly Type UInt64 = typeof(ulong);
  265. public static readonly Type IntPtr = typeof(IntPtr);
  266. public static readonly Type Double = typeof(double);
  267. public static readonly Type Frame = typeof(Frame);
  268. public static readonly Type Kernel = typeof(Kernel);
  269. public static readonly Type Builtins = typeof(Builtins);
  270. public static readonly Type SubInfo = typeof(SubInfo);
  271. public static readonly Type P6any = typeof(P6any);
  272. public static readonly Type Variable = typeof(Variable);
  273. public static readonly Type P6opaque = typeof(P6opaque);
  274. public static readonly Type DynBlockDelegate = typeof(DynBlockDelegate);
  275. public static readonly Type STable = typeof(STable);
  276. public static readonly Type VarHash = typeof(VarHash);
  277. public static readonly Type VVarList = typeof(VarDeque);
  278. public static readonly Type FVarList = typeof(Variable[]);
  279. public static readonly Type Cursor = typeof(Cursor);
  280. public static readonly Type RxFrame = typeof(RxFrame);
  281. public static readonly Type CC = typeof(CC);
  282. public static readonly Type LAD = typeof(LAD);
  283. public static readonly Type RuntimeUnit = typeof(RuntimeUnit);
  284. public static readonly Type StashCursor = typeof(StashCursor);
  285. public static readonly ConstructorInfo SubInfo_ctor =
  286. SubInfo.GetConstructor(new Type[] {
  287. String, typeof(int[]), typeof(DynBlockDelegate),
  288. SubInfo, LAD, typeof(int[]), typeof(string[]),
  289. Int32, typeof(string[]), typeof(int[]) });
  290. public static readonly ConstructorInfo DynBlockDelegate_ctor =
  291. typeof(DynBlockDelegate).GetConstructor(new Type[] {
  292. typeof(object), typeof(IntPtr) });
  293. public static readonly ConstructorInfo P6opaque_ctor =
  294. typeof(P6opaque).GetConstructor(new Type[] {
  295. STable });
  296. public static readonly ConstructorInfo DMO_ctor =
  297. STable.GetConstructor(new Type[] { String });
  298. public static readonly ConstructorInfo RxFrame_ctor =
  299. RxFrame.GetConstructor(new Type[] { String, Cursor, Boolean });
  300. public static readonly ConstructorInfo SV_ctor =
  301. typeof(RWVariable).GetConstructor(new Type[] {
  302. STable, typeof(ViviHook), P6any });
  303. public static readonly ConstructorInfo SubViviHook_ctor =
  304. typeof(SubViviHook).GetConstructor(new Type[] { P6any });
  305. public static readonly ConstructorInfo Rat_ctor =
  306. typeof(Rat).GetConstructor(new Type[] { typeof(BigInteger), typeof(ulong) });
  307. public static readonly ConstructorInfo BigInteger_ctor =
  308. typeof(BigInteger).GetConstructor(new Type[] { typeof(short), typeof(uint[]) });
  309. public static readonly ConstructorInfo CC_ctor =
  310. CC.GetConstructor(new Type[] { typeof(int[]) });
  311. public static readonly ConstructorInfo SC_ctor =
  312. StashCursor.GetConstructor(new Type[] { typeof(Frame), typeof(int) });
  313. public static readonly MethodInfo P6any_InvokeMethod =
  314. P6any.GetMethod("InvokeMethod");
  315. public static readonly MethodInfo P6any_Invoke =
  316. P6any.GetMethod("Invoke");
  317. public static readonly MethodInfo P6any_SetSlot =
  318. P6any.GetMethod("SetSlot", new Type[] { STable, String, typeof(object) });
  319. public static readonly MethodInfo P6any_GetSlot =
  320. P6any.GetMethod("GetSlot", new Type[] { STable, String });
  321. public static readonly MethodInfo SubInfo_AddHint =
  322. SubInfo.GetMethod("AddHint");
  323. public static readonly MethodInfo Variable_Fetch =
  324. Variable.GetMethod("Fetch");
  325. public static readonly MethodInfo VVarList_Item =
  326. VVarList.GetMethod("get_Item");
  327. public static readonly MethodInfo VarHash_Remove =
  328. VarHash.GetMethod("Remove");
  329. public static readonly MethodInfo VarHash_get_Item =
  330. VarHash.GetMethod("get_Item");
  331. public static readonly MethodInfo VarHash_set_Item =
  332. VarHash.GetMethod("set_Item");
  333. public static readonly MethodInfo Kernel_MakeSub =
  334. typeof(Kernel).GetMethod("MakeSub");
  335. public static readonly MethodInfo Kernel_CheckUnsafe =
  336. typeof(Kernel).GetMethod("CheckUnsafe");
  337. public static readonly MethodInfo Kernel_NewLabelVar =
  338. typeof(Kernel).GetMethod("NewLabelVar");
  339. public static readonly MethodInfo Kernel_MakeDispatcher =
  340. typeof(Kernel).GetMethod("MakeDispatcherF");
  341. public static readonly MethodInfo Kernel_Die =
  342. typeof(Kernel).GetMethod("Die");
  343. public static readonly MethodInfo Kernel_SFH =
  344. typeof(Kernel).GetMethod("SearchForHandler");
  345. public static readonly MethodInfo Kernel_BootModule =
  346. typeof(Kernel).GetMethod("BootModule");
  347. public static readonly MethodInfo Kernel_GetGlobal =
  348. typeof(Kernel).GetMethod("GetGlobal");
  349. public static readonly MethodInfo Kernel_BindGlobal =
  350. typeof(Kernel).GetMethod("BindGlobal");
  351. public static readonly MethodInfo Kernel_NewRWListVar =
  352. typeof(Kernel).GetMethod("NewRWListVar");
  353. public static readonly MethodInfo Kernel_NewRWScalar =
  354. typeof(Kernel).GetMethod("NewRWScalar");
  355. public static readonly MethodInfo Kernel_NewTypedScalar =
  356. typeof(Kernel).GetMethod("NewTypedScalar");
  357. public static readonly MethodInfo Kernel_NewMuAnyScalar =
  358. typeof(Kernel).GetMethod("NewMuAnyScalar");
  359. public static readonly MethodInfo Kernel_Assign =
  360. typeof(Kernel).GetMethod("Assign");
  361. public static readonly MethodInfo Kernel_CreateArray =
  362. typeof(Kernel).GetMethod("CreateArray");
  363. public static readonly MethodInfo Kernel_CreateHash =
  364. typeof(Kernel).GetMethod("CreateHash");
  365. public static readonly MethodInfo Kernel_GetVar =
  366. typeof(Kernel).GetMethod("GetVar");
  367. public static readonly MethodInfo Kernel_Decontainerize =
  368. typeof(Kernel).GetMethod("Decontainerize");
  369. public static readonly MethodInfo Kernel_NewBoundVar =
  370. typeof(Kernel).GetMethod("NewBoundVar");
  371. public static readonly MethodInfo Kernel_IterHasFlat =
  372. typeof(Kernel).GetMethod("IterHasFlat");
  373. public static readonly MethodInfo Kernel_ContextHelper =
  374. typeof(Kernel).GetMethod("ContextHelper");
  375. public static readonly MethodInfo Kernel_StatusHelper =
  376. typeof(Kernel).GetMethod("StatusHelper");
  377. public static readonly MethodInfo Kernel_SetStatus =
  378. typeof(Kernel).GetMethod("SetStatus");
  379. public static readonly MethodInfo Kernel_SortHelper =
  380. typeof(Kernel).GetMethod("SortHelper");
  381. public static readonly MethodInfo Kernel_AddPhaser =
  382. typeof(Kernel).GetMethod("AddPhaser");
  383. public static readonly MethodInfo Kernel_FirePhasers =
  384. typeof(Kernel).GetMethod("FirePhasers");
  385. public static readonly MethodInfo Kernel_BoxAnyMO_Int32 =
  386. typeof(Kernel).GetMethod("BoxAnyMO").MakeGenericMethod(typeof(int));
  387. public static readonly MethodInfo Kernel_BoxAnyMO_Double =
  388. typeof(Kernel).GetMethod("BoxAnyMO").MakeGenericMethod(typeof(double));
  389. public static readonly MethodInfo Kernel_BoxAnyMO_Rat =
  390. typeof(Kernel).GetMethod("BoxAnyMO").MakeGenericMethod(typeof(Rat));
  391. public static readonly MethodInfo Kernel_BoxAnyMO_BigInteger =
  392. typeof(Kernel).GetMethod("BoxAnyMO").MakeGenericMethod(typeof(BigInteger));
  393. public static readonly MethodInfo Builtins_Make =
  394. typeof(Builtins).GetMethod("Make");
  395. public static readonly MethodInfo Builtins_MEMap =
  396. typeof(Builtins).GetMethod("MEMap");
  397. public static readonly MethodInfo Builtins_MEGrep =
  398. typeof(Builtins).GetMethod("MEGrep");
  399. public static readonly MethodInfo DMO_AddMethod =
  400. typeof(STable).GetMethod("AddMethod");
  401. public static readonly MethodInfo DMO_AddAttribute =
  402. typeof(STable).GetMethod("AddAttribute");
  403. public static readonly MethodInfo DMO_Invalidate =
  404. typeof(STable).GetMethod("Invalidate");
  405. public static readonly MethodInfo DMO_FillParametricRole =
  406. typeof(STable).GetMethod("FillParametricRole");
  407. public static readonly MethodInfo DMO_FillRole =
  408. typeof(STable).GetMethod("FillRole");
  409. public static readonly MethodInfo RxFrame_PushBacktrack =
  410. typeof(RxFrame).GetMethod("PushBacktrack");
  411. public static readonly MethodInfo RxFrame_PushCapture =
  412. typeof(RxFrame).GetMethod("PushCapture");
  413. public static readonly MethodInfo Console_WriteLine =
  414. typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
  415. public static readonly MethodInfo Console_Write =
  416. typeof(Console).GetMethod("Write", new Type[] { typeof(string) });
  417. public static readonly MethodInfo Environment_Exit =
  418. typeof(Environment).GetMethod("Exit");
  419. public static readonly MethodInfo StringBuilder_Append_String =
  420. typeof(StringBuilder).GetMethod("Append", new Type[] { String });
  421. public static readonly MethodInfo TW_WriteLine =
  422. typeof(TextWriter).GetMethod("WriteLine", new Type[] { String });
  423. public static readonly MethodInfo Console_get_Error =
  424. typeof(Console).GetMethod("get_Error");
  425. public static readonly MethodInfo Object_ToString =
  426. typeof(object).GetMethod("ToString", new Type[0]);
  427. public static readonly MethodInfo RU_LoadStrArray =
  428. RuntimeUnit.GetMethod("LoadStrArray");
  429. public static readonly MethodInfo RU_LoadPackage =
  430. RuntimeUnit.GetMethod("LoadPackage");
  431. public static readonly MethodInfo RU_LoadClassMembers =
  432. RuntimeUnit.GetMethod("LoadClassMembers");
  433. public static readonly MethodInfo RU_LoadSubInfo =
  434. RuntimeUnit.GetMethod("LoadSubInfo");
  435. public static readonly MethodInfo RU_LoadSignature =
  436. RuntimeUnit.GetMethod("LoadSignature");
  437. public static readonly MethodInfo RU_LoadLAD =
  438. RuntimeUnit.GetMethod("LoadLAD");
  439. public static readonly MethodInfo RU_LoadLADArr =
  440. RuntimeUnit.GetMethod("LoadLADArr");
  441. public static readonly MethodInfo Frame_Return =
  442. Frame.GetMethod("Return");
  443. public static readonly MethodInfo Frame_Binder =
  444. Frame.GetMethod("Binder");
  445. public static readonly FieldInfo P6any_mo =
  446. P6any.GetField("mo");
  447. public static readonly FieldInfo StashEnt_v =
  448. typeof(StashEnt).GetField("v");
  449. public static readonly FieldInfo SubInfo_protosub =
  450. SubInfo.GetField("protosub");
  451. public static readonly FieldInfo SubInfo_protopad =
  452. SubInfo.GetField("protopad");
  453. public static readonly FieldInfo SubInfo_mo =
  454. SubInfo.GetField("mo");
  455. public static readonly FieldInfo P6opaque_slots =
  456. P6opaque.GetField("slots");
  457. public static readonly FieldInfo DMO_typeObj =
  458. STable.GetField("typeObj");
  459. public static readonly FieldInfo DMO_initObj =
  460. STable.GetField("initObj");
  461. public static readonly FieldInfo DMO_how =
  462. STable.GetField("how");
  463. public static readonly FieldInfo Frame_rx =
  464. typeof(Frame).GetField("rx");
  465. public static readonly FieldInfo Frame_ip =
  466. typeof(Frame).GetField("ip");
  467. public static readonly FieldInfo Frame_caller =
  468. typeof(Frame).GetField("caller");
  469. public static readonly FieldInfo Frame_outer =
  470. typeof(Frame).GetField("outer");
  471. public static readonly FieldInfo Frame_resultSlot =
  472. typeof(Frame).GetField("resultSlot");
  473. public static readonly FieldInfo Frame_lexn =
  474. typeof(Frame).GetField("lexn");
  475. [Immutable]
  476. public static readonly FieldInfo[] Frame_lexi32 = new FieldInfo[] {
  477. typeof(Frame).GetField("lexi0"),
  478. typeof(Frame).GetField("lexi1")
  479. };
  480. [Immutable]
  481. public static readonly FieldInfo[] Frame_lexobj = new FieldInfo[] {
  482. typeof(Frame).GetField("lex0"),
  483. typeof(Frame).GetField("lex1"),
  484. typeof(Frame).GetField("lex2"),
  485. typeof(Frame).GetField("lex3"),
  486. typeof(Frame).GetField("lex4"),
  487. typeof(Frame).GetField("lex5"),
  488. typeof(Frame).GetField("lex6"),
  489. typeof(Frame).GetField("lex7"),
  490. typeof(Frame).GetField("lex8"),
  491. typeof(Frame).GetField("lex9")
  492. };
  493. public static readonly FieldInfo RU_xref = RuntimeUnit.GetField("xref");
  494. public const int NumInt32 = 2;
  495. public const int NumInline = 10;
  496. // other random stuff
  497. public static readonly ClrOp[] EmptyClrOp = new ClrOp[0];
  498. }
  499. // This are expressional CLR operators. This is lower level than the
  500. // CPS stuff; if HasCases is true, Returns must be void. Thus,
  501. // there is no need to handle argument spills.
  502. abstract class ClrOp {
  503. public bool HasCases;
  504. public bool Constant; // if this returns a value, can it be reordered?
  505. public Type Returns;
  506. public abstract void CodeGen(CgContext cx);
  507. public virtual void ListCases(CgContext cx) { }
  508. public virtual ClrOp Sink() {
  509. throw (Returns == Tokens.Void)
  510. ? (Exception)new ArgumentException()
  511. : new NotImplementedException();
  512. }
  513. protected static void TypeCheck(Type sub, Type super) {
  514. if (!super.IsAssignableFrom(sub))
  515. throw new Exception(sub + " not subtype of " + super);
  516. }
  517. protected static void TypeCheck(Type sub, Type super, object c) {
  518. if (!super.IsAssignableFrom(sub))
  519. throw new Exception(sub + " not subtype of " + super + ": " + c);
  520. }
  521. }
  522. // NOT FOR GENERAL USE: only in implementing Sink for Clr*** with
  523. // irreducable operations
  524. class ClrSink : ClrOp {
  525. public readonly ClrOp zyg;
  526. public override void ListCases(CgContext cx) {
  527. zyg.ListCases(cx);
  528. }
  529. public override void CodeGen(CgContext cx) {
  530. zyg.CodeGen(cx);
  531. cx.il.Emit(OpCodes.Pop);
  532. }
  533. public ClrSink(ClrOp zyg) {
  534. if (zyg.Returns == Tokens.Void)
  535. throw new ArgumentException();
  536. this.zyg = zyg;
  537. Returns = Tokens.Void;
  538. }
  539. }
  540. class ClrMethodCall : ClrOp {
  541. public readonly MethodInfo Method;
  542. public readonly ClrOp[] Zyg;
  543. public override ClrOp Sink() {
  544. return new ClrSink(this);
  545. }
  546. public override void CodeGen(CgContext cx) {
  547. if (HasCases) {
  548. cx.il.Emit(OpCodes.Ldarg_1);
  549. cx.EmitInt(cx.next_case);
  550. cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
  551. }
  552. int scratch_ix = -1;
  553. LocalBuilder scratch_lb = null;
  554. int i = 0;
  555. if (!Method.IsStatic) {
  556. ClrOp o = Zyg[i++];
  557. o.CodeGen(cx);
  558. if (o.Returns.IsValueType) {
  559. if (Method.DeclaringType == o.Returns) {
  560. scratch_ix = 0;
  561. while (scratch_ix < cx.scratches.Count &&
  562. cx.scratches[scratch_ix].LocalType != o.Returns)
  563. scratch_ix++;
  564. if (scratch_ix == cx.scratches.Count)
  565. cx.scratches.Add(cx.il.DeclareLocal(o.Returns));
  566. scratch_lb = cx.scratches[scratch_ix];
  567. cx.scratches[scratch_ix] = null;
  568. cx.il.Emit(OpCodes.Stloc, scratch_lb);
  569. cx.il.Emit(OpCodes.Ldloca, scratch_lb);
  570. }
  571. else
  572. cx.il.Emit(OpCodes.Box, o.Returns);
  573. }
  574. }
  575. // this needs to come AFTER the invocant
  576. if (HasCases)
  577. cx.il.Emit(OpCodes.Ldarg_1);
  578. for (; i < Zyg.Length; i++) {
  579. Zyg[i].CodeGen(cx);
  580. }
  581. cx.il.Emit(((Method.IsStatic || !Method.IsVirtual) ?
  582. OpCodes.Call : OpCodes.Callvirt), Method);
  583. if (HasCases) {
  584. cx.il.Emit(OpCodes.Ret);
  585. cx.il.MarkLabel(cx.cases[cx.next_case++]);
  586. cx.save_line();
  587. }
  588. if (scratch_ix >= 0)
  589. cx.scratches[scratch_ix] = scratch_lb;
  590. }
  591. public override void ListCases(CgContext cx) {
  592. // it is not legal for any of out children to have cases to list
  593. if (HasCases)
  594. cx.num_cases++;
  595. }
  596. public ClrMethodCall(bool cps, MethodInfo mi, params ClrOp[] zyg) {
  597. Method = mi;
  598. Zyg = zyg;
  599. Returns = cps ? Tokens.Void : mi.ReturnType;
  600. HasCases = cps;
  601. List<Type> ts = new List<Type>();
  602. if (!mi.IsStatic)
  603. ts.Add(mi.DeclaringType);
  604. if (cps && mi.GetParameters()[0].ParameterType != Tokens.Frame)
  605. throw new ArgumentException("CPS method not taking a frame");
  606. if (cps && mi.ReturnType != Tokens.Frame)
  607. throw new ArgumentException("CPS method not returning a frame");
  608. bool skip = cps;
  609. foreach (ParameterInfo pi in mi.GetParameters()) {
  610. if (skip) { skip = false; continue; }
  611. ts.Add(pi.ParameterType);
  612. }
  613. if (zyg.Length != ts.Count)
  614. throw new Exception("argument list length mismatch for " + mi +
  615. " got " + zyg.Length + " need " + ts.Count);
  616. for (int i = 0; i < ts.Count; i++) {
  617. TypeCheck(zyg[i].Returns, ts[i], mi);
  618. }
  619. }
  620. }
  621. class ClrConstructorCall : ClrOp {
  622. public readonly ConstructorInfo Method;
  623. public readonly ClrOp[] Zyg;
  624. public override ClrOp Sink() {
  625. return new ClrSink(this);
  626. }
  627. public override void CodeGen(CgContext cx) {
  628. foreach (ClrOp o in Zyg) {
  629. o.CodeGen(cx);
  630. }
  631. cx.il.Emit(OpCodes.Newobj, Method);
  632. }
  633. public ClrConstructorCall(ConstructorInfo mi, ClrOp[] zyg) {
  634. Method = mi;
  635. Zyg = zyg;
  636. Returns = mi.DeclaringType;
  637. List<Type> ts = new List<Type>();
  638. foreach (ParameterInfo pi in mi.GetParameters()) {
  639. ts.Add(pi.ParameterType);
  640. }
  641. if (zyg.Length != ts.Count)
  642. throw new Exception("argument list length mismatch");
  643. for (int i = 0; i < ts.Count; i++) {
  644. TypeCheck(zyg[i].Returns, ts[i], mi);
  645. }
  646. }
  647. }
  648. class ClrContexty : ClrOp {
  649. public readonly ClrOp[] zyg;
  650. public readonly MethodInfo inv;
  651. public readonly FieldInfo thing;
  652. // This could be avoided in some cases, but probably +$customobj;
  653. // shouldn't be optimized out
  654. public override ClrOp Sink() {
  655. return new ClrSink(this);
  656. }
  657. public override void CodeGen(CgContext cx) {
  658. zyg[0].CodeGen(cx);
  659. cx.make_ospill();
  660. cx.il.Emit(OpCodes.Dup);
  661. cx.il.Emit(OpCodes.Stloc, cx.ospill);
  662. cx.il.Emit(OpCodes.Callvirt, Tokens.Variable_Fetch);
  663. cx.il.Emit(OpCodes.Ldfld, Tokens.P6any_mo);
  664. cx.il.Emit(OpCodes.Ldfld, thing);
  665. cx.il.Emit(OpCodes.Ldloc, cx.ospill);
  666. for (int i = 1; i < zyg.Length; i++)
  667. zyg[i].CodeGen(cx);
  668. cx.il.Emit(OpCodes.Callvirt, inv);
  669. }
  670. public ClrContexty(FieldInfo thing, MethodInfo inv, ClrOp[] zyg) {
  671. this.thing = thing;
  672. this.inv = inv;
  673. this.zyg = zyg;
  674. Returns = inv.ReturnType;
  675. }
  676. }
  677. class ClrOperator : ClrOp {
  678. public readonly OpCode op;
  679. public readonly ClrOp[] zyg;
  680. public override ClrOp Sink() {
  681. ClrOp[] szyg = new ClrOp[zyg.Length];
  682. for (int i = 0; i < szyg.Length; i++)
  683. szyg[i] = zyg[i].Sink();
  684. return new ClrSeq(szyg);
  685. }
  686. public override void CodeGen(CgContext cx) {
  687. foreach (ClrOp c in zyg)
  688. c.CodeGen(cx);
  689. cx.il.Emit(op);
  690. }
  691. public ClrOperator(Type ret, OpCode op, ClrOp[] zyg) {
  692. Returns = ret;
  693. this.op = op;
  694. this.zyg = zyg;
  695. }
  696. }
  697. class ClrCompare : ClrOp {
  698. public readonly string op;
  699. public readonly ClrOp[] zyg;
  700. public override ClrOp Sink() {
  701. ClrOp[] szyg = new ClrOp[zyg.Length];
  702. for (int i = 0; i < szyg.Length; i++)
  703. szyg[i] = zyg[i].Sink();
  704. return new ClrSeq(szyg);
  705. }
  706. public override void CodeGen(CgContext cx) {
  707. foreach (ClrOp c in zyg)
  708. c.CodeGen(cx);
  709. bool flt = zyg[0].Returns == Tokens.Double;
  710. OpCode ilop;
  711. bool not = false;
  712. if (op == "<") { ilop = OpCodes.Clt; }
  713. else if (op == ">") { ilop = OpCodes.Cgt; }
  714. else if (op == ">=") {
  715. ilop = flt ? OpCodes.Clt_Un : OpCodes.Clt;
  716. not = true;
  717. }
  718. else if (op == "<=") {
  719. ilop = flt ? OpCodes.Cgt_Un : OpCodes.Cgt;
  720. not = true;
  721. }
  722. else if (op == "==") { ilop = OpCodes.Ceq; }
  723. else if (op == "!=") { ilop = OpCodes.Ceq; not = true; }
  724. else throw new ArgumentException(op + " as polyop");
  725. cx.il.Emit(ilop);
  726. if (not) {
  727. cx.il.Emit(OpCodes.Ldc_I4_0);
  728. cx.il.Emit(OpCodes.Ceq);
  729. }
  730. }
  731. public ClrCompare(string op, ClrOp[] zyg) {
  732. Returns = Tokens.Boolean;
  733. this.op = op;
  734. this.zyg = zyg;
  735. }
  736. }
  737. class ClrGetField : ClrOp {
  738. public readonly FieldInfo f;
  739. public readonly ClrOp zyg;
  740. // Not strictly right, but Perl 6 code never sees CLR nulls, and
  741. // this is a major win for some cases
  742. public override ClrOp Sink() {
  743. return zyg.Sink();
  744. }
  745. public override void CodeGen(CgContext cx) {
  746. zyg.CodeGen(cx);
  747. cx.il.Emit(OpCodes.Ldfld, f);
  748. }
  749. public ClrGetField(FieldInfo f, ClrOp zyg) {
  750. TypeCheck(zyg.Returns, f.DeclaringType);
  751. Returns = f.FieldType;
  752. this.f = f;
  753. this.zyg = zyg;
  754. }
  755. }
  756. class ClrSetField : ClrOp {
  757. public readonly FieldInfo f;
  758. public readonly ClrOp zyg1;
  759. public readonly ClrOp zyg2;
  760. public override void CodeGen(CgContext cx) {
  761. zyg1.CodeGen(cx);
  762. zyg2.CodeGen(cx);
  763. cx.il.Emit(OpCodes.Stfld, f);
  764. }
  765. public ClrSetField(FieldInfo f, ClrOp zyg1, ClrOp zyg2) {
  766. TypeCheck(zyg1.Returns, f.DeclaringType);
  767. TypeCheck(zyg2.Returns, f.FieldType);
  768. Returns = Tokens.Void;
  769. this.f = f;
  770. this.zyg1 = zyg1;
  771. this.zyg2 = zyg2;
  772. }
  773. }
  774. class ClrGetConst : ClrOp {
  775. public readonly FieldInfo f;
  776. public override ClrOp Sink() { return ClrNoop.Instance; }
  777. public override void CodeGen(CgContext cx) {
  778. cx.il.Emit(OpCodes.Ldarg_0);
  779. cx.il.Emit(OpCodes.Ldfld, f);
  780. }
  781. public ClrGetConst(FieldInfo f) {
  782. Returns = f.FieldType;
  783. this.f = f;
  784. }
  785. }
  786. class ClrPadGet : ClrOp {
  787. public readonly int up;
  788. public readonly int index;
  789. public override ClrOp Sink() { return ClrNoop.Instance; }
  790. public override void CodeGen(CgContext cx) {
  791. cx.il.Emit(OpCodes.Ldarg_1);
  792. for (int i = 0; i < up; i++)
  793. cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_outer);
  794. cx.EmitGetlex(index + Tokens.NumInt32, Tokens.Variable);
  795. }
  796. public ClrPadGet(int up, int index) {
  797. Returns = Tokens.Variable;
  798. this.up = up;
  799. this.index = index;
  800. }
  801. }
  802. class ClrPadSet : ClrOp {
  803. public readonly int up;
  804. public readonly int index;
  805. public readonly ClrOp zyg;
  806. public override void CodeGen(CgContext cx) {
  807. cx.il.Emit(OpCodes.Ldarg_1);
  808. for (int i = 0; i < up; i++)
  809. cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_outer);
  810. cx.EmitPreSetlex(index + Tokens.NumInt32);
  811. zyg.CodeGen(cx);
  812. cx.EmitSetlex(index + Tokens.NumInt32, Tokens.Variable);
  813. }
  814. public ClrPadSet(int up, int index, ClrOp zyg) {
  815. Returns = Tokens.Void;
  816. this.zyg = zyg;
  817. this.up = up;
  818. this.index = index;
  819. }
  820. }
  821. class ClrProtoSet : ClrOp {
  822. public readonly int ix;
  823. public readonly ClrOp zyg1;
  824. public readonly ClrOp zyg2;
  825. public override void CodeGen(CgContext cx) {
  826. zyg1.CodeGen(cx);
  827. cx.EmitPreSetlex(ix + Tokens.NumInt32);
  828. zyg2.CodeGen(cx);
  829. cx.EmitSetlex(ix + Tokens.NumInt32, Tokens.Variable);
  830. }
  831. public ClrProtoSet(int ix, ClrOp zyg1, ClrOp zyg2) {
  832. TypeCheck(zyg1.Returns, Tokens.Frame);
  833. Returns = Tokens.Void;
  834. this.ix = ix;
  835. this.zyg1 = zyg1;
  836. this.zyg2 = zyg2;
  837. }
  838. }
  839. class ClrProtoGet : ClrOp {
  840. public readonly int ix;
  841. public readonly ClrOp zyg;
  842. public override ClrOp Sink() { return ClrNoop.Instance; }
  843. public override void CodeGen(CgContext cx) {
  844. zyg.CodeGen(cx);
  845. cx.EmitGetlex(ix + Tokens.NumInt32, Tokens.Variable);
  846. }
  847. public ClrProtoGet(int ix, ClrOp zyg) {
  848. TypeCheck(zyg.Returns, Tokens.Frame);
  849. Returns = Tokens.Variable;
  850. this.ix = ix;
  851. this.zyg = zyg;
  852. }
  853. }
  854. class ClrMarkConstant : ClrOp {
  855. readonly ClrOp real;
  856. public ClrMarkConstant(ClrOp real) {
  857. this.real = real;
  858. Returns = real.Returns;
  859. HasCases = false;
  860. Constant = true;
  861. }
  862. // no side effects, huh?
  863. public override ClrOp Sink() {
  864. return ClrNoop.Instance;
  865. }
  866. public override void CodeGen(CgContext cx) {
  867. real.CodeGen(cx);
  868. }
  869. }
  870. class ClrNoop : ClrOp {
  871. private ClrNoop() {
  872. Returns = Tokens.Void;
  873. HasCases = false;
  874. }
  875. public override void CodeGen(CgContext cx) { }
  876. [Immutable] public static ClrNoop Instance = new ClrNoop();
  877. }
  878. class ClrEhSpan : ClrOp {
  879. public readonly int kls;
  880. public readonly string tag;
  881. public readonly string ls;
  882. public readonly string le;
  883. public readonly int ng;
  884. public readonly string lg;
  885. public ClrEhSpan(int kls, string tag, string ls, string le, string lg) {
  886. Returns = Tokens.Void;
  887. HasCases = false;
  888. this.kls = kls; this.tag = tag; this.ls = ls; this.le = le;
  889. this.lg = lg;
  890. }
  891. public ClrEhSpan(int kls, string tag, string ls, string le, int ng) {
  892. Returns = Tokens.Void;
  893. HasCases = false;
  894. this.kls = kls; this.tag = tag; this.ls = ls; this.le = le;
  895. this.ng = ng;
  896. }
  897. public override void CodeGen(CgContext cx) {
  898. int lidn = -1;
  899. if (tag != "") {
  900. for (lidn = 0; lidn < cx.ehlabelBuffer.Count &&
  901. cx.ehlabelBuffer[lidn] != tag; lidn++);
  902. if (lidn == cx.ehlabelBuffer.Count)
  903. cx.ehlabelBuffer.Add(tag);
  904. }
  905. cx.ehspanBuffer.Add(cx.named_cases[ls]);
  906. cx.ehspanBuffer.Add(cx.named_cases[le]);
  907. cx.ehspanBuffer.Add(kls);
  908. if (lg == null) {
  909. cx.ehspanBuffer.Add(ng);
  910. } else if (kls == SubInfo.ON_VARLOOKUP) {
  911. int ix = cx.let_names.Length - 1;
  912. while (ix >= 0 && cx.let_names[ix] != lg)
  913. ix--;
  914. if (ix < Tokens.NumInt32)
  915. throw new Exception("variable in index area??");
  916. cx.ehspanBuffer.Add(ix - Tokens.NumInt32);
  917. } else {
  918. cx.ehspanBuffer.Add(cx.named_cases[lg]);
  919. }
  920. cx.ehspanBuffer.Add(lidn);
  921. }
  922. }
  923. class ClrPushLine : ClrOp {
  924. public readonly int line;
  925. public ClrPushLine(int line) {
  926. this.line = line;
  927. Returns = Tokens.Void;
  928. HasCases = false;
  929. }
  930. public override void CodeGen(CgContext cx) {
  931. cx.lineStack.Add(line);
  932. }
  933. }
  934. class ClrPopLine : ClrOp {
  935. public ClrPopLine() {
  936. Returns = Tokens.Void;
  937. HasCases = false;
  938. }
  939. public override void CodeGen(CgContext cx) {
  940. cx.lineStack.RemoveAt(cx.lineStack.Count - 1);
  941. }
  942. }
  943. class ClrSync : ClrOp {
  944. private ClrSync() {
  945. Returns = Tokens.Void;
  946. HasCases = true;
  947. }
  948. public override void ListCases(CgContext cx) { cx.num_cases++; }
  949. public override void CodeGen(CgContext cx) {
  950. cx.il.Emit(OpCodes.Ldarg_1);
  951. cx.EmitInt(cx.next_case);
  952. cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
  953. cx.il.MarkLabel(cx.cases[cx.next_case++]);
  954. cx.save_line();
  955. }
  956. [Immutable] public static ClrSync Instance = new ClrSync();
  957. }
  958. // only used in ClrOperator.Sink, and assumes it in the HasCases=false
  959. class ClrSeq : ClrOp {
  960. readonly ClrOp[] zyg;
  961. public ClrSeq(ClrOp[] zyg) {
  962. Returns = Tokens.Void;
  963. HasCases = false;
  964. this.zyg = zyg;
  965. }
  966. public override void CodeGen(CgContext cx) {
  967. foreach(ClrOp z in zyg)
  968. z.CodeGen(cx);
  969. }
  970. }
  971. class ClrSubyCall : ClrOp {
  972. public readonly bool ismethod;
  973. public readonly string sig;
  974. public readonly ClrOp[] zyg;
  975. // generates the argument list, from the elements of zyg
  976. void GenArgList(int min, CgContext cx) {
  977. bool general = false;
  978. for (int i = min; i < zyg.Length; i++)
  979. if (sig[i - min] != '\0')
  980. general = true;
  981. if (!general) {
  982. cx.EmitInt(zyg.Length - min + (ismethod ? 1 : 0));
  983. cx.il.Emit(OpCodes.Newarr, Tokens.Variable);
  984. if (ismethod) {
  985. cx.il.Emit(OpCodes.Dup);
  986. cx.EmitInt(0);
  987. cx.il.Emit(OpCodes.Ldloc, cx.sspill);
  988. cx.il.Emit(OpCodes.Stelem_Ref);
  989. }
  990. for (int i = min; i < zyg.Length; i++) {
  991. cx.il.Emit(OpCodes.Dup);
  992. cx.EmitInt(i - min + (ismethod ? 1 : 0));
  993. zyg[i].CodeGen(cx);
  994. cx.il.Emit(OpCodes.Stelem_Ref);
  995. }
  996. cx.il.Emit(OpCodes.Ldnull);
  997. } else {
  998. if (cx.pspill == null) cx.pspill = cx.il.DeclareLocal(typeof(List<Variable>));
  999. if (cx.nspill == null) cx.nspill = cx.il.DeclareLocal(Tokens.VarHash);
  1000. cx.il.Emit(OpCodes.Newobj, typeof(List<Variable>).GetConstructor(new Type[0]));
  1001. cx.il.Emit(OpCodes.Stloc, cx.pspill);
  1002. cx.il.Emit(OpCodes.Newobj, Tokens.VarHash.GetConstructor(new Type[0]));
  1003. cx.il.Emit(OpCodes.Stloc, cx.nspill);
  1004. if (ismethod) {
  1005. cx.il.Emit(OpCodes.Ldloc, cx.pspill);
  1006. cx.il.Emit(OpCodes.Ldloc, cx.sspill);
  1007. cx.il.Emit(OpCodes.Call, typeof(List<Variable>).GetMethod("Add"));
  1008. }
  1009. int csr = 0;
  1010. int ix = min;
  1011. while (csr != sig.Length) {
  1012. int len = (int)sig[csr];
  1013. string tok = sig.Substring(csr+1, len);
  1014. csr += (len + 1);
  1015. if (tok == "") {
  1016. cx.il.Emit(OpCodes.Ldloc, cx.pspill);
  1017. zyg[ix++].CodeGen(cx);
  1018. cx.il.Emit(OpCodes.Call, typeof(List<Variable>).GetMethod("Add"));
  1019. } else if (tok == "flatcap") {
  1020. cx.il.Emit(OpCodes.Ldloc, cx.pspill);
  1021. cx.il.Emit(OpCodes.Ldloc, cx.nspill);
  1022. zyg[ix++].CodeGen(cx);
  1023. cx.il.Emit(OpCodes.Call, Tokens.Kernel.GetMethod("AddCap"));
  1024. } else if (tok[0] == ':') {
  1025. cx.il.Emit(OpCodes.Ldloc, cx.nspill);
  1026. cx.il.Emit(OpCodes.Ldstr, tok.Substring(1));
  1027. zyg[ix++].CodeGen(cx);
  1028. cx.il.Emit(OpCodes.Call, Tokens.VarHash_set_Item);
  1029. } else {
  1030. throw new ArgumentException(tok);
  1031. }
  1032. }
  1033. cx.il.Emit(OpCodes.Ldloc, cx.pspill);
  1034. cx.il.Emit(OpCodes.Call, typeof(List<Variable>).GetMethod("ToArray"));
  1035. cx.il.Emit(OpCodes.Ldloc, cx.nspill);
  1036. }
  1037. }
  1038. public override void CodeGen(CgContext cx) {
  1039. cx.il.Emit(OpCodes.Ldarg_1);
  1040. cx.EmitInt(cx.next_case);
  1041. cx.il.Emit(OpCodes.Stfld, Tokens.Frame_ip);
  1042. zyg[ismethod ? 1 : 0].CodeGen(cx);
  1043. if (ismethod) {
  1044. cx.make_sspill();
  1045. cx.il.Emit(OpCodes.Dup);
  1046. cx.il.Emit(OpCodes.Stloc, cx.sspill);
  1047. cx.il.Emit(OpCodes.Callvirt, Tokens.Variable_Fetch);
  1048. }
  1049. cx.il.Emit(OpCodes.Ldarg_1);
  1050. if (ismethod)
  1051. zyg[0].CodeGen(cx);
  1052. GenArgList(ismethod ? 2 : 1, cx);
  1053. cx.il.Emit(OpCodes.Callvirt, ismethod ?
  1054. Tokens.P6any_InvokeMethod : Tokens.P6any_Invoke);
  1055. cx.il.Emit(OpCodes.Ret);
  1056. cx.il.MarkLabel(cx.cases[cx.next_case++]);
  1057. cx.save_line();
  1058. }
  1059. public override void ListCases(CgContext cx) {
  1060. cx.num_cases++;
  1061. }
  1062. public ClrSubyCall(bool ismethod, string sig, ClrOp[] zyg) {
  1063. int i = 0;
  1064. if (ismethod) TypeCheck(zyg[i++].Returns, Tokens.String, "methodname");
  1065. TypeCheck(zyg[i++].Returns, ismethod ? Tokens.Variable : Tokens.P6any, "sub");
  1066. int j = 0;
  1067. while (j < sig.Length) {
  1068. string s = sig.Substring(j+1, sig[j]);
  1069. j += (1 + s.Length);
  1070. TypeCheck(zyg[i++].Returns, (s == "flatcap") ? Tokens.P6any : Tokens.Variable, j);
  1071. }
  1072. this.ismethod = ismethod;
  1073. this.sig = sig;
  1074. this.zyg = zyg;
  1075. this.Returns = Tokens.Void;
  1076. this.HasCases = true;
  1077. }
  1078. }
  1079. class ClrPushLet : ClrOp {
  1080. string Name;
  1081. // Initial must not have a net let-stack effect (how to enforce?)
  1082. ClrOp Initial;
  1083. public ClrPushLet(string name, ClrOp initial) {
  1084. Initial = initial;
  1085. Name = name;
  1086. Returns = Tokens.Void;
  1087. }
  1088. public override void CodeGen(CgContext cx) {
  1089. // indexes 0-1 can only be used by ints
  1090. int ix = (Initial.Returns == typeof(int)) ? 0 : Tokens.NumInt32;
  1091. while (ix < cx.let_types.Length && cx.let_types[ix] != null)
  1092. ix++;
  1093. cx.il.Emit(OpCodes.Ldarg_1);
  1094. cx.EmitPreSetlex(ix);
  1095. // Initial must not have a net effect on cx.let_types
  1096. Initial.CodeGen(cx);
  1097. // let_types.Length tracks the highest index used.
  1098. if (ix >= cx.let_types.Length) {
  1099. Array.Resize(ref cx.let_types, ix+1);
  1100. Array.Resize(ref cx.let_names, ix+1);
  1101. }
  1102. cx.let_types[ix] = Initial.Returns;
  1103. cx.let_names[ix] = Name;
  1104. cx.EmitSetlex(ix, Initial.Returns);
  1105. }
  1106. }
  1107. class ClrPokeLet : ClrOp {
  1108. string Name;
  1109. ClrOp Value;
  1110. public ClrPokeLet(string name, ClrOp value) {
  1111. Value = value;
  1112. Name = name;
  1113. Returns = Tokens.Void;
  1114. }
  1115. public override void CodeGen(CgContext cx) {
  1116. int ix = cx.let_names.Length - 1;
  1117. while (ix >= 0 && cx.let_names[ix] != Name)
  1118. ix--;
  1119. if (ix == cx.let_names.Length)
  1120. throw new Exception("let " + Name + " not found");
  1121. cx.il.Emit(OpCodes.Ldarg_1);
  1122. cx.EmitPreSetlex(ix);
  1123. // Initial must not have a net effect on cx.let_types
  1124. Value.CodeGen(cx);
  1125. cx.EmitSetlex(ix, Value.Returns);
  1126. }
  1127. }
  1128. class ClrPeekLet : ClrOp {
  1129. string Name;
  1130. public override ClrOp Sink() { return ClrNoop.Instance; }
  1131. public ClrPeekLet(string name, Type letType) {
  1132. Name = name;
  1133. Returns = letType;
  1134. }
  1135. public override void CodeGen(CgContext cx) {
  1136. int ix = cx.let_names.Length - 1;
  1137. while (ix >= 0 && cx.let_names[ix] != Name)
  1138. ix--;
  1139. if (ix == cx.let_names.Length)
  1140. throw new Exception("let " + Name + " not found");
  1141. cx.il.Emit(OpCodes.Ldarg_1);
  1142. cx.EmitGetlex(ix, Returns);
  1143. }
  1144. }
  1145. class ClrSetResult : ClrOp {
  1146. ClrOp zyg;
  1147. public ClrSetResult(ClrOp zyg) {
  1148. Returns = Tokens.Void;
  1149. this.zyg = zyg;
  1150. }
  1151. public override void CodeGen(CgContext cx) {
  1152. cx.il.Emit(OpCodes.Ldarg_1);
  1153. zyg.CodeGen(cx);
  1154. if (zyg.Returns.IsValueType)
  1155. cx.il.Emit(OpCodes.Box, zyg.Returns);
  1156. cx.il.Emit(OpCodes.Stfld, Tokens.Frame_resultSlot);
  1157. }
  1158. }
  1159. class ClrResult : ClrOp {
  1160. public ClrRe

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