PageRenderTime 93ms CodeModel.GetById 19ms 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
  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 ClrResult(Type letType) {
  1161. Returns = letType;
  1162. }
  1163. public override ClrOp Sink() { return ClrNoop.Instance; }
  1164. public override void CodeGen(CgContext cx) {
  1165. if (Returns == Tokens.Void)
  1166. return;
  1167. cx.il.Emit(OpCodes.Ldarg_1);
  1168. cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_resultSlot);
  1169. if (Config.CGVerifiable || Returns.IsValueType)
  1170. cx.il.Emit(OpCodes.Unbox_Any, Returns);
  1171. }
  1172. }
  1173. class ClrDropLet : ClrOp {
  1174. public string Name;
  1175. public ClrOp Inner;
  1176. public override ClrOp Sink() {
  1177. return new ClrDropLet(Name, Inner.Sink());
  1178. }
  1179. public ClrDropLet(string name, ClrOp inner) {
  1180. Name = name;
  1181. Inner = inner;
  1182. Returns = inner.Returns;
  1183. HasCases = inner.HasCases;
  1184. }
  1185. public override void ListCases(CgContext cx) {
  1186. Inner.ListCases(cx);
  1187. }
  1188. public override void CodeGen(CgContext cx) {
  1189. Inner.CodeGen(cx);
  1190. int ix = cx.let_names.Length - 1;
  1191. while (ix >= 0 && cx.let_names[ix] != Name)
  1192. ix--;
  1193. if (ix == cx.let_names.Length)
  1194. throw new Exception("let " + Name + " not found");
  1195. cx.let_names[ix] = null;
  1196. cx.let_types[ix] = null;
  1197. // XXX We probably should null reference-valued lets here
  1198. }
  1199. }
  1200. // TODO Investigate DLR-style labels with arguments
  1201. class ClrLabel : ClrOp {
  1202. string name;
  1203. bool case_too;
  1204. public ClrLabel(string name, bool case_too) {
  1205. this.name = name;
  1206. this.case_too = case_too;
  1207. Returns = Tokens.Void;
  1208. HasCases = true;
  1209. }
  1210. public override void ListCases(CgContext cx) {
  1211. cx.named_labels[name] = cx.il.DefineLabel();
  1212. if (case_too)
  1213. cx.named_cases[name] = cx.num_cases++;
  1214. }
  1215. public override void CodeGen(CgContext cx) {
  1216. cx.il.MarkLabel(cx.named_labels[name]);
  1217. if (case_too) {
  1218. cx.il.MarkLabel(cx.cases[cx.named_cases[name]]);
  1219. cx.next_case++;
  1220. cx.save_line();
  1221. }
  1222. }
  1223. }
  1224. class ClrGoto : ClrOp {
  1225. string name;
  1226. bool iffalse;
  1227. ClrOp inner;
  1228. public ClrGoto(string name, bool iffalse, ClrOp inner) {
  1229. this.name = name;
  1230. this.iffalse = iffalse;
  1231. this.inner = inner;
  1232. Returns = Tokens.Void;
  1233. }
  1234. public override void CodeGen(CgContext cx) {
  1235. // TODO: peephole optimize ceq/brtrue and similar forms
  1236. Label l = cx.named_labels[name];
  1237. if (inner != null) {
  1238. inner.CodeGen(cx);
  1239. cx.il.Emit(iffalse ? OpCodes.Brfalse : OpCodes.Brtrue, l);
  1240. } else {
  1241. cx.il.Emit(OpCodes.Br, l);
  1242. }
  1243. }
  1244. }
  1245. class ClrCpsReturn : ClrOp {
  1246. ClrOp child;
  1247. public ClrCpsReturn(ClrOp child) {
  1248. this.child = child;
  1249. this.Returns = Tokens.Void;
  1250. }
  1251. public override void CodeGen(CgContext cx) {
  1252. if (child != null) {
  1253. cx.il.Emit(OpCodes.Ldarg_1);
  1254. cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_caller);
  1255. child.CodeGen(cx);
  1256. cx.il.Emit(OpCodes.Stfld, Tokens.Frame_resultSlot);
  1257. }
  1258. cx.il.Emit(OpCodes.Ldarg_1);
  1259. cx.il.Emit(OpCodes.Call, Tokens.Frame_Return);
  1260. cx.il.Emit(OpCodes.Ret);
  1261. }
  1262. }
  1263. class ClrStringLiteral : ClrOp {
  1264. string data;
  1265. public override ClrOp Sink() { return ClrNoop.Instance; }
  1266. public ClrStringLiteral(string data) {
  1267. this.data = data;
  1268. if (data == null) throw new ArgumentNullException();
  1269. Returns = Tokens.String;
  1270. Constant = true;
  1271. }
  1272. public override void CodeGen(CgContext cx) {
  1273. cx.il.Emit(OpCodes.Ldstr, data);
  1274. }
  1275. }
  1276. class ClrCpsFrame : ClrOp {
  1277. public override ClrOp Sink() { return ClrNoop.Instance; }
  1278. private ClrCpsFrame() {
  1279. Returns = Tokens.Frame;
  1280. Constant = true;
  1281. }
  1282. public override void CodeGen(CgContext cx) {
  1283. cx.il.Emit(OpCodes.Ldarg_1);
  1284. }
  1285. [Immutable] public static ClrCpsFrame Instance = new ClrCpsFrame();
  1286. }
  1287. class ClrCpsConsts : ClrOp {
  1288. public override ClrOp Sink() { return ClrNoop.Instance; }
  1289. private ClrCpsConsts() {
  1290. Returns = typeof(Constants);
  1291. Constant = true;
  1292. }
  1293. public override void CodeGen(CgContext cx) {
  1294. cx.il.Emit(OpCodes.Ldarg_0);
  1295. }
  1296. [Immutable] public static ClrCpsConsts Instance = new ClrCpsConsts();
  1297. }
  1298. class ClrNullLiteral : ClrOp {
  1299. public override ClrOp Sink() { return ClrNoop.Instance; }
  1300. public ClrNullLiteral(Type ty) {
  1301. Returns = ty;
  1302. Constant = true;
  1303. }
  1304. public override void CodeGen(CgContext cx) {
  1305. cx.il.Emit(OpCodes.Ldnull);
  1306. }
  1307. }
  1308. class ClrUnboxAny : ClrOp {
  1309. public readonly ClrOp zyg;
  1310. public override ClrOp Sink() { return zyg.Sink(); }
  1311. public ClrUnboxAny(Type ty, ClrOp zyg) {
  1312. Returns = ty;
  1313. this.zyg = zyg;
  1314. }
  1315. public override void CodeGen(CgContext cx) {
  1316. zyg.CodeGen(cx);
  1317. cx.il.Emit(OpCodes.Unbox_Any, Returns);
  1318. }
  1319. }
  1320. class ClrTypeLiteral : ClrOp {
  1321. readonly Type body;
  1322. public override ClrOp Sink() { return ClrNoop.Instance; }
  1323. public ClrTypeLiteral(Type body) {
  1324. this.body = body;
  1325. Returns = typeof(Type);
  1326. Constant = true;
  1327. }
  1328. public override void CodeGen(CgContext cx) {
  1329. cx.il.Emit(OpCodes.Ldtoken, body);
  1330. cx.il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
  1331. }
  1332. }
  1333. class ClrDBDLiteral : ClrOp {
  1334. readonly MethodInfo body;
  1335. public override ClrOp Sink() { return ClrNoop.Instance; }
  1336. public ClrDBDLiteral(MethodInfo body) {
  1337. this.body = body;
  1338. Returns = Tokens.DynBlockDelegate;
  1339. Constant = true;
  1340. }
  1341. public override void CodeGen(CgContext cx) {
  1342. cx.il.Emit(OpCodes.Ldnull);
  1343. cx.il.Emit(OpCodes.Ldftn, body);
  1344. cx.il.Emit(OpCodes.Newobj, Tokens.DynBlockDelegate_ctor);
  1345. }
  1346. }
  1347. // Because the CLR has no evaluation stack types narrower than int32, this
  1348. // node does duty both for int and bool. When sized types are added, it
  1349. // will also handle int8, int16, and unsigned versions thereof.
  1350. class ClrIntLiteral : ClrOp {
  1351. int data;
  1352. public override ClrOp Sink() { return ClrNoop.Instance; }
  1353. public ClrIntLiteral(Type ty, int data) {
  1354. this.data = data;
  1355. Returns = ty;
  1356. Constant = true;
  1357. }
  1358. public override void CodeGen(CgContext cx) {
  1359. cx.EmitInt(data);
  1360. }
  1361. }
  1362. class ClrLongLiteral : ClrOp {
  1363. long data;
  1364. public override ClrOp Sink() { return ClrNoop.Instance; }
  1365. public ClrLongLiteral(Type ty, long data) {
  1366. this.data = data;
  1367. Returns = ty;
  1368. Constant = true;
  1369. }
  1370. public override void CodeGen(CgContext cx) {
  1371. cx.EmitLong(data);
  1372. }
  1373. }
  1374. class ClrLabelLiteral : ClrOp {
  1375. CgContext tcx;
  1376. string name;
  1377. public override ClrOp Sink() { return ClrNoop.Instance; }
  1378. public ClrLabelLiteral(CgContext tcx, string name) {
  1379. this.name = name;
  1380. this.tcx = tcx;
  1381. Returns = Tokens.Int32;
  1382. Constant = true;
  1383. }
  1384. public override void CodeGen(CgContext cx) {
  1385. cx.EmitInt(tcx.named_cases[name]);
  1386. }
  1387. }
  1388. class ClrLabelArray : ClrOp {
  1389. CgContext tcx;
  1390. string[] names;
  1391. public override ClrOp Sink() { return ClrNoop.Instance; }
  1392. public ClrLabelArray(CgContext tcx, string[] names) {
  1393. this.names = names;
  1394. this.tcx = tcx;
  1395. Returns = typeof(int[]);
  1396. Constant = true;
  1397. }
  1398. public override void CodeGen(CgContext cx) {
  1399. byte[] vec = new byte[names.Length*4];
  1400. int j = 0;
  1401. for (int i = 0; i < names.Length; i++) {
  1402. uint k = (uint)tcx.named_cases[names[i]];
  1403. vec[j++] = (byte)k; k >>= 8;
  1404. vec[j++] = (byte)k; k >>= 8;
  1405. vec[j++] = (byte)k; k >>= 8;
  1406. vec[j++] = (byte)k; k >>= 8;
  1407. }
  1408. cx.EmitDataArray(Tokens.Int32, vec.Length / 4, vec);
  1409. }
  1410. }
  1411. class ClrNumLiteral : ClrOp {
  1412. double data;
  1413. public override ClrOp Sink() { return ClrNoop.Instance; }
  1414. public ClrNumLiteral(double data) {
  1415. this.data = data;
  1416. Returns = Tokens.Double;
  1417. Constant = true;
  1418. }
  1419. public override void CodeGen(CgContext cx) {
  1420. cx.il.Emit(OpCodes.Ldc_R8, data);
  1421. }
  1422. }
  1423. class ClrNewArray : ClrOp {
  1424. readonly ClrOp[] zyg;
  1425. public ClrNewArray(Type r, ClrOp[] zyg) {
  1426. Returns = r.MakeArrayType();
  1427. if (r.IsValueType)
  1428. throw new ArgumentException();
  1429. foreach(ClrOp c in zyg)
  1430. TypeCheck(c.Returns, r, "new-array");
  1431. HasCases = false;
  1432. this.zyg = zyg;
  1433. }
  1434. public override ClrOp Sink() {
  1435. ClrOp[] szyg = new ClrOp[zyg.Length];
  1436. for (int i = 0; i < szyg.Length; i++)
  1437. szyg[i] = zyg[i].Sink();
  1438. return new ClrSeq(szyg);
  1439. }
  1440. public override void CodeGen(CgContext cx) {
  1441. cx.EmitInt(zyg.Length);
  1442. cx.il.Emit(OpCodes.Newarr, Returns.GetElementType());
  1443. for (int i = 0; i < zyg.Length; i++) {
  1444. cx.il.Emit(OpCodes.Dup);
  1445. cx.EmitInt(i);
  1446. zyg[i].CodeGen(cx);
  1447. cx.il.Emit(OpCodes.Stelem_Ref);
  1448. }
  1449. }
  1450. }
  1451. class ClrNewDataArray : ClrOp {
  1452. readonly byte[] vec;
  1453. readonly int ct;
  1454. readonly Type ty;
  1455. public ClrNewDataArray(Type ty, int ct, byte[] vec) {
  1456. // TODO: automatically cut array into segments
  1457. if (vec.Length >= 0x3f0000)
  1458. throw new ArgumentException();
  1459. Returns = ty.MakeArrayType();
  1460. this.ty = ty;
  1461. this.ct = ct;
  1462. this.vec = vec;
  1463. Constant = true;
  1464. }
  1465. public override ClrOp Sink() { return ClrNoop.Instance; }
  1466. public override void CodeGen(CgContext cx) {
  1467. cx.EmitDataArray(ty, ct, vec);
  1468. }
  1469. }
  1470. class ClrWiden : ClrOp {
  1471. readonly ClrOp z;
  1472. public ClrWiden(Type to, ClrOp z) {
  1473. Returns = to;
  1474. this.z = z;
  1475. this.Constant = z.Constant;
  1476. }
  1477. public override void ListCases(CgContext cx) { z.ListCases(cx); }
  1478. public override ClrOp Sink() { return z.Sink(); }
  1479. public override void CodeGen(CgContext cx) {
  1480. z.CodeGen(cx);
  1481. }
  1482. }
  1483. // CpsOps are rather higher level, and can support operations that
  1484. // both return to the trampoline and return a value.
  1485. class CpsOp {
  1486. // each statement MUST return void
  1487. public ClrOp[] stmts;
  1488. // the head MUST NOT have cases
  1489. public ClrOp head;
  1490. public CpsOp(ClrOp head) : this(Tokens.EmptyClrOp, head) { }
  1491. public CpsOp(ClrOp[] stmts, ClrOp head) {
  1492. if (head.HasCases)
  1493. throw new Exception("head must not have cases");
  1494. foreach (ClrOp s in stmts)
  1495. if (s.Returns != Tokens.Void)
  1496. throw new Exception("stmts must return void");
  1497. this.head = head;
  1498. this.stmts = stmts;
  1499. }
  1500. public static CpsOp Cps(ClrOp nothead, Type ty) {
  1501. return new CpsOp(new ClrOp[] { nothead }, new ClrResult(ty));
  1502. }
  1503. // this particular use of a delegate feels wrong
  1504. private static CpsOp Primitive(CpsOp[] zyg, Func<ClrOp[],CpsOp> raw) {
  1505. List<ClrOp> stmts = new List<ClrOp>();
  1506. List<ClrOp> args = new List<ClrOp>();
  1507. List<string> pop = new List<string>();
  1508. for (int i = 0; i < zyg.Length; i++) {
  1509. foreach (ClrOp s in zyg[i].stmts)
  1510. stmts.Add(s);
  1511. bool effects_before_use = false;
  1512. for (int j = i + 1; j < zyg.Length; j++)
  1513. if (zyg[j].stmts.Length != 0)
  1514. effects_before_use = true;
  1515. for (int j = 0; j < i; j++)
  1516. if (!zyg[j].head.Constant)
  1517. effects_before_use = true;
  1518. // if we have statements, then we need our head
  1519. // spilled right away, because interleaving evaluation
  1520. // (detectably) isn't allowed.
  1521. // unless, nothing with side effects can possibly
  1522. // come between.
  1523. if (!effects_before_use || zyg[i].stmts.Length == 0) {
  1524. args.Add(zyg[i].head);
  1525. } else {
  1526. string ln = "!spill" + EmitUnit.Current.nextid++;
  1527. args.Add(new ClrPeekLet(ln, zyg[i].head.Returns));
  1528. stmts.Add(new ClrPushLet(ln, zyg[i].head));
  1529. pop.Add(ln);
  1530. }
  1531. }
  1532. CpsOp rval = raw(args.ToArray());
  1533. foreach (ClrOp c in rval.stmts)
  1534. stmts.Add(c);
  1535. ClrOp head = rval.head;
  1536. for (int i = pop.Count - 1; i >= 0; i--)
  1537. head = new ClrDropLet(pop[i], head);
  1538. return new CpsOp(stmts.ToArray(), head);
  1539. }
  1540. public static CpsOp Sequence(params CpsOp[] terms) {
  1541. if (terms.Length == 0) return new CpsOp(ClrNoop.Instance);
  1542. int k = -1;
  1543. foreach (CpsOp t in terms)
  1544. k += 1 + t.stmts.Length;
  1545. ClrOp[] stmts = new ClrOp[k];
  1546. k = 0;
  1547. for (int i = 0; i < terms.Length - 1; i++) {
  1548. if (terms[i].head.Returns != Tokens.Void)
  1549. throw new Exception("Non-void expression used in nonfinal sequence position" + terms[i].head.Returns);
  1550. foreach (ClrOp s in terms[i].stmts)
  1551. stmts[k++] = s;
  1552. stmts[k++] = terms[i].head;
  1553. }
  1554. foreach (ClrOp s in terms[terms.Length - 1].stmts)
  1555. stmts[k++] = s;
  1556. return new CpsOp(stmts, terms[terms.Length - 1].head);
  1557. }
  1558. static ClrOp StripResult(ClrOp it) {
  1559. if (it is ClrResult)
  1560. return ClrNoop.Instance;
  1561. if (it is ClrDropLet) {
  1562. ClrDropLet cit = (ClrDropLet) it;
  1563. string n = cit.Name;
  1564. it = StripResult(cit.Inner);
  1565. if (it != null)
  1566. return new ClrDropLet(n, it);
  1567. }
  1568. return null;
  1569. }
  1570. static void Resultify(ref ClrOp[] stmts, ref ClrOp head) {
  1571. if (head.Returns == Tokens.Void) return;
  1572. ClrOp head_s = StripResult(head);
  1573. if (head_s == null) {
  1574. head_s = ClrNoop.Instance;
  1575. Array.Resize(ref stmts, stmts.Length + 1);
  1576. stmts[stmts.Length - 1] = new ClrSetResult(head);
  1577. }
  1578. head = head_s;
  1579. }
  1580. public static CpsOp Span(string l1, string l2, bool sync,
  1581. List<ClrEhSpan> co, CpsOp body) {
  1582. ClrOp body_h = body.head;
  1583. ClrOp[] body_s = body.stmts;
  1584. Resultify(ref body_s, ref body_h);
  1585. List<ClrOp> stmts = new List<ClrOp>();
  1586. stmts.Add(new ClrLabel(l1, true));
  1587. if (sync) stmts.Add(ClrSync.Instance);
  1588. foreach (ClrOp c in body_s) stmts.Add(c);
  1589. stmts.Add(body_h);
  1590. if (sync) stmts.Add(ClrSync.Instance);
  1591. stmts.Add(new ClrLabel(l2, true));
  1592. foreach (ClrEhSpan cl in co) stmts.Add(cl);
  1593. // TODO: this is currently only used for exceptiony stuff so
  1594. // Variable is required.
  1595. return new CpsOp(stmts.ToArray(), new ClrResult(Tokens.Variable));
  1596. }
  1597. public static CpsOp SyncBefore(CpsOp z) {
  1598. if (z.stmts.Length != 0 && z.stmts[0] == ClrSync.Instance)
  1599. return z;
  1600. if (z.head is ClrSync)
  1601. return z;
  1602. // TODO: it's not really necessary to force a full cps-format
  1603. // node here. But we don't have universal recursion for
  1604. // non-cps nodes.
  1605. ClrOp[] body = new ClrOp[z.stmts.Length + 1];
  1606. Array.Copy(z.stmts, 0, body, 1, body.Length - 1);
  1607. body[0] = ClrSync.Instance;
  1608. return new CpsOp(body, z.head);
  1609. }
  1610. public static CpsOp Ternary(CpsOp cond, CpsOp iftrue, CpsOp iffalse) {
  1611. ClrOp iftrue_h = iftrue.head;
  1612. ClrOp iffalse_h = iffalse.head;
  1613. ClrOp[] iftrue_s = iftrue.stmts;
  1614. ClrOp[] iffalse_s = iffalse.stmts;
  1615. Resultify(ref iftrue_s, ref iftrue_h);
  1616. Resultify(ref iffalse_s, ref iffalse_h);
  1617. EmitUnit eu = EmitUnit.Current;
  1618. string l1 = "!else" + (eu.nextid++);
  1619. string l2 = "!endif" + (eu.nextid++);
  1620. List<ClrOp> stmts = new List<ClrOp>();
  1621. foreach (ClrOp c in cond.stmts)
  1622. stmts.Add(c);
  1623. stmts.Add(new ClrGoto(l1, true, cond.head));
  1624. foreach (ClrOp c in iftrue_s)
  1625. stmts.Add(c);
  1626. stmts.Add(iftrue_h);
  1627. stmts.Add(new ClrGoto(l2, false, null));
  1628. stmts.Add(new ClrLabel(l1, false));
  1629. foreach (ClrOp c in iffalse_s)
  1630. stmts.Add(c);
  1631. stmts.Add(iffalse_h);
  1632. stmts.Add(new ClrLabel(l2, false));
  1633. Type ty = iffalse.head.Returns;
  1634. if (iftrue.head.Returns != ty) {
  1635. if (Tokens.Variable.IsAssignableFrom(iftrue.head.Returns) &&
  1636. Tokens.Variable.IsAssignableFrom(ty))
  1637. ty = Tokens.Variable;
  1638. else
  1639. throw new Exception("Cannot match types in ternary: " + iftrue.head.Returns + " " + ty);
  1640. }
  1641. return new CpsOp(stmts.ToArray(),
  1642. (ty == Tokens.Void) ? (ClrOp)ClrNoop.Instance :
  1643. new ClrResult(ty));
  1644. }
  1645. // this is simplified a bit since body is always void
  1646. public static CpsOp While(bool until, bool once, CpsOp cond, CpsOp body) {
  1647. EmitUnit eu = EmitUnit.Current;
  1648. string l1 = "!again" + (eu.nextid++);
  1649. string l2 = "!check" + (eu.nextid++);
  1650. List<ClrOp> stmts = new List<ClrOp>();
  1651. if (!once)
  1652. stmts.Add(new ClrGoto(l2, false, null));
  1653. stmts.Add(new ClrLabel(l1, false));
  1654. foreach(ClrOp c in body.stmts)
  1655. stmts.Add(c);
  1656. stmts.Add(body.head);
  1657. if (!once)
  1658. stmts.Add(new ClrLabel(l2, false));
  1659. foreach(ClrOp c in cond.stmts)
  1660. stmts.Add(c);
  1661. stmts.Add(new ClrGoto(l1, until, cond.head));
  1662. return new CpsOp(stmts.ToArray(), ClrNoop.Instance);
  1663. }
  1664. public static CpsOp MethodCall(MethodInfo tk, params CpsOp[] zyg) {
  1665. return CpsCall(null, tk, zyg);
  1666. }
  1667. public static CpsOp CpsCall(Type cps, MethodInfo tk, params CpsOp[] zyg) {
  1668. return Primitive(zyg, delegate (ClrOp[] heads) {
  1669. return (cps == null) ?
  1670. new CpsOp(new ClrMethodCall(false, tk, heads)) :
  1671. Cps(new ClrMethodCall(true, tk, heads), cps);
  1672. });
  1673. }
  1674. public static CpsOp ConstructorCall(ConstructorInfo tk, params CpsOp[] zyg) {
  1675. return Primitive(zyg, delegate (ClrOp[] heads) {
  1676. return new CpsOp(new ClrConstructorCall(tk, heads));
  1677. });
  1678. }
  1679. public static CpsOp CpsReturn(params CpsOp[] zyg) {
  1680. return Primitive(zyg, delegate (ClrOp[] heads) {
  1681. return new CpsOp(new ClrCpsReturn(heads.Length > 0 ? heads[0] : null));
  1682. });
  1683. }
  1684. public static CpsOp LabelId(CgContext tcx, string label) {
  1685. return new CpsOp(new ClrLabelLiteral(tcx, label));
  1686. }
  1687. public static CpsOp LabelTable(CgContext tcx, string[] labels) {
  1688. return new CpsOp(new ClrLabelArray(tcx, labels));
  1689. }
  1690. public static CpsOp Goto(string label, bool iffalse, params CpsOp[] zyg) {
  1691. return Primitive(zyg, delegate (ClrOp[] heads) {
  1692. return new CpsOp(new ClrGoto(label, iffalse,
  1693. heads.Length > 0 ? heads[0] : null));
  1694. });
  1695. }
  1696. public static CpsOp GotoReturn(string label, CpsOp body) {
  1697. ClrOp body_h = body.head;
  1698. ClrOp[] body_s = body.stmts;
  1699. Resultify(ref body_s, ref body_h);
  1700. List<ClrOp> stmts = new List<ClrOp>();
  1701. foreach (ClrOp c in body_s) stmts.Add(c);
  1702. stmts.Add(body_h);
  1703. stmts.Add(new ClrGoto(label, false, null));
  1704. return new CpsOp(stmts.ToArray(), new ClrNullLiteral(Tokens.Variable));
  1705. }
  1706. public static CpsOp StringLiteral(string s) {
  1707. return new CpsOp(new ClrStringLiteral(s));
  1708. }
  1709. public static CpsOp DoubleLiteral(double d) {
  1710. return new CpsOp(new ClrNumLiteral(d));
  1711. }
  1712. public static CpsOp CharLiteral(char x) {
  1713. return new CpsOp(new ClrIntLiteral(typeof(char), x));
  1714. }
  1715. public static CpsOp ShortLiteral(int x) {
  1716. return new CpsOp(new ClrIntLiteral(Tokens.Int16, x));
  1717. }
  1718. public static CpsOp IntLiteral(int x) {
  1719. return new CpsOp(new ClrIntLiteral(Tokens.Int32, x));
  1720. }
  1721. public static CpsOp BoolLiteral(bool x) {
  1722. return new CpsOp(new ClrIntLiteral(Tokens.Boolean, x ? 1 : 0));
  1723. }
  1724. public static CpsOp LongLiteral(long x) {
  1725. return new CpsOp(new ClrLongLiteral(Tokens.Int64, x));
  1726. }
  1727. public static CpsOp ULongLiteral(ulong x) {
  1728. return new CpsOp(new ClrLongLiteral(Tokens.UInt64, (long)x));
  1729. }
  1730. public static CpsOp TypeLiteral(Type x) {
  1731. return new CpsOp(new ClrTypeLiteral(x));
  1732. }
  1733. public static CpsOp DBDLiteral(MethodInfo x) {
  1734. return new CpsOp(new ClrDBDLiteral(x));
  1735. }
  1736. public static CpsOp Label(string name, bool case_too) {
  1737. return CpsOp.Cps(new ClrLabel(name, case_too), Tokens.Void);
  1738. }
  1739. public static CpsOp IsConst(CpsOp real) {
  1740. if (real.stmts.Length != 0 || real.head.Returns == Tokens.Void)
  1741. throw new ArgumentException();
  1742. return new CpsOp(real.stmts, new ClrMarkConstant(real.head));
  1743. }
  1744. // A previous niecza backend had this stuff tie into the
  1745. // lifter, such that var->obj predictably happened as the
  1746. // beginning. But TimToady says that's not needed.
  1747. public static CpsOp Contexty(FieldInfo thing, MethodInfo inv,
  1748. CpsOp[] zyg) {
  1749. return Primitive(zyg, delegate(ClrOp[] heads) {
  1750. return new CpsOp(new ClrContexty(thing, inv, heads));
  1751. });
  1752. }
  1753. public static CpsOp Operator(Type rt, OpCode op, params CpsOp[] zyg) {
  1754. return Primitive(zyg, delegate(ClrOp[] heads) {
  1755. return new CpsOp(new ClrOperator(rt, op, heads));
  1756. });
  1757. }
  1758. // this is a stupid interface.
  1759. public static CpsOp PolyOp(string txt, CpsOp a, CpsOp b) {
  1760. return Primitive(new CpsOp[] { a, b }, delegate(ClrOp[] heads) {
  1761. if (heads[0].Returns != heads[1].Returns)
  1762. throw new ArgumentException("Arguments to " + txt + " must have same type");
  1763. if (heads[0].Returns == Tokens.Int32 ||
  1764. heads[0].Returns == Tokens.Double) {
  1765. } else if (!heads[0].Returns.IsValueType &&
  1766. (txt == "==" || txt == "!=")) {
  1767. } else
  1768. throw new NotImplementedException();
  1769. OpCode op;
  1770. if (txt == "+") { op = OpCodes.Add; }
  1771. else if (txt == "-") { op = OpCodes.Sub; }
  1772. else if (txt == "*") { op = OpCodes.Mul; }
  1773. else if (txt == "/") { op = OpCodes.Div; }
  1774. else return new CpsOp(new ClrCompare(txt, heads));
  1775. return new CpsOp(new ClrOperator(heads[0].Returns, op, heads));
  1776. });
  1777. }
  1778. public static CpsOp PokeLet(string name, CpsOp zyg) {
  1779. return Primitive(new CpsOp[] { zyg }, delegate(ClrOp[] heads) {
  1780. return new CpsOp(new ClrPokeLet(name, heads[0]));
  1781. });
  1782. }
  1783. public static CpsOp PeekLet(string name, Type rt) {
  1784. return new CpsOp(new ClrPeekLet(name, rt));
  1785. }
  1786. public static CpsOp Let(string name, CpsOp head, CpsOp tail) {
  1787. List<ClrOp> stmts = new List<ClrOp>();
  1788. foreach (ClrOp c in head.stmts)
  1789. stmts.Add(c);
  1790. stmts.Add(new ClrPushLet(name, head.head));
  1791. foreach (ClrOp c in tail.stmts)
  1792. stmts.Add(c);
  1793. return new CpsOp(stmts.ToArray(), new ClrDropLet(name, tail.head));
  1794. }
  1795. public static CpsOp Annotate(int line, CpsOp body) {
  1796. if (body.stmts.Length == 0) return body;
  1797. List<ClrOp> stmts = new List<ClrOp>();
  1798. stmts.Add(new ClrPushLine(line));
  1799. foreach (ClrOp c in body.stmts) stmts.Add(c);
  1800. stmts.Add(new ClrPopLine());
  1801. return new CpsOp(stmts.ToArray(), body.head);
  1802. }
  1803. public static CpsOp LexAccess(LexInfo l, int up, CpsOp[] zyg) {
  1804. return Primitive(zyg, delegate(ClrOp[] heads) {
  1805. return new CpsOp((heads.Length >= 1)
  1806. ? l.SetCode(up, heads[0], EmitUnit.Current.np.sub)
  1807. : new ClrWiden(Tokens.Variable,
  1808. l.GetCode(up, EmitUnit.Current.np.sub)));
  1809. });
  1810. }
  1811. public static CpsOp SubyCall(bool method, string sig, params CpsOp[] zyg) {
  1812. return Primitive(zyg, delegate(ClrOp[] heads) {
  1813. return CpsOp.Cps(new ClrSubyCall(method, sig, heads), Tokens.Variable);
  1814. });
  1815. }
  1816. public static CpsOp GetField(FieldInfo fi, CpsOp zyg) {
  1817. return Primitive(new CpsOp[1] { zyg }, delegate(ClrOp[] heads) {
  1818. return new CpsOp(new ClrGetField(fi, heads[0]));
  1819. });
  1820. }
  1821. public static CpsOp GetConst(FieldInfo fi) {
  1822. return new CpsOp(new ClrGetConst(fi));
  1823. }
  1824. public static CpsOp SetField(FieldInfo fi, CpsOp za, CpsOp zb) {
  1825. return Primitive(new CpsOp[2] { za, zb }, delegate(ClrOp[] heads) {
  1826. return new CpsOp(new ClrSetField(fi, heads[0], heads[1]));
  1827. });
  1828. }
  1829. public static CpsOp Sink(CpsOp zyg) {
  1830. return new CpsOp(zyg.stmts, zyg.head.Sink());
  1831. }
  1832. public static CpsOp Null(Type ty) {
  1833. return new CpsOp(new ClrNullLiteral(ty));
  1834. }
  1835. public static CpsOp UnboxAny(Type ty, CpsOp inside) {
  1836. return Primitive(new CpsOp[] { inside }, delegate (ClrOp[] h) {
  1837. return new CpsOp(new ClrUnboxAny(ty, h[0]));
  1838. });
  1839. }
  1840. public static CpsOp CallFrame() {
  1841. return new CpsOp(ClrCpsFrame.Instance);
  1842. }
  1843. public static CpsOp Constants() {
  1844. return new CpsOp(ClrCpsConsts.Instance);
  1845. }
  1846. public static CpsOp RxFrame() {
  1847. return IsConst(GetField(Tokens.Frame_rx, CallFrame()));
  1848. }
  1849. // only use this for reference types
  1850. public static CpsOp NewArray(Type ty, params CpsOp[] zyg) {
  1851. return Primitive(zyg, delegate (ClrOp[] h) {
  1852. return new CpsOp(new ClrNewArray(ty, h));
  1853. });
  1854. }
  1855. public static CpsOp NewByteArray(Type ty, byte[] vec) {
  1856. return new CpsOp(new ClrNewDataArray(ty, vec.Length, vec));
  1857. }
  1858. public static CpsOp NewIntArray(Type ty, int[] vec) {
  1859. byte[] buf = new byte[vec.Length * 4];
  1860. int r = 0;
  1861. for (int i = 0; i < vec.Length; i++) {
  1862. uint d = (uint) vec[i];
  1863. buf[r++] = (byte)((d >> 0) & 0xFF);
  1864. buf[r++] = (byte)((d >> 8) & 0xFF);
  1865. buf[r++] = (byte)((d >> 16) & 0xFF);
  1866. buf[r++] = (byte)((d >> 24) & 0xFF);
  1867. }
  1868. return new CpsOp(new ClrNewDataArray(ty, vec.Length, buf));
  1869. }
  1870. public static CpsOp Widen(Type to, CpsOp z) {
  1871. return new CpsOp(z.stmts, new ClrWiden(to, z.head));
  1872. }
  1873. }
  1874. class CpsBuilder {
  1875. public readonly TypeBuilder tb;
  1876. public readonly MethodBuilder mb;
  1877. public readonly CgContext cx;
  1878. public readonly EmitUnit eu;
  1879. public CpsBuilder(EmitUnit eu, string clrname, bool pub) {
  1880. this.eu = eu;
  1881. this.tb = eu.type_builder;
  1882. mb = tb.DefineMethod(clrname, (pub ? MethodAttributes.Public : 0),
  1883. typeof(Frame), new Type[] { typeof(Frame) });
  1884. cx = new CgContext();
  1885. cx.tb = tb;
  1886. }
  1887. public void ReserveLex(int ct) {
  1888. Array.Resize(ref cx.let_types, ct + Tokens.NumInt32);
  1889. Array.Resize(ref cx.let_names, ct + Tokens.NumInt32);
  1890. for (int i = 0; i < ct; i++) {
  1891. cx.let_types[i+ Tokens.NumInt32] = Tokens.Variable;
  1892. }
  1893. }
  1894. public int Spills() {
  1895. int ix = cx.let_types.Length - Tokens.NumInt32 - Tokens.NumInline;
  1896. return (ix > 0) ? ix : 0;
  1897. }
  1898. public void Build(CpsOp body) {
  1899. // ListCases may want to define labels, so this needs to come
  1900. // early
  1901. cx.il = mb.GetILGenerator();
  1902. cx.num_cases = 1;
  1903. foreach (ClrOp s in body.stmts)
  1904. s.ListCases(cx);
  1905. body.head.ListCases(cx);
  1906. cx.cases = new Label[cx.num_cases];
  1907. for (int i = 0; i < cx.num_cases; i++)
  1908. cx.cases[i] = cx.il.DefineLabel();
  1909. cx.il.Emit(OpCodes.Ldarg_1);
  1910. cx.il.Emit(OpCodes.Ldfld, Tokens.Frame_ip);
  1911. cx.il.Emit(OpCodes.Switch, cx.cases);
  1912. cx.il.Emit(OpCodes.Ldarg_1);
  1913. cx.il.Emit(OpCodes.Ldstr, "Invalid IP");
  1914. cx.il.Emit(OpCodes.Call, Tokens.Kernel_Die);
  1915. cx.il.Emit(OpCodes.Ret);
  1916. cx.il.MarkLabel(cx.cases[cx.next_case++]);
  1917. cx.save_line();
  1918. foreach (ClrOp s in body.stmts)
  1919. s.CodeGen(cx);
  1920. body.head.CodeGen(cx);
  1921. }
  1922. }
  1923. class NamProcessor {
  1924. internal SubInfo sub;
  1925. public readonly CpsBuilder cpb;
  1926. Dictionary<string, Type> let_types = new Dictionary<string, Type>();
  1927. List<List<ClrEhSpan>> eh_stack = new List<List<ClrEhSpan>>();
  1928. List<object[]> scope_stack = new List<object[]>();
  1929. internal List<KeyValuePair<AltInfo, string[]>> altinfo_fixups =
  1930. new List<KeyValuePair<AltInfo, string[]>>();
  1931. public NamProcessor(CpsBuilder cpb, SubInfo sub) {
  1932. this.sub = sub;
  1933. this.cpb = cpb;
  1934. }
  1935. CpsOp AccessLex(object[] zyg) {
  1936. return RawAccessLex( JScalar.S(zyg[0]), JScalar.S(zyg[1]),
  1937. (zyg.Length > 2 ? Scan(zyg[2]) : null));
  1938. }
  1939. CpsOp AccessLet(object[] zyg) {
  1940. string name = JScalar.S(zyg[1]);
  1941. CpsOp set_to = zyg.Length > 2 ? Scan(zyg[2]) : null;
  1942. Type t;
  1943. if (let_types.TryGetValue(name, out t)) {
  1944. return (set_to == null) ? CpsOp.PeekLet(name, t) :
  1945. CpsOp.PokeLet(name, set_to);
  1946. }
  1947. throw new Exception("No such let " + name);
  1948. }
  1949. CpsOp CheckScopes(string name, ref int outer, CpsOp set_to) {
  1950. for (int i = scope_stack.Count - 1; i >= 0; i--) {
  1951. if (outer > 0) { outer--; continue; }
  1952. object[] rec = scope_stack[i];
  1953. for (int j = 2; j < rec.Length - 2; j += 2) {
  1954. if (JScalar.S(rec[j]) == name) {
  1955. string lname = JScalar.S(rec[j+1]);
  1956. return (set_to == null) ?
  1957. CpsOp.PeekLet(lname, let_types[lname]) :
  1958. CpsOp.PokeLet(lname, set_to);
  1959. }
  1960. }
  1961. }
  1962. return null;
  1963. }
  1964. CpsOp RawAccessLex(string type, string name, CpsOp set_to) {
  1965. bool core = type == "corelex";
  1966. int outer = (type == "outerlex") ? 1 : 0;
  1967. int uplevel;
  1968. CpsOp r;
  1969. if (!core && (r = CheckScopes(name, ref outer, set_to)) != null)
  1970. return r;
  1971. LexInfo lex = ResolveLex(name, outer>0, out uplevel, core);
  1972. if (lex == null) {
  1973. CpsOp sc = CpsOp.ConstructorCall(Tokens.SC_ctor,
  1974. CpsOp.CallFrame(), CpsOp.IntLiteral(
  1975. scope_stack.Count));
  1976. if (core) name = "CORE::" + name;
  1977. if (outer != 0) name = "OUTER::" + name;
  1978. return CpsOp.MethodCall(Tokens.StashCursor.
  1979. GetMethod("Indirect"), sc, CpsOp.StringLiteral(name),
  1980. CpsOp.BoolLiteral(false), set_to != null ? set_to :
  1981. CpsOp.Null(Tokens.Variable));
  1982. }
  1983. return CpsOp.LexAccess(lex, uplevel,
  1984. set_to == null ? new CpsOp[0] : new CpsOp[] { set_to });
  1985. }
  1986. LexInfo ResolveLex(string name, bool upf, out int uplevel, bool core) {
  1987. uplevel = 0;
  1988. SubInfo csr = sub;
  1989. if (upf) {
  1990. csr = csr.outer;
  1991. uplevel++;
  1992. }
  1993. while (true) {
  1994. LexInfo r;
  1995. if ((!core || csr.unit.name == "CORE") &&
  1996. csr.dylex.TryGetValue(name, out r)) {
  1997. if (r is LIAlias) {
  1998. name = (r as LIAlias).to;
  1999. continue;
  2000. } else {
  2001. return r;
  2002. }
  2003. }
  2004. if (csr.outer == null)
  2005. return null;
  2006. csr = csr.outer;
  2007. uplevel++;
  2008. }
  2009. }
  2010. STable ResolvePkg(string name) {
  2011. int dummy;
  2012. LexInfo li = ResolveLex(name, false, out dummy, true);
  2013. if (li == null)
  2014. throw new Exception("Unable to find lexical " + name + " in " + sub.name);
  2015. return ((LIPackage)li).pkg;
  2016. }
  2017. // synchronize with LIDispatch.MakeDispatch
  2018. internal CpsOp MakeDispatch(string prefix) {
  2019. HashSet<string> names = new HashSet<string>();
  2020. List<CpsOp> cands = new List<CpsOp>();
  2021. CpsOp proto = CpsOp.Null(Tokens.P6any);
  2022. string filter = prefix + ":";
  2023. string pn = prefix + ":(!proto)";
  2024. for (SubInfo csr = sub; ; csr = csr.outer) {
  2025. bool brk = false;
  2026. foreach (KeyValuePair<string,LexInfo> kp in csr.dylex) {
  2027. if (Utils.StartsWithInvariant(filter, kp.Key) &&
  2028. kp.Key != pn &&
  2029. !names.Contains(kp.Key)) {
  2030. names.Add(kp.Key);
  2031. brk = true;
  2032. cands.Add(CpsOp.MethodCall(Tokens.Variable_Fetch, RawAccessLex("scopedlex", kp.Key, null)));
  2033. }
  2034. }
  2035. if (csr.outer == null) break;
  2036. // don't go above nearest proto
  2037. if (csr.dylex.ContainsKey(pn)) {
  2038. proto = CpsOp.MethodCall(Tokens.Variable_Fetch, RawAccessLex("scopedlex", pn, null));
  2039. break;
  2040. }
  2041. if (brk) cands.Add(CpsOp.Null(Tokens.P6any));
  2042. }
  2043. return CpsOp.MethodCall(Tokens.Kernel_MakeDispatcher,
  2044. CpsOp.CallFrame(),
  2045. CpsOp.StringLiteral(prefix), proto,
  2046. CpsOp.NewArray(Tokens.P6any, cands.ToArray()));
  2047. }
  2048. object[] InlineCall(SubInfo tgt, object[] zyg) {
  2049. EmitUnit eu = EmitUnit.Current;
  2050. object tgzyg = Reader.Read(tgt.nam_str, tgt.nam_refs);
  2051. string[] lex_names = (new List<string>(tgt.dylex.Keys)).ToArray();
  2052. // locale-independant code generation
  2053. Array.Sort(lex_names, string.CompareOrdinal);
  2054. // letscope: gives visible names to lets
  2055. List<object> scope = new List<object>();
  2056. scope.Add("letscope");
  2057. scope.Add((tgt.special & SubInfo.TRANSPARENT) != 0 ? "1" : "0");
  2058. // let: introduces symbols for !argN, !lexN
  2059. List<object> let = new List<object>();
  2060. let.Add("letn");
  2061. List<object> bind = new List<object>();
  2062. bind.Add("_inlinebind");
  2063. bind.Add(tgt.name);
  2064. bind.Add(tgt.sig);
  2065. bind.Add(null);
  2066. // give unique names to the arguments
  2067. foreach (object a in zyg) {
  2068. string alias = "!arg" + eu.nextid++;
  2069. bind.Add(new object[] { "letvar", alias });
  2070. let.Add(alias);
  2071. let.Add(a);
  2072. }
  2073. string[] slot_to_lex = new string[tgt.num_lex_slots];
  2074. for (int i = 0; i < lex_names.Length; i++) {
  2075. string ln = lex_names[i];
  2076. LISimple li = (LISimple)tgt.dylex[ln]; // checked in inlinable()
  2077. string let_name = "!var" + eu.nextid++;
  2078. slot_to_lex[li.index] = ln;
  2079. let.Add(let_name);
  2080. if ((li.flags & LISimple.NOINIT) != 0)
  2081. let.Add(new object[] { "null", "var" });
  2082. else if ((li.flags & LISimple.ROINIT) != 0)
  2083. let.Add(new object[] { "scopedlex", "Any" });
  2084. else if ((li.flags & LISimple.DEFOUTER) != 0)
  2085. let.Add(new object[] { "scopedlex", ln });
  2086. else if ((li.flags & LISimple.HASH) != 0)
  2087. let.Add(new object[] { "newhash" });
  2088. else if ((li.flags & LISimple.LIST) != 0)
  2089. let.Add(new object[] { "newarray" });
  2090. else if (li.type == null)
  2091. let.Add(new object[] { "newblankrwscalar" });
  2092. else
  2093. let.Add(new object[] { "_newoftype",
  2094. eu.TypeConstant(li.type) });
  2095. scope.Add(ln);
  2096. scope.Add(let_name);
  2097. }
  2098. string[] lexicals_fixup =
  2099. new string[tgt.sig.parms.Length];
  2100. for (int i = 0; i < lexicals_fixup.Length; i ++) {
  2101. int slot = tgt.sig.parms[i].slot;
  2102. if (slot < 0)
  2103. lexicals_fixup[i] = null;
  2104. else
  2105. lexicals_fixup[i] = slot_to_lex[slot];
  2106. }
  2107. bind[3] = lexicals_fixup;
  2108. scope.Add(new object[] {
  2109. "prog",
  2110. bind.ToArray(),
  2111. tgzyg
  2112. });
  2113. let.Add(scope.ToArray());
  2114. if (tgt.IsTopicalizer()) {
  2115. int tid = eu.nextid++;
  2116. return new object[] {
  2117. "xspan", "!start"+tid, "!end"+tid, "0", let.ToArray(),
  2118. SubInfo.ON_SUCCEED.ToString(), "", "!end"+tid
  2119. };
  2120. } else {
  2121. return let.ToArray();
  2122. }
  2123. }
  2124. CpsOp SubyCall(bool ismethod, object[] zyg) {
  2125. int sh = ismethod ? 3 : 2;
  2126. string sig = JScalar.S(zyg[sh-1]);
  2127. CpsOp[] args = new CpsOp[zyg.Length - 2];
  2128. if (ismethod) {
  2129. args[0] = AnyStr(zyg[1]);
  2130. }
  2131. for (int i = sh; i < zyg.Length; i++)
  2132. args[i-2] = Scan(zyg[i]);
  2133. return CpsOp.SubyCall(ismethod, sig, args);
  2134. }
  2135. static string FixStr(object z) { return JScalar.S(z); }
  2136. static double FixNum(object z) { return JScalar.N(z); }
  2137. static int FixInt(object z) { return (int)FixNum(z); }
  2138. static bool FixBool(object z) { return FixNum(z) != 0; }
  2139. CpsOp AnyStr(object z) {
  2140. return (z is object[]) ? Scan(z) : CpsOp.StringLiteral(FixStr(z));
  2141. }
  2142. [Immutable] static Dictionary<string, Func<NamProcessor, object[], CpsOp>> handlers;
  2143. [Immutable] static Dictionary<string, Func<CpsOp[], CpsOp>> thandlers;
  2144. [Immutable] static Dictionary<string, Type> namtypes;
  2145. static Type namtype(object z) {
  2146. string name = JScalar.S(z);
  2147. if (name.Length > 4 && name.Substring(0,4) == "clr:")
  2148. return Type.GetType(name.Substring(4));
  2149. return namtypes[name];
  2150. }
  2151. static NamProcessor() {
  2152. namtypes = new Dictionary<string, Type>();
  2153. namtypes["str"] = Tokens.String;
  2154. namtypes["num"] = Tokens.Double;
  2155. namtypes["int"] = Tokens.Int32;
  2156. namtypes["var"] = Tokens.Variable;
  2157. namtypes["stable"] = Tokens.STable;
  2158. namtypes["obj"] = Tokens.P6any;
  2159. namtypes["fvarlist"] = Tokens.FVarList;
  2160. namtypes["vvarlist"] = Tokens.VVarList;
  2161. namtypes["varhash"] = Tokens.VarHash;
  2162. namtypes["frame"] = Tokens.Frame;
  2163. namtypes["cursor"] = Tokens.Cursor;
  2164. namtypes["strbuf"] = typeof(StringBuilder);
  2165. namtypes["treader"] = typeof(TextReader);
  2166. namtypes["twriter"] = typeof(TextWriter);
  2167. namtypes["blob"] = typeof(byte[]);
  2168. namtypes["socket"] = typeof(System.Net.Sockets.Socket);
  2169. handlers = new Dictionary<string, Func<NamProcessor,object[],CpsOp>>();
  2170. thandlers = new Dictionary<string, Func<CpsOp[], CpsOp>>();
  2171. handlers["null"] = delegate(NamProcessor th, object[] zyg) {
  2172. return CpsOp.Null(namtype(zyg[1])); };
  2173. handlers["str"] = delegate(NamProcessor th, object[] zyg) {
  2174. return CpsOp.StringLiteral(JScalar.S(zyg[1])); };
  2175. handlers["int"] = delegate(NamProcessor th, object[] zyg) {
  2176. return CpsOp.IntLiteral(JScalar.I(zyg[1])); };
  2177. handlers["char"] = delegate(NamProcessor th, object[] zyg) {
  2178. return CpsOp.CharLiteral(JScalar.S(zyg[1])[0]); };
  2179. handlers["double"] = delegate(NamProcessor th, object[] zyg) {
  2180. return CpsOp.DoubleLiteral(JScalar.N(zyg[1])); };
  2181. handlers["bool"] = delegate(NamProcessor th, object[] zyg) {
  2182. return CpsOp.BoolLiteral(FixBool(zyg[1])); };
  2183. handlers["ann"] = delegate(NamProcessor th, object[] zyg) {
  2184. return CpsOp.Annotate(FixInt(zyg[1]), th.Scan(zyg[2])); };
  2185. thandlers["statement"] = delegate(CpsOp[] z) {
  2186. return CpsOp.SyncBefore(z[0]); };
  2187. handlers["label"] = delegate(NamProcessor th, object[] z) {
  2188. return CpsOp.Label(FixStr(z[1]), true);
  2189. };
  2190. handlers["cgoto"] = delegate(NamProcessor th, object[] z) {
  2191. return CpsOp.Goto(FixStr(z[1]), false, th.Scan(z[2]));
  2192. };
  2193. handlers["ncgoto"] = delegate(NamProcessor th, object[] z) {
  2194. return CpsOp.Goto(FixStr(z[1]), true, th.Scan(z[2]));
  2195. };
  2196. handlers["goto"] = delegate(NamProcessor th, object[] z) {
  2197. return CpsOp.Goto(FixStr(z[1]), false);
  2198. };
  2199. handlers["xspan"] = delegate(NamProcessor th, object[] z) {
  2200. List<ClrEhSpan> xn = new List<ClrEhSpan>();
  2201. string ls = FixStr(z[1]);
  2202. string le = FixStr(z[2]);
  2203. for (int i = 5; i < z.Length; i += 3)
  2204. xn.Add(new ClrEhSpan(FixInt(z[i]), FixStr(z[i+1]),
  2205. ls, le, FixStr(z[i+2])));
  2206. th.eh_stack.Add(xn);
  2207. CpsOp ch = th.Scan(z[4]);
  2208. th.eh_stack.RemoveAt(th.eh_stack.Count - 1);
  2209. return CpsOp.Span(ls, le, FixBool(z[3]), xn, ch);
  2210. };
  2211. handlers["_inlinebind"] = delegate(NamProcessor th, object[] zyg) {
  2212. CpsOp[] args = JScalar.A<CpsOp>(4, zyg, th.Scan);
  2213. Signature sig = (Signature)zyg[2];
  2214. string[] lexnames = (string[])zyg[3];
  2215. string name = (string)zyg[1];
  2216. EmitUnit eu = EmitUnit.Current;
  2217. List<CpsOp> ops = new List<CpsOp>();
  2218. int aused = 0;
  2219. for (int i = 0; i < sig.parms.Length; i++) {
  2220. int flags = sig.parms[i].flags;
  2221. string lex = lexnames[i];
  2222. STable type = sig.parms[i].type;
  2223. CpsOp get = null;
  2224. if (aused < args.Length) {
  2225. get = args[aused++];
  2226. } else if ((flags & Parameter.DEFOUTER) != 0) {
  2227. get = th.RawAccessLex("outerlex", lex, null);
  2228. } else if ((flags & Parameter.OPTIONAL) != 0) {
  2229. get = eu.TypeConstantP(type);
  2230. } else {
  2231. get = CpsOp.CpsCall(Tokens.Variable, Tokens.Kernel_Die,
  2232. CpsOp.StringLiteral("No value in "+name+" available for parameter "+sig.parms[i].name));
  2233. }
  2234. if (lex == null) {
  2235. ops.Add(CpsOp.Sink(get));
  2236. } else if ((flags & Parameter.IS_COPY) != 0) {
  2237. CpsOp init;
  2238. if ((flags & Parameter.IS_HASH) != 0) {
  2239. init = CpsOp.MethodCall(Tokens.Kernel_CreateHash);
  2240. } else if ((flags & Parameter.IS_LIST) != 0) {
  2241. init = CpsOp.MethodCall(Tokens.Kernel_CreateArray);
  2242. } else if (type == null) {
  2243. init = CpsOp.MethodCall(Tokens.Kernel_NewMuAnyScalar, CpsOp.CallFrame());
  2244. } else {
  2245. init = CpsOp.MethodCall(Tokens.Kernel_NewTypedScalar,
  2246. eu.TypeConstant(type));
  2247. }
  2248. ops.Add(th.RawAccessLex("scopedlex", lex, init));
  2249. ops.Add(CpsOp.Sink(CpsOp.MethodCall(
  2250. Tokens.Kernel_Assign,
  2251. th.RawAccessLex("scopedlex", lex, null),
  2252. get)));
  2253. } else if ((flags & Parameter.RWTRANS) != 0) {
  2254. ops.Add(th.RawAccessLex("scopedlex", lex, get));
  2255. } else {
  2256. int mode = 0;
  2257. if ((flags & Parameter.READWRITE) != 0)
  2258. mode = Kernel.NBV_RW;
  2259. else if ((flags & (Parameter.IS_LIST |
  2260. Parameter.IS_HASH)) != 0)
  2261. mode = Kernel.NBV_LIST;
  2262. ops.Add(th.RawAccessLex("scopedlex", lex,
  2263. CpsOp.MethodCall(Tokens.Kernel_NewBoundVar,
  2264. CpsOp.IntLiteral(mode),
  2265. eu.TypeConstant(type), get)));
  2266. }
  2267. }
  2268. return CpsOp.Sequence(ops.ToArray());
  2269. };
  2270. handlers["_inline"] = delegate(NamProcessor th, object[] zyg) {
  2271. object[] rzyg = new object[zyg.Length - 2];
  2272. Array.Copy(zyg, 2, rzyg, 0, rzyg.Length);
  2273. return th.Scan(th.InlineCall((SubInfo)zyg[1], rzyg));
  2274. };
  2275. handlers["letscope"] = delegate(NamProcessor th, object[] zyg) {
  2276. List<ClrEhSpan> xn = new List<ClrEhSpan>();
  2277. string s = "!start" + EmitUnit.Current.nextid++;
  2278. string e = "!end" + EmitUnit.Current.nextid++;
  2279. for (int i = 2; i < zyg.Length - 2; i += 2) {
  2280. string vn = JScalar.S(zyg[i]);
  2281. string ln = JScalar.S(zyg[i+1]);
  2282. xn.Add(new ClrEhSpan(SubInfo.ON_VARLOOKUP, vn, s, e, ln));
  2283. }
  2284. th.scope_stack.Add(zyg);
  2285. xn.Add(new ClrEhSpan(SubInfo.ON_VARLOOKUP, "", s, e, th.scope_stack.Count));
  2286. CpsOp co = th.Scan(zyg[zyg.Length - 1]);
  2287. th.scope_stack.RemoveAt(th.scope_stack.Count - 1);
  2288. return CpsOp.Span(s, e, false, xn, co);
  2289. };
  2290. handlers["widen"] = delegate(NamProcessor th, object[] zyg) {
  2291. return CpsOp.Widen(namtype(zyg[1]), th.Scan(zyg[2])); };
  2292. handlers["letvar"] = delegate(NamProcessor th, object[] zyg) {
  2293. return th.AccessLet(zyg); };
  2294. handlers["scopedlex"] =
  2295. handlers["outerlex"] =
  2296. handlers["corelex"] = delegate(NamProcessor th, object[] zyg) {
  2297. return th.AccessLex(zyg); };
  2298. handlers["compare"] = handlers["arith"] =
  2299. delegate(NamProcessor th, object[] zyg) {
  2300. return CpsOp.PolyOp(FixStr(zyg[1]),
  2301. th.Scan(zyg[2]), th.Scan(zyg[3])); };
  2302. handlers["setslot"] = delegate(NamProcessor th, object[] zyg) {
  2303. CpsOp scope = (zyg[1] is object[]) ? th.Scan(zyg[1]) :
  2304. th.cpb.eu.TypeConstant(th.ResolvePkg(JScalar.S(zyg[1])));
  2305. return CpsOp.MethodCall(Tokens.P6any_SetSlot,
  2306. th.Scan(zyg[3]), scope, th.AnyStr(zyg[2]), th.Scan(zyg[4])); };
  2307. handlers["getslot"] = delegate(NamProcessor th, object[] zyg) {
  2308. Type ty = namtype(zyg[3]);
  2309. CpsOp scope = (zyg[1] is object[]) ? th.Scan(zyg[1]) :
  2310. th.cpb.eu.TypeConstant(th.ResolvePkg(JScalar.S(zyg[1])));
  2311. return CpsOp.UnboxAny(ty, CpsOp.MethodCall(Tokens.P6any_GetSlot,
  2312. th.Scan(zyg[4]), scope, th.AnyStr(zyg[2]))); };
  2313. handlers["cast"] = delegate(NamProcessor th, object[] zyg) {
  2314. Type tty = namtype(zyg[1]);
  2315. CpsOp z = th.Scan(zyg[2]);
  2316. Type fty = z.head.Returns;
  2317. if (tty == Tokens.Frame && fty == Tokens.P6any
  2318. || tty == Tokens.Cursor && fty == Tokens.P6any) {
  2319. return CpsOp.UnboxAny(tty, z);
  2320. } else if (tty == Tokens.Double && fty == Tokens.Int32) {
  2321. return CpsOp.Operator(tty, OpCodes.Conv_R8, z);
  2322. } else if (tty == Tokens.Int32 && fty == Tokens.Double) {
  2323. return CpsOp.Operator(tty, OpCodes.Conv_I4, z);
  2324. } else if (fty == Tokens.Boolean && tty == Tokens.Int32) {
  2325. return CpsOp.Widen(tty, z);
  2326. } else {
  2327. throw new NotImplementedException("cast " + fty + " -> " + tty);
  2328. }
  2329. };
  2330. handlers["die"] = delegate(NamProcessor th, object[] zyg) {
  2331. if (!(zyg[1] is object[])) {
  2332. return CpsOp.CpsCall(Tokens.Variable, Tokens.Kernel_Die,
  2333. CpsOp.StringLiteral(FixStr(zyg[1])));
  2334. } else {
  2335. return CpsOp.CpsCall(Tokens.Variable, Tokens.Kernel_SFH,
  2336. CpsOp.IntLiteral(SubInfo.ON_DIE),
  2337. CpsOp.Null(Tokens.Frame), CpsOp.IntLiteral(-1),
  2338. CpsOp.Null(Tokens.String), th.Scan(zyg[1]));
  2339. }
  2340. };
  2341. handlers["control"] = delegate(NamProcessor th, object[] zyg) {
  2342. if (zyg[1] is object[]) goto dynamic;
  2343. if (JScalar.S(((object[])zyg[2])[0]) != "null") goto dynamic;
  2344. if (JScalar.S(((object[])zyg[3])[0]) != "int") goto dynamic;
  2345. if (JScalar.S(((object[])zyg[4])[0]) != "null") goto dynamic;
  2346. {
  2347. int type = JScalar.I(zyg[1]);
  2348. string lbl = null;
  2349. for (int i = th.eh_stack.Count - 1; i >= 0; i--)
  2350. foreach (ClrEhSpan ces in th.eh_stack[i])
  2351. if (ces.kls == type) {
  2352. lbl = ces.lg;
  2353. goto found;
  2354. }
  2355. goto dynamic;
  2356. found:
  2357. return CpsOp.GotoReturn(lbl, th.Scan(zyg[5]));
  2358. }
  2359. dynamic:
  2360. CpsOp[] z = new CpsOp[5];
  2361. for (int i = 1; i < 5; i++)
  2362. z[i] = th.Scan(zyg[i+1]);
  2363. z[0] = zyg[1] is object[] ? th.Scan(zyg[1]) :
  2364. CpsOp.IntLiteral(FixInt(zyg[1]));
  2365. return CpsOp.CpsCall(Tokens.Variable, Tokens.Kernel_SFH, z);
  2366. };
  2367. handlers["comma"] = delegate(NamProcessor th, object[] zyg) {
  2368. return CpsOp.MethodCall(Tokens.Kernel_NewRWListVar,
  2369. CpsOp.MethodCall(Tokens.Kernel.GetMethod("BoxRaw").MakeGenericMethod(Tokens.FVarList),
  2370. CpsOp.NewArray(Tokens.Variable, JScalar.A<CpsOp>(1, zyg, th.Scan)),
  2371. th.cpb.eu.TypeConstant(th.sub.setting.ParcelMO)));
  2372. };
  2373. handlers["makejunction"] = delegate(NamProcessor th, object[] zyg) {
  2374. return CpsOp.MethodCall(
  2375. Tokens.Builtins.GetMethod("MakeJunction"),
  2376. CpsOp.Constants(),
  2377. CpsOp.IntLiteral(JScalar.I(zyg[1])),
  2378. CpsOp.NewArray(Tokens.Variable, JScalar.A<CpsOp>(2, zyg, th.Scan)));
  2379. };
  2380. handlers["box"] = delegate(NamProcessor th, object[] zyg) {
  2381. CpsOp mo;
  2382. if (!(zyg[1] is object[])) {
  2383. STable real_mo;
  2384. string name = FixStr(zyg[1]);
  2385. // these might need to happen *early*, before user classes
  2386. // are set up
  2387. if (name == "Str") {
  2388. real_mo = th.sub.setting.StrMO;
  2389. } else if (name == "Num") {
  2390. real_mo = th.sub.setting.NumMO;
  2391. } else {
  2392. int dummy;
  2393. LexInfo li = th.ResolveLex(name,false,out dummy,true);
  2394. if (li == null)
  2395. throw new NieczaException("Cannot resolve package " + name);
  2396. real_mo = (li as LIPackage).pkg;
  2397. }
  2398. mo = th.cpb.eu.TypeConstant(real_mo);
  2399. } else {
  2400. mo = CpsOp.GetField(Tokens.P6any_mo, th.Scan(zyg[1]));
  2401. }
  2402. CpsOp boxee = th.Scan(zyg[2]);
  2403. return CpsOp.MethodCall(Tokens.Kernel.GetMethod("BoxAnyMO").MakeGenericMethod(boxee.head.Returns), boxee, mo);
  2404. };
  2405. handlers["unbox"] = delegate(NamProcessor th, object[] zyg) {
  2406. Type t = namtype(zyg[1]);
  2407. CpsOp unboxee = th.Scan(zyg[2]);
  2408. if (unboxee.head.Returns == Tokens.Variable)
  2409. unboxee = CpsOp.MethodCall(Tokens.Variable_Fetch, unboxee);
  2410. return CpsOp.MethodCall(Tokens.Kernel.GetMethod("UnboxAny").MakeGenericMethod(t), unboxee);
  2411. };
  2412. handlers["newboundvar"] = delegate(NamProcessor th, object[] zyg) {
  2413. CpsOp typ = th.Scan(zyg[3]);
  2414. CpsOp rhs = th.Scan(zyg[4]);
  2415. int ro = JScalar.B(zyg[1]) ? 0 : Kernel.NBV_RW;
  2416. int mode = JScalar.B(zyg[2]) ? Kernel.NBV_LIST : ro; // ignore RW if LIST
  2417. return CpsOp.MethodCall(Tokens.Kernel_NewBoundVar,
  2418. CpsOp.IntLiteral(mode), typ, rhs);
  2419. };
  2420. handlers["whileloop"] = delegate(NamProcessor th, object[] z) {
  2421. return CpsOp.While(FixBool(z[1]), FixBool(z[2]),
  2422. th.Scan(z[3]), th.Scan(z[4])); };
  2423. thandlers["_pushleave"] = Methody(null, Tokens.Frame.GetMethod("PushLeave"));
  2424. handlers["_makesub"] = delegate(NamProcessor th, object[] z) {
  2425. return CpsOp.MethodCall(Tokens.Kernel_MakeSub,
  2426. EmitUnit.Current.SubConstant((SubInfo)z[1]),
  2427. CpsOp.CallFrame()); };
  2428. handlers["_newlabel"] = delegate(NamProcessor th, object[] z) {
  2429. return CpsOp.MethodCall(Tokens.Kernel_NewLabelVar,
  2430. CpsOp.CallFrame(),
  2431. CpsOp.StringLiteral(JScalar.S(z[1]))); };
  2432. handlers["_cpsop"] = delegate(NamProcessor th, object[] z) {
  2433. return z[1] as CpsOp; };
  2434. handlers["_newdispatch"] = delegate(NamProcessor th, object[] z) {
  2435. return th.MakeDispatch(JScalar.S(z[1])); };
  2436. thandlers["_binder"] = Methody(Tokens.Void, Tokens.Frame_Binder);
  2437. handlers["class_ref"] = delegate(NamProcessor th, object[] z) {
  2438. string kind = FixStr(z[1]);
  2439. STable m;
  2440. if (z[2] is STable) {
  2441. m = (STable)z[2];
  2442. } else {
  2443. m = th.ResolvePkg(JScalar.S(z[2]));
  2444. }
  2445. if (kind == "mo")
  2446. return th.cpb.eu.TypeConstant(m);
  2447. if (kind == "typeObj")
  2448. return th.cpb.eu.TypeConstantP(m);
  2449. throw new NotImplementedException("class_ref " + kind);
  2450. };
  2451. handlers["methodcall"] = delegate (NamProcessor th, object[] zyg) {
  2452. return th.SubyCall(true, zyg); };
  2453. handlers["subcall"] = delegate (NamProcessor th, object[] zyg) {
  2454. return th.SubyCall(false, zyg); };
  2455. handlers["letn"] = delegate(NamProcessor th, object[] zyg) {
  2456. int i = 1;
  2457. Dictionary<string,Type> old =
  2458. new Dictionary<string,Type>(th.let_types);
  2459. List<KeyValuePair<string,CpsOp>> lvec =
  2460. new List<KeyValuePair<string,CpsOp>>();
  2461. while (zyg.Length - i >= 3 && !(zyg[i] is object[])) {
  2462. string name = FixStr(zyg[i]);
  2463. CpsOp init = th.Scan(zyg[i+1]);
  2464. th.let_types[name] = init.head.Returns;
  2465. lvec.Add(new KeyValuePair<string,CpsOp>(name, init));
  2466. i += 2;
  2467. }
  2468. List<CpsOp> rest = new List<CpsOp>();
  2469. while (i < zyg.Length)
  2470. rest.Add(th.Scan(zyg[i++]));
  2471. CpsOp bit = CpsOp.Sequence(rest.ToArray());
  2472. for (int j = lvec.Count - 1; j >= 0; j--)
  2473. bit = CpsOp.Let(lvec[j].Key, lvec[j].Value, bit);
  2474. th.let_types = old;
  2475. return bit;
  2476. };
  2477. handlers["newcc"] = delegate(NamProcessor th, object[] z) {
  2478. int[] vec = new int[z.Length - 1];
  2479. for (int i = 0; i < vec.Length; i++)
  2480. vec[i] = FixInt(z[i+1]);
  2481. return CpsOp.ConstructorCall(Tokens.CC_ctor,
  2482. CpsOp.NewIntArray(Tokens.Int32, vec));
  2483. };
  2484. handlers["rxpushcapture"] = delegate(NamProcessor th, object[] z) {
  2485. CpsOp strs = th.cpb.eu.StringListConst(JScalar.SA(2,z));
  2486. return CpsOp.MethodCall(Tokens.RxFrame_PushCapture,
  2487. CpsOp.RxFrame(), strs, th.Scan(z[1]));
  2488. };
  2489. handlers["rxincorpshift"] = delegate(NamProcessor th, object[] z) {
  2490. CpsOp strs = th.cpb.eu.StringListConst(JScalar.SA(0,z[1]));
  2491. return CpsOp.Goto("backtrack", true,
  2492. CpsOp.MethodCall(Tokens.RxFrame.GetMethod("IncorpShift"),
  2493. CpsOp.RxFrame(), strs,
  2494. CpsOp.LabelId(th.cpb.cx, JScalar.S(z[2]))));
  2495. };
  2496. handlers["rxincorpcut"] = delegate(NamProcessor th, object[] z) {
  2497. CpsOp strs = th.cpb.eu.StringListConst(JScalar.SA(0,z[1]));
  2498. return CpsOp.Goto("backtrack", true,
  2499. CpsOp.MethodCall(Tokens.RxFrame.GetMethod("IncorpCut"),
  2500. CpsOp.RxFrame(), strs, CpsOp.IntLiteral(
  2501. JScalar.I(z[2]) * RxFrame.IC_ZERO_WIDTH +
  2502. JScalar.I(z[3]) * RxFrame.IC_NEGATIVE),
  2503. th.Scan(z[4])));
  2504. };
  2505. handlers["rxbprim"] = delegate(NamProcessor th, object[] z) {
  2506. CpsOp[] args = new CpsOp[z.Length - 1];
  2507. for(int i = 0; i < z.Length - 2; i++)
  2508. args[i+1] = th.Scan(z[i+2]);
  2509. args[0] = CpsOp.RxFrame();
  2510. CpsOp call = CpsOp.MethodCall(
  2511. Tokens.RxFrame.GetMethod(FixStr(z[1])), args);
  2512. return CpsOp.Goto("backtrack", true, call);
  2513. };
  2514. handlers["rxlprim"] = delegate(NamProcessor th, object[] z) {
  2515. CpsOp[] args = new CpsOp[z.Length - 1];
  2516. for(int i = 0; i < z.Length - 2; i++)
  2517. args[i+1] = th.Scan(z[i+2]);
  2518. args[0] = CpsOp.RxFrame();
  2519. return CpsOp.CpsCall(Tokens.Variable,
  2520. Tokens.RxFrame.GetMethod(FixStr(z[1])), args);
  2521. };
  2522. handlers["const"] = delegate(NamProcessor th, object[] z) {
  2523. object[] ch = z[1] as object[];
  2524. if (ch == null) {
  2525. return th.cpb.eu.RefConstant("", "", z[1], null);
  2526. }
  2527. string chh = JScalar.S(ch[0]);
  2528. if (chh == "exactnum") {
  2529. return th.cpb.eu.VarConstExact(JScalar.I(ch[1]),
  2530. JScalar.S(ch[2]));
  2531. } else if (chh == "box" && !(ch[1] is object[])) {
  2532. string typ = JScalar.S(ch[1]);
  2533. object[] chch = ch[2] as object[];
  2534. string chchh = JScalar.S(chch[0]);
  2535. if (typ == "Str" && chchh == "str") {
  2536. return th.cpb.eu.VarConstStr(JScalar.S(chch[1]));
  2537. } else if (typ == "Num" && chchh == "double") {
  2538. return th.cpb.eu.VarConstNum(JScalar.N(chch[1]));
  2539. } else {
  2540. Console.WriteLine("odd constant box {0}/{1}", typ, chchh);
  2541. }
  2542. } else if (chh == "newcc") {
  2543. return th.cpb.eu.CCConst(JScalar.IA(1, ch));
  2544. } else if (chh == "fcclist_new") {
  2545. int[][] ccl = new int[ch.Length - 1][];
  2546. for (int i = 1; i < ch.Length; i++)
  2547. ccl[i-1] = JScalar.IA(1, ch[i]);
  2548. return th.cpb.eu.CCListConst(ccl);
  2549. } else {
  2550. Console.WriteLine("odd constant {0}", chh);
  2551. }
  2552. return th.Scan(z[1]);
  2553. };
  2554. handlers["sc_root"] = delegate(NamProcessor th, object[] z) {
  2555. return CpsOp.ConstructorCall(Tokens.SC_ctor,
  2556. CpsOp.CallFrame(), CpsOp.IntLiteral(
  2557. th.scope_stack.Count));
  2558. };
  2559. thandlers["sc_indir"] = Methody(null, Tokens.StashCursor.GetMethod("Indirect"));
  2560. thandlers["return"] = CpsOp.CpsReturn;
  2561. thandlers["ternary"] = delegate(CpsOp[] z) {
  2562. return CpsOp.Ternary(z[0], z[1], z[2]); };
  2563. thandlers["sink"] = delegate(CpsOp[] z) {
  2564. return CpsOp.Sink(z[0]); };
  2565. thandlers["callframe"] = delegate(CpsOp[] z) { return CpsOp.CallFrame(); };
  2566. thandlers["fvarlist_new"] = delegate(CpsOp[] z) {
  2567. return CpsOp.NewArray(Tokens.Variable, z); };
  2568. thandlers["fcclist_new"] = delegate(CpsOp[] z) {
  2569. return CpsOp.NewArray(Tokens.CC, z); };
  2570. thandlers["setbox"] = delegate(CpsOp[] z) {
  2571. MethodInfo mi = typeof(Kernel).GetMethod("SetBox").MakeGenericMethod(z[1].head.Returns);
  2572. return CpsOp.MethodCall(mi, z); };
  2573. // yuck.
  2574. thandlers["mrl_count"] = thandlers["fvarlist_length"] = delegate(CpsOp[] z) {
  2575. return CpsOp.Operator(Tokens.Int32, OpCodes.Conv_I4,
  2576. CpsOp.Operator(Tokens.IntPtr, OpCodes.Ldlen, z));
  2577. };
  2578. handlers["_newoftype"] = delegate(NamProcessor th, object[] z) {
  2579. return CpsOp.MethodCall(Tokens.Kernel_NewTypedScalar,
  2580. (CpsOp)z[1]); };
  2581. thandlers["newblankrwscalar"] = delegate(CpsOp[] z) {
  2582. return CpsOp.MethodCall(Tokens.Kernel_NewMuAnyScalar, CpsOp.CallFrame()); };
  2583. // XXX - wrong order - problem?
  2584. thandlers["fvarlist_item"] = delegate(CpsOp[] z) {
  2585. return CpsOp.Operator(Tokens.Variable, OpCodes.Ldelem_Ref,
  2586. z[1], z[0]); };
  2587. thandlers["mrl_index"] = delegate(CpsOp[] z) {
  2588. return CpsOp.Operator(Tokens.P6any, OpCodes.Ldelem_Ref,
  2589. z[1], z[0]); };
  2590. thandlers["vvarlist_item"] = delegate(CpsOp[] z) {
  2591. return CpsOp.MethodCall(Tokens.VVarList_Item, z[1], z[0]); };
  2592. thandlers["varhash_getindex"] = delegate(CpsOp[] z) {
  2593. return CpsOp.MethodCall(Tokens.VarHash_get_Item, z[1], z[0]); };
  2594. thandlers["varhash_setindex"] = delegate(CpsOp[] z) {
  2595. return CpsOp.MethodCall(Tokens.VarHash_set_Item,
  2596. z[1], z[0], z[2]); };
  2597. thandlers["vvarlist_sort"] = delegate(CpsOp[] z) {
  2598. return CpsOp.MethodCall(Tokens.Kernel_SortHelper,
  2599. CpsOp.CallFrame(), z[0], z[1]); };
  2600. thandlers["make"] = delegate(CpsOp[] z) {
  2601. return CpsOp.MethodCall(Tokens.Builtins_Make,
  2602. CpsOp.CallFrame(), z[0]); };
  2603. thandlers["simple_eval"] = Methody(Tokens.Variable,
  2604. Tokens.Builtins.GetMethod("simple_eval"));
  2605. thandlers["you_are_here"] = Methody(Tokens.Variable,
  2606. Tokens.Builtins.GetMethod("you_are_here"));
  2607. thandlers["callnext"] = Methody(Tokens.Variable,
  2608. Tokens.Builtins.GetMethod("CallNext"));
  2609. handlers["context_get"] = delegate(NamProcessor th, object[] z) {
  2610. string name = JScalar.S(z[1]);
  2611. int outer = JScalar.I(z[2]);
  2612. CpsOp r1 = th.CheckScopes(name, ref outer, null);
  2613. if (r1 != null) return r1;
  2614. LexInfo l;
  2615. if (outer == 0 && th.sub.dylex.TryGetValue(name, out l))
  2616. return CpsOp.LexAccess(l, 0, new CpsOp[0]);
  2617. return CpsOp.MethodCall(Tokens.Kernel_ContextHelper,
  2618. CpsOp.CallFrame(), CpsOp.StringLiteral(name),
  2619. CpsOp.IntLiteral(outer)); };
  2620. thandlers["set_status"] = delegate(CpsOp[] z) {
  2621. return CpsOp.MethodCall( Tokens.Kernel_SetStatus,
  2622. CpsOp.CallFrame(), z[0], z[1]); };
  2623. thandlers["newrwlistvar"] = Methody(null, Tokens.Kernel_NewRWListVar);
  2624. thandlers["iter_hasflat"] = delegate(CpsOp[] z) {
  2625. return CpsOp.MethodCall(Tokens.Kernel_IterHasFlat,
  2626. z[0], CpsOp.BoolLiteral(true)); };
  2627. thandlers["iter_hasarg"] = delegate(CpsOp[] z) {
  2628. return CpsOp.MethodCall(Tokens.Kernel_IterHasFlat,
  2629. z[0], CpsOp.BoolLiteral(false)); };
  2630. thandlers["map"] = delegate(CpsOp[] z) {
  2631. return CpsOp.CpsCall(Tokens.Variable, Tokens.Builtins_MEMap,
  2632. CpsOp.NewArray(Tokens.Variable, z)); };
  2633. thandlers["grep"] = delegate(CpsOp[] z) {
  2634. return CpsOp.CpsCall(Tokens.Variable, Tokens.Builtins_MEGrep,
  2635. CpsOp.NewArray(Tokens.Variable, z)); };
  2636. handlers["newrwscalar"] = delegate(NamProcessor th, object[] z) {
  2637. return CpsOp.MethodCall(Tokens.Kernel_NewRWScalar,
  2638. th.cpb.eu.TypeConstant(th.sub.setting.AnyMO), th.Scan(z[1])); };
  2639. thandlers["newvsubvar"] = delegate(CpsOp[] z) {
  2640. return CpsOp.ConstructorCall(Tokens.SV_ctor, z[0],
  2641. CpsOp.ConstructorCall(Tokens.SubViviHook_ctor,
  2642. z[1]), z[2]); };
  2643. thandlers["strbuf_append"] = delegate(CpsOp[] z) {
  2644. return CpsOp.Sink(CpsOp.MethodCall(Tokens.StringBuilder_Append_String, z)); };
  2645. thandlers["varhash_delete_key"] = delegate(CpsOp[] z) {
  2646. return CpsOp.Sink(CpsOp.MethodCall(Tokens.VarHash_Remove, z)); };
  2647. thandlers["note"] = delegate(CpsOp[] z) {
  2648. return CpsOp.MethodCall(Tokens.TW_WriteLine,
  2649. CpsOp.MethodCall(Tokens.Console_get_Error), z[0]); };
  2650. ConstructorInfo string_ctor = Tokens.String.GetConstructor(new Type[] {
  2651. typeof(char), Tokens.Int32 });
  2652. thandlers["str_chr"] = delegate(CpsOp[] z) {
  2653. return CpsOp.ConstructorCall(string_ctor,
  2654. CpsOp.Operator(typeof(char), OpCodes.Conv_U2, z),
  2655. CpsOp.IntLiteral(1));
  2656. };
  2657. MethodInfo itcommon = Tokens.Builtins.GetMethod("HashIter");
  2658. thandlers["hash_keys"] = delegate(CpsOp[] z) {
  2659. return CpsOp.MethodCall(itcommon, CpsOp.IntLiteral(0), z[0]); };
  2660. thandlers["hash_values"] = delegate(CpsOp[] z) {
  2661. return CpsOp.MethodCall(itcommon, CpsOp.IntLiteral(1), z[0]); };
  2662. thandlers["hash_kv"] = delegate(CpsOp[] z) {
  2663. return CpsOp.MethodCall(itcommon, CpsOp.IntLiteral(2), z[0]); };
  2664. thandlers["hash_pairs"] = delegate(CpsOp[] z) {
  2665. return CpsOp.MethodCall(itcommon, CpsOp.IntLiteral(3), z[0]); };
  2666. Func<CpsOp[], CpsOp> real_pushcut = RxCall(null, "PushCutGroup");
  2667. handlers["pushcut"] = delegate(NamProcessor th, object[] z) {
  2668. return real_pushcut(new CpsOp[] { CpsOp.StringLiteral(FixStr(z[1])) }); };
  2669. thandlers["rxframe"] = delegate(CpsOp[] z) {
  2670. return CpsOp.RxFrame(); };
  2671. handlers["rxcall"] = delegate(NamProcessor th, object[] z) {
  2672. CpsOp[] x = new CpsOp[z.Length - 1];
  2673. for (int i = 2; i < z.Length; i++)
  2674. x[i-1] = th.Scan(z[i]);
  2675. x[0] = CpsOp.RxFrame();
  2676. string name = JScalar.S(z[1]);
  2677. return CpsOp.CpsCall((name == "EndWith" ? Tokens.Void : null),
  2678. Tokens.RxFrame.GetMethod(name), x); };
  2679. handlers["rxinit"] = delegate(NamProcessor th, object[] z) {
  2680. return CpsOp.SetField(Tokens.Frame_rx, CpsOp.CallFrame(),
  2681. CpsOp.ConstructorCall(Tokens.RxFrame_ctor,
  2682. th.Scan(z[1]), th.Scan(z[2]),
  2683. CpsOp.BoolLiteral(FixBool(z[3])))); };
  2684. handlers["rxpushb"] = delegate(NamProcessor th, object[] z) {
  2685. return CpsOp.MethodCall(Tokens.RxFrame_PushBacktrack,
  2686. CpsOp.RxFrame(),
  2687. CpsOp.LabelId(th.cpb.cx, JScalar.S(z[2]))); };
  2688. handlers["ltm_push_alts"] = delegate(NamProcessor th, object[] z) {
  2689. LAD[] prefixes = JScalar.A<LAD>(0, z[1],
  2690. DowncallReceiver.BuildLadJ);
  2691. AltInfo ai = new AltInfo(prefixes, JScalar.S(z[2]), null);
  2692. th.altinfo_fixups.Add(new KeyValuePair<AltInfo,string[]>(
  2693. ai, JScalar.SA(0, z[3])));
  2694. CpsOp aic = th.cpb.eu.RefConstant(ai.dba, "", ai, null);
  2695. return CpsOp.MethodCall(Tokens.RxFrame.GetMethod("LTMPushAlts"),
  2696. CpsOp.RxFrame(), CpsOp.CallFrame(), aic); };
  2697. thandlers["popcut"] = RxCall(null, "PopCutGroup");
  2698. thandlers["rxend"] = delegate(CpsOp[] zyg) {
  2699. return CpsOp.Sequence(
  2700. CpsOp.CpsCall(Tokens.Void,
  2701. Tokens.RxFrame.GetMethod("MakeMatch"), CpsOp.RxFrame()),
  2702. CpsOp.CpsCall(Tokens.Void,
  2703. Tokens.RxFrame.GetMethod("End"), CpsOp.RxFrame())); };
  2704. thandlers["rxfinalend"] = delegate(CpsOp[] zyg) {
  2705. return CpsOp.Sequence(
  2706. CpsOp.CpsCall(Tokens.Void,
  2707. Tokens.RxFrame.GetMethod("MakeMatch"), CpsOp.RxFrame()),
  2708. CpsOp.CpsCall(Tokens.Void,
  2709. Tokens.RxFrame.GetMethod("FinalEnd"), CpsOp.RxFrame())); };
  2710. thandlers["rxbacktrack"] = RxCall(Tokens.Void, "Backtrack");
  2711. thandlers["rxgetquant"] = RxCall(null, "GetQuant");
  2712. thandlers["rxsetquant"] = RxCall(null, "SetQuant");
  2713. thandlers["rxopenquant"] = RxCall(null, "OpenQuant");
  2714. thandlers["rxclosequant"] = RxCall(null, "CloseQuant");
  2715. thandlers["rxincquant"] = RxCall(null, "IncQuant");
  2716. thandlers["rxsetclass"] = RxCall(null, "SetClass");
  2717. thandlers["rxsetpos"] = RxCall(null, "SetPos");
  2718. thandlers["rxsetcapsfrom"] = RxCall(null, "SetCapturesFrom");
  2719. thandlers["rxgetpos"] = RxCall(null, "GetPos");
  2720. thandlers["rxcommitgroup"] = RxCall(null, "CommitGroup");
  2721. handlers["rawcall"] = delegate(NamProcessor th, object[] z) {
  2722. string name = JScalar.S(z[1]);
  2723. CpsOp[] rst = JScalar.A<CpsOp>(2, z, th.Scan);
  2724. Type[] tx = new Type[rst.Length - 1];
  2725. for (int i = 0; i < tx.Length; i++)
  2726. tx[i] = rst[i+1].head.Returns;
  2727. MethodInfo mi = rst[0].head.Returns.GetMethod(name, tx);
  2728. return CpsOp.MethodCall(mi, rst); };
  2729. handlers["rawscall"] = delegate(NamProcessor th, object[] z) {
  2730. string name = JScalar.S(z[1]);
  2731. int ixn = name.LastIndexOf(':');
  2732. Type cpsrt = null;
  2733. if (ixn >= 0) {
  2734. cpsrt = Type.GetType(name.Substring(ixn+1));
  2735. name = name.Substring(0, ixn);
  2736. }
  2737. int ix = name.LastIndexOf('.');
  2738. CpsOp[] rst = JScalar.A<CpsOp>(2, z, th.Scan);
  2739. int k = (cpsrt != null) ? 1 : 0;
  2740. Type[] tx = new Type[rst.Length + k];
  2741. for (int i = 0; i < rst.Length; i++)
  2742. tx[i+k] = rst[i].head.Returns;
  2743. if (cpsrt != null) tx[0] = Tokens.Frame;
  2744. MethodInfo mi = Type.GetType(name.Substring(0, ix))
  2745. .GetMethod(name.Substring(ix+1), tx);
  2746. return CpsOp.CpsCall(cpsrt, mi, JScalar.A<CpsOp>(2, z, th.Scan)); };
  2747. thandlers["var_islist"] = Methody(null, Tokens.Variable.GetMethod("get_List"));
  2748. thandlers["var_is_rw"] = Methody(null, Tokens.Variable.GetMethod("get_Rw"));
  2749. thandlers["llhow_name"] = FieldGet(Tokens.STable, "name");
  2750. thandlers["stab_what"] = FieldGet(Tokens.STable, "typeObj");
  2751. thandlers["obj_llhow"] = FieldGet(Tokens.P6any, "mo");
  2752. thandlers["varhash_clear"] = Methody(null, Tokens.VarHash.GetMethod("Clear"));
  2753. thandlers["varhash_new"] = Constructy(Tokens.VarHash.GetConstructor(new Type[0]));
  2754. thandlers["varhash_dup"] = Constructy(Tokens.VarHash.GetConstructor(new Type[]{ Tokens.VarHash }));
  2755. thandlers["varhash_contains_key"] = Methody(null, Tokens.VarHash.GetMethod("ContainsKey"));
  2756. thandlers["num_to_string"] = Methody(null, typeof(Utils).GetMethod("N2S"));
  2757. thandlers["str_length"] = Methody(null, Tokens.String.GetMethod("get_Length"));
  2758. thandlers["str_tonum"] = Methody(null, typeof(Utils).GetMethod("S2N"));
  2759. thandlers["str_substring"] = Methody(null, Tokens.Builtins.GetMethod("LaxSubstring2"));
  2760. thandlers["str_tolower"] = Methody(null, Tokens.String.GetMethod("ToLowerInvariant"));
  2761. thandlers["str_toupper"] = Methody(null, Tokens.String.GetMethod("ToUpperInvariant"));
  2762. thandlers["str_flip"] = Methody(null, typeof(Utils).GetMethod("StrFlip"));
  2763. thandlers["strcmp"] = Methody(null, Tokens.String.GetMethod("CompareOrdinal", new Type[] { Tokens.String, Tokens.String }));
  2764. thandlers["strbuf_new"] = Constructy(typeof(StringBuilder).GetConstructor(new Type[0]));
  2765. thandlers["strbuf_seal"] = Methody(null, Tokens.Object_ToString);
  2766. thandlers["say"] = Methody(null, Tokens.Console_WriteLine);
  2767. thandlers["print"] = Methody(null, Tokens.Console_Write);
  2768. thandlers["slurp"] = Methody(null, typeof(File).GetMethod("ReadAllText", new Type[] { Tokens.String }));
  2769. thandlers["spurt"] = Methody(null, typeof(File).GetMethod("WriteAllText", new Type[] { Tokens.String, Tokens.String }));
  2770. thandlers["vvarlist_to_fvarlist"] = Methody(null, Tokens.VVarList.GetMethod("CopyAsArray"));
  2771. thandlers["vvarlist_shift"] = Methody(null, Tokens.VVarList.GetMethod("Shift"));
  2772. thandlers["vvarlist_pop"] = Methody(null, Tokens.VVarList.GetMethod("Pop"));
  2773. thandlers["vvarlist_count"] = Methody(null, Tokens.VVarList.GetMethod("Count"));
  2774. thandlers["vvarlist_unshift"] = Methody(null, Tokens.VVarList.GetMethod("Unshift"));
  2775. thandlers["vvarlist_unshiftn"] = Methody(null, Tokens.VVarList.GetMethod("UnshiftN"));
  2776. thandlers["vvarlist_append"] = Methody(null, Tokens.VVarList.GetMethod("PushD"));
  2777. thandlers["vvarlist_push"] = Methody(null, Tokens.VVarList.GetMethod("Push"));
  2778. thandlers["vvarlist_new_empty"] = Constructy(Tokens.VVarList.GetConstructor(new Type[] { }));
  2779. thandlers["vvarlist_new_singleton"] = Constructy(Tokens.VVarList.GetConstructor(new Type[] { Tokens.Variable }));
  2780. thandlers["vvarlist_from_fvarlist"] = Constructy(Tokens.VVarList.GetConstructor(new Type[] { Tokens.FVarList }));
  2781. thandlers["vvarlist_clone"] = Constructy(Tokens.VVarList.GetConstructor(new Type[] { Tokens.VVarList }));
  2782. thandlers["stab_privatemethod"] = Methody(null, Tokens.STable.GetMethod("GetPrivateMethod"));
  2783. thandlers["path_file_exists"] = Methody(null, typeof(File).GetMethod("Exists"));
  2784. thandlers["path_dir_exists"] = Methody(null, typeof(Directory).GetMethod("Exists"));
  2785. thandlers["path_get_directory_name"] = Methody(null, typeof(Path).GetMethod("GetDirectoryName", new Type[] { Tokens.String }));
  2786. thandlers["path_get_file_name"] = Methody(null, typeof(Path).GetMethod("GetFileName", new Type[] { Tokens.String }));
  2787. thandlers["path_combine"] = Methody(null, typeof(Path).GetMethod("Combine", new Type[] { Tokens.String, Tokens.String }));
  2788. thandlers["path_change_ext"] = Methody(null, typeof(Path).GetMethod("ChangeExtension", new Type[] { Tokens.String, Tokens.String }));
  2789. thandlers["path_realpath"] = Methody(null, typeof(Path).GetMethod("GetFullPath"));
  2790. handlers["_addmethod"] = delegate(NamProcessor th, object[] z) {
  2791. return CpsOp.MethodCall(Tokens.DMO_AddMethod, th.Scan(z[1]), CpsOp.IntLiteral(JScalar.I(z[2])), th.Scan(z[3]), th.Scan(z[4])); };
  2792. thandlers["_invalidate"] = Methody(null, Tokens.STable.GetMethod("Invalidate"));
  2793. handlers["do_require"] = delegate(NamProcessor th, object[] z) {
  2794. return CpsOp.MethodCall(Tokens.Kernel.GetMethod("DoRequire"),
  2795. CpsOp.StringLiteral(JScalar.S(z[1]))); };
  2796. thandlers["obj_is_defined"] = Methody(null, Tokens.P6any.GetMethod("IsDefined"));
  2797. thandlers["how"] = Methody(Tokens.P6any, Tokens.P6any.GetMethod("HOW"));
  2798. thandlers["obj_what"] = Methody(null, Tokens.P6any.GetMethod("GetTypeObject"));
  2799. thandlers["obj_isa"] = Methody(null, Tokens.P6any.GetMethod("Isa"));
  2800. thandlers["obj_does"] = Methody(null, Tokens.P6any.GetMethod("Does"));
  2801. thandlers["obj_newblank"] = Constructy(Tokens.P6opaque_ctor);
  2802. thandlers["cursor_pos"] = FieldGet(Tokens.Cursor, "pos");
  2803. thandlers["cursor_from"] = FieldGet(Tokens.Cursor, "from");
  2804. thandlers["cursor_butpos"] = Methody(null, Tokens.Cursor.GetMethod("At"));
  2805. thandlers["cursor_backing"] = Methody(null, Tokens.Cursor.GetMethod("GetBacking"));
  2806. thandlers["cursor_ast"] = Methody(null, Tokens.Cursor.GetMethod("AST"));
  2807. thandlers["cursor_dows"] = Methody(null, Tokens.Cursor.GetMethod("SimpleWS"));
  2808. thandlers["cursor_item"] = Methody(null, Tokens.Cursor.GetMethod("GetKey"));
  2809. thandlers["cursor_unpackcaps"] = Methody(null, Tokens.Cursor.GetMethod("UnpackCaps"));
  2810. thandlers["cursor_O"] = Methody(null, Tokens.Cursor.GetMethod("O"));
  2811. thandlers["cursor_synthetic"] = Methody(Tokens.Void, Tokens.Cursor.GetMethod("Synthetic"));
  2812. thandlers["cursor_fresh"] = Methody(null, Tokens.Cursor.GetMethod("FreshClass"));
  2813. thandlers["cursor_unmatch"] = Methody(null, Tokens.Cursor.GetMethod("UnMatch"));
  2814. thandlers["cursor_reduced"] = Methody(null, Tokens.Cursor.GetMethod("Reduced"));
  2815. thandlers["rxstripcaps"] = Methody(null, Tokens.Cursor.GetMethod("StripCaps"));
  2816. thandlers["prog"] = CpsOp.Sequence;
  2817. thandlers["shift"] = Contexty("mro_shift");
  2818. thandlers["pop"] = Contexty("mro_pop");
  2819. thandlers["push"] = Pushy("mro_push");
  2820. thandlers["unshift"] = Pushy("mro_unshift");
  2821. thandlers["defined"] = Contexty("mro_defined");
  2822. thandlers["asbool"] = Contexty("mro_Bool");
  2823. thandlers["num"] = Contexty("mro_Numeric");
  2824. thandlers["asstr"] = Contexty("mro_Str");
  2825. thandlers["item"] = Contexty("mro_item");
  2826. thandlers["list"] = Contexty("mro_list");
  2827. thandlers["hash"] = Contexty("mro_hash");
  2828. thandlers["obj_asdef"] = Contexty("mro_defined");
  2829. thandlers["obj_asbool"] = Contexty("mro_Bool");
  2830. thandlers["obj_asnum"] = Contexty("mro_Numeric");
  2831. thandlers["obj_asstr"] = Contexty("mro_Str");
  2832. thandlers["obj_getbool"] = Contexty("mro_raw_Bool");
  2833. thandlers["obj_getdef"] = Contexty("mro_raw_defined");
  2834. thandlers["obj_getnum"] = Contexty("mro_raw_Numeric");
  2835. thandlers["obj_getstr"] = Contexty("mro_raw_Str");
  2836. thandlers["at_key"] = thandlers["obj_at_key"] = Contexty("mro_at_key");
  2837. thandlers["at_pos"] = thandlers["obj_at_pos"] = Contexty("mro_at_pos");
  2838. thandlers["exists_key"] = thandlers["obj_exists_key"] = Contexty("mro_exists_key");
  2839. thandlers["delete_key"] = thandlers["obj_delete_key"] = Contexty("mro_delete_key");
  2840. thandlers["cross"] = Methody(Tokens.Variable, Tokens.Builtins.GetMethod("MECross"));
  2841. thandlers["zip"] = Methody(Tokens.Variable, Tokens.Builtins.GetMethod("MEZip"));
  2842. thandlers["var_new_tied"] = Constructy(typeof(TiedVariable).GetConstructor(new Type[] { Tokens.P6any, Tokens.P6any, Tokens.P6any }));
  2843. thandlers["obj_typename"] = Methody(null, Tokens.P6any.GetMethod("GetTypeName"));
  2844. thandlers["fetch"] = Methody(null, Tokens.Variable_Fetch);
  2845. thandlers["default_new"] = delegate(CpsOp[] z) {
  2846. return CpsOp.Sequence(
  2847. CpsOp.Label("!again", false),
  2848. CpsOp.CpsCall(Tokens.Void, Tokens.Kernel.GetMethod("DefaultNew"), z),
  2849. CpsOp.Goto("!again", false),
  2850. CpsOp.Null(Tokens.Variable));
  2851. };
  2852. thandlers["assign"] = Methody(null, Tokens.Kernel_Assign);
  2853. thandlers["cotake"] = Methody(Tokens.Variable, Tokens.Kernel.GetMethod("CoTake"));
  2854. thandlers["take"] = Methody(Tokens.Variable, Tokens.Kernel.GetMethod("Take"));
  2855. thandlers["startgather"] = Methody(Tokens.Frame, Tokens.Kernel.GetMethod("GatherHelper"));
  2856. thandlers["get_first"] = Methody(null, Tokens.Kernel.GetMethod("GetFirst"));
  2857. thandlers["promote_to_list"] = Methody(null, Tokens.Kernel.GetMethod("PromoteToList"));
  2858. thandlers["instrole"] = Methody(Tokens.Variable, Tokens.Kernel.GetMethod("InstantiateRole"));
  2859. thandlers["role_apply"] = Methody(null, Tokens.Kernel.GetMethod("RoleApply"));
  2860. thandlers["iter_to_list"] = Methody(null, Tokens.Kernel.GetMethod("IterToList"));
  2861. thandlers["iter_flatten"] = Methody(null, Tokens.Kernel.GetMethod("IterFlatten"));
  2862. thandlers["iter_copy_elems"] = Methody(null, Tokens.Kernel.GetMethod("IterCopyElems"));
  2863. thandlers["frame_caller"] = FieldGet(Tokens.Frame, "caller");
  2864. thandlers["frame_outer"] = FieldGet(Tokens.Frame, "outer");
  2865. thandlers["frame_sub"] = FieldGet(Tokens.Frame, "sub");
  2866. thandlers["frame_args"] = Methody(null, Tokens.Frame.GetMethod("GetArgs"));
  2867. thandlers["frame_dyn_caller"] = Methody(null, Tokens.Frame.GetMethod("DynamicCaller"));
  2868. thandlers["frame_file"] = Methody(null, Tokens.Frame.GetMethod("ExecutingFile"));
  2869. thandlers["frame_line"] = Methody(null, Tokens.Frame.GetMethod("ExecutingLine"));
  2870. thandlers["frame_hint"] = Methody(null, Tokens.Frame.GetMethod("LexicalFind"));
  2871. thandlers["treader_getc"] = Methody(null, typeof(TextReader).GetMethod("Read", new Type[0]));
  2872. thandlers["treader_slurp"] = Methody(null, typeof(TextReader).GetMethod("ReadToEnd"));
  2873. thandlers["treader_getline"] = Methody(null, typeof(TextReader).GetMethod("ReadLine"));
  2874. thandlers["treader_close"] = Methody(null, typeof(TextReader).GetMethod("Close"));
  2875. ConstructorInfo treader_open = typeof(StreamReader).GetConstructor(new Type[1] { Tokens.String });
  2876. thandlers["treader_open"] = delegate(CpsOp[] z) {
  2877. return CpsOp.Widen(typeof(TextReader),
  2878. CpsOp.ConstructorCall(treader_open, z)); };
  2879. ConstructorInfo twriter_open = typeof(StreamWriter).GetConstructor(new Type[1] { Tokens.String });
  2880. thandlers["twriter_open"] = delegate(CpsOp[] z) {
  2881. return CpsOp.Widen(typeof(TextWriter),
  2882. CpsOp.ConstructorCall(twriter_open, z)); };
  2883. ConstructorInfo twriter_append = typeof(StreamWriter).GetConstructor(new Type[2] { Tokens.String, Tokens.Boolean });
  2884. thandlers["twriter_append"] = delegate(CpsOp[] z) {
  2885. return CpsOp.Widen(typeof(TextWriter),
  2886. CpsOp.ConstructorCall(twriter_append, z)); };
  2887. thandlers["twriter_puts"] = Methody(null, typeof(TextWriter).GetMethod("Write", new Type[] { Tokens.String }));
  2888. thandlers["twriter_close"] = Methody(null, typeof(TextWriter).GetMethod("Close"));
  2889. foreach (KeyValuePair<string, Func<CpsOp[], CpsOp>> kv
  2890. in thandlers) {
  2891. handlers[kv.Key] = MakeTotalHandler(kv.Value);
  2892. }
  2893. }
  2894. static Func<CpsOp[], CpsOp> SimpleB(string name) {
  2895. return Methody(null, Tokens.Builtins.GetMethod(name));
  2896. }
  2897. static Func<CpsOp[], CpsOp> Methody(Type cps, MethodInfo mi) {
  2898. if (mi == null) throw new ArgumentException();
  2899. bool implicit_frame = Attribute.IsDefined(mi, typeof(ImplicitFrameAttribute));
  2900. bool implicit_consts = Attribute.IsDefined(mi, typeof(ImplicitConstsAttribute));
  2901. bool force_cps = Attribute.IsDefined(mi, typeof(CpsAttribute));
  2902. ParameterInfo[] pi = mi.GetParameters();
  2903. int paix = pi.Length - 1;
  2904. bool param_array = pi.Length > 0 &&
  2905. Attribute.IsDefined(pi[paix], typeof(ParamArrayAttribute));
  2906. return delegate(CpsOp[] cpses) {
  2907. if (implicit_consts) cpses = Utils.PrependArr(CpsOp.Constants(), cpses);
  2908. if (implicit_frame) cpses = Utils.PrependArr(CpsOp.CallFrame(), cpses);
  2909. if (param_array && (cpses.Length != pi.Length || !pi[paix].ParameterType.IsAssignableFrom(cpses[paix].head.Returns))) {
  2910. CpsOp[] n1 = new CpsOp[pi.Length];
  2911. CpsOp[] n2 = new CpsOp[cpses.Length - paix];
  2912. Array.Copy(cpses, 0, n1, 0, n1.Length - 1);
  2913. Array.Copy(cpses, paix, n2, 0, n2.Length);
  2914. n1[n1.Length - 1] = CpsOp.NewArray(pi[paix].ParameterType.GetElementType(), n2);
  2915. cpses = n1;
  2916. }
  2917. return CpsOp.CpsCall(force_cps ? Tokens.Variable : cps, mi, cpses);
  2918. };
  2919. }
  2920. static Func<CpsOp[], CpsOp> RxCall(Type cps, string name) {
  2921. MethodInfo mi = Tokens.RxFrame.GetMethod(name);
  2922. return delegate(CpsOp[] cpses) {
  2923. CpsOp[] n = new CpsOp[cpses.Length + 1];
  2924. Array.Copy(cpses, 0, n, 1, cpses.Length);
  2925. n[0] = CpsOp.RxFrame();
  2926. return CpsOp.CpsCall(cps, mi, n); };
  2927. }
  2928. static Func<CpsOp[], CpsOp> Constructy(ConstructorInfo mi) {
  2929. return delegate(CpsOp[] cpses) {
  2930. return CpsOp.ConstructorCall(mi, cpses); };
  2931. }
  2932. static Func<CpsOp[], CpsOp> FieldGet(Type t, string name) {
  2933. FieldInfo f = t.GetField(name);
  2934. return delegate(CpsOp[] cpses) {
  2935. return CpsOp.GetField(f, cpses[0]); };
  2936. }
  2937. static Func<CpsOp[], CpsOp> Contexty(string name) {
  2938. FieldInfo f = Tokens.STable.GetField(name);
  2939. MethodInfo g = f.FieldType.GetMethod("Get");
  2940. return delegate(CpsOp[] cpses) {
  2941. return CpsOp.Contexty(f, g, cpses);
  2942. };
  2943. }
  2944. static Func<CpsOp[], CpsOp> Pushy(string name) {
  2945. FieldInfo f = Tokens.STable.GetField(name);
  2946. MethodInfo g = f.FieldType.GetMethod("Invoke");
  2947. return delegate(CpsOp[] cpses) {
  2948. CpsOp[] args = new CpsOp[cpses.Length - 1];
  2949. Array.Copy(cpses, 1, args, 0, args.Length);
  2950. return CpsOp.Contexty(f, g, new CpsOp[2] {
  2951. cpses[0], CpsOp.NewArray(Tokens.Variable, args) });
  2952. };
  2953. }
  2954. static Func<NamProcessor, object[], CpsOp> MakeTotalHandler(
  2955. Func<CpsOp[], CpsOp> real) {
  2956. return delegate (NamProcessor th, object[] zyg) {
  2957. CpsOp[] zco = new CpsOp[zyg.Length - 1];
  2958. for (int i = 0; i < zco.Length; i++)
  2959. zco[i] = th.Scan(zyg[i+1]);
  2960. return real(zco);
  2961. };
  2962. }
  2963. public void MakeBody(object b) {
  2964. cpb.ReserveLex(sub.num_lex_slots);
  2965. cpb.Build(Scan(WrapBody(b)));
  2966. }
  2967. public void FillSubInfo(Type ty, object constTable) {
  2968. MethodInfo m = ty.GetMethod(cpb.mb.Name);
  2969. sub.lines = cpb.cx.lineBuffer.ToArray();
  2970. sub.edata = cpb.cx.ehspanBuffer.ToArray();
  2971. sub.label_names = cpb.cx.ehlabelBuffer.ToArray();
  2972. sub.nspill = cpb.Spills();
  2973. foreach (var kv in altinfo_fixups) {
  2974. kv.Key.labels = new int[kv.Value.Length];
  2975. for (int i = 0; i < kv.Value.Length; i++) {
  2976. kv.Key.labels[i] =
  2977. cpb.cx.named_cases[kv.Value[i]];
  2978. }
  2979. }
  2980. sub.code = (DynBlockDelegate) Delegate.CreateDelegate(
  2981. Tokens.DynBlockDelegate, constTable, m);
  2982. if (sub.protopad != null) {
  2983. sub.protopad.code = sub.code;
  2984. sub.protopad.EnsureSpills(sub.nspill);
  2985. }
  2986. }
  2987. object j(string s) { return s; }
  2988. object[] a(params object[] ax) { return ax; }
  2989. void EnterCode(List<object> frags) {
  2990. List<object> latefrags = new List<object>();
  2991. // Lexpad setup: XXX should be done *before* entry, indeed
  2992. // before the binder, so defaults work right
  2993. foreach (KeyValuePair<string,LexInfo> kv in sub.dylex) {
  2994. if ((sub.special & SubInfo.RUN_ONCE) != 0)
  2995. continue; // we'll just use the static pad
  2996. if (kv.Value is LISub) {
  2997. LISub ls = (LISub) kv.Value;
  2998. frags.Add(a(j("scopedlex"), j(kv.Key),
  2999. a(j("_makesub"), ls.def)));
  3000. } else if (kv.Value is LISimple) {
  3001. LISimple ls = kv.Value as LISimple;
  3002. int f = ls.flags;
  3003. if ((f & LISimple.NOINIT) != 0) continue;
  3004. object bit;
  3005. CpsOp tc = EmitUnit.Current.TypeConstant(ls.type);
  3006. if ((f & LISimple.ROINIT) != 0) {
  3007. bit = a(j("class_ref"), j("typeObj"), sub.setting.AnyMO);
  3008. } else if ((f & LISimple.DEFOUTER) != 0) {
  3009. bit = a(j("outerlex"), j(kv.Key));
  3010. } else if ((f & (LISimple.HASH | LISimple.LIST)) != 0) {
  3011. bit = a(j( ((f & LISimple.HASH) != 0) ?
  3012. "newhash" : "newarray" ));
  3013. } else if (ls.type == null) {
  3014. bit = a(j("newblankrwscalar"));
  3015. } else {
  3016. bit = a(j("_newoftype"), tc);
  3017. }
  3018. frags.Add(a(j("scopedlex"), j(kv.Key), bit));
  3019. } else if (kv.Value is LILabel) {
  3020. frags.Add(a(j("scopedlex"), j(kv.Key),
  3021. a(j("_newlabel"), j(kv.Key))));
  3022. } else if (kv.Value is LIDispatch) {
  3023. latefrags.Add(a(j("scopedlex"), j(kv.Key),
  3024. a(j("_newdispatch"), j(kv.Key))));
  3025. }
  3026. }
  3027. foreach (object lf in latefrags) frags.Add(lf);
  3028. if (sub.sig != null) frags.Add(a(j("_binder")));
  3029. // PRE
  3030. foreach (SubInfo z in sub.GetPhasers(Kernel.PHASER_PRE)) {
  3031. frags.Add(a(j("ternary"),
  3032. a(j("obj_getbool"), a(j("subcall"), j(""),
  3033. a(j("_makesub"), z))),
  3034. a(j("prog")),
  3035. a(j("sink"),a(j("die"),
  3036. j("Precondition failed in " + sub.name)))));
  3037. }
  3038. foreach (SubInfo z in sub.GetPhasers(Kernel.PHASER_POST)) {
  3039. frags.Add(a(j("_pushleave"),
  3040. (sub.phaser == Kernel.PHASER_PRE ?
  3041. a(j("frame_outer"), a(j("callframe"))) :
  3042. a(j("callframe"))),
  3043. a(j("int"), j(LeaveHook.POST.ToString())),
  3044. a(j("_makesub"), z)));
  3045. }
  3046. // includes UNDO and LEAVE
  3047. foreach (SubInfo z in sub.GetPhasers(Kernel.PHASER_KEEP)) {
  3048. int type = z.phaser == Kernel.PHASER_KEEP ? LeaveHook.KEEP :
  3049. z.phaser == Kernel.PHASER_UNDO ? LeaveHook.UNDO :
  3050. LeaveHook.UNDO + LeaveHook.KEEP;
  3051. frags.Add(a(j("_pushleave"), a(j("callframe")),
  3052. a(j("int"), j(type.ToString())),
  3053. a(j("_makesub"), z)));
  3054. }
  3055. foreach (SubInfo z in sub.GetPhasers(Kernel.PHASER_ENTER)) {
  3056. frags.Add(a(j("sink"), a(j("subcall"), j(""),
  3057. a(j("_makesub"), z))));
  3058. }
  3059. }
  3060. object WrapBody(object b) {
  3061. List<object> enter = new List<object>();
  3062. EnterCode(enter);
  3063. List<object> handlers = new List<object>();
  3064. handlers.Add("xspan");
  3065. handlers.Add("tstart");
  3066. handlers.Add("tend");
  3067. handlers.Add("0");
  3068. handlers.Add(b);
  3069. // TODO: bind a ro container around return values
  3070. if (sub.IsTopicalizer()) {
  3071. handlers.Add("6");
  3072. handlers.Add("");
  3073. handlers.Add("tend");
  3074. }
  3075. foreach (KeyValuePair<string,LexInfo> kv in sub.dylex) {
  3076. if (!(kv.Value is LILabel))
  3077. continue;
  3078. handlers.Add("8");
  3079. handlers.Add(kv.Key);
  3080. handlers.Add("goto_" + kv.Key);
  3081. }
  3082. if (sub.mo.HasType(sub.setting.RoutineMO) &&
  3083. (sub.special & SubInfo.RETURN_PASS) == 0) {
  3084. handlers.Add("4");
  3085. handlers.Add("");
  3086. handlers.Add("tend");
  3087. }
  3088. if (handlers.Count != 5)
  3089. b = handlers.ToArray();
  3090. enter.Insert(0, "prog");
  3091. enter.Add(new object[] { "return", b });
  3092. b = enter.ToArray();
  3093. return b;
  3094. }
  3095. CpsOp Scan(object node) {
  3096. object[] rnode = (object[]) node;
  3097. string tag = JScalar.S(rnode[0]);
  3098. Func<NamProcessor, object[], CpsOp> handler;
  3099. if (!handlers.TryGetValue(tag, out handler)) {
  3100. MethodInfo mi = Tokens.Builtins.GetMethod(tag);
  3101. if (mi == null)
  3102. throw new Exception("Unhandled nam operator " + tag);
  3103. handlers[tag] = handler = (mi.ReturnType == Tokens.Frame &&
  3104. mi.GetParameters().Length >= 1 &&
  3105. mi.GetParameters()[0].ParameterType == Tokens.Frame)
  3106. ? MakeTotalHandler(Methody(Tokens.Variable, mi))
  3107. : MakeTotalHandler(Methody(null, mi));
  3108. }
  3109. if (Config.CGVerbose > 1)
  3110. Console.WriteLine("enter " + tag);
  3111. CpsOp r = handler(this, rnode);
  3112. if (Config.CGVerbose > 1)
  3113. Console.WriteLine("exit " + tag + " " + r.head.Returns);
  3114. return r;
  3115. }
  3116. }
  3117. public class Backend {
  3118. [TrueGlobal]
  3119. public static bool cross_level_load;
  3120. public static string LocStr(string fo, int lo, string fn, int ln) {
  3121. return fn == fo ? " (see line " + lo + ")" :
  3122. " (see " + fo + " line " + lo + ")";
  3123. }
  3124. }
  3125. // instantiatable for the sake of reflecty loading
  3126. public abstract class CallReceiver : MarshalByRefObject, IDictionary {
  3127. public bool IsFixedSize { get { return false; } }
  3128. public bool IsReadOnly { get { return false; } }
  3129. public bool IsSynchronized { get { return false; } }
  3130. public int Count { get { return 0; } }
  3131. public object SyncRoot { get { return null; } }
  3132. public ICollection Keys { get { return null; } }
  3133. public ICollection Values { get { return null; } }
  3134. public void Add(object a, object b) { }
  3135. public void Clear() { }
  3136. public IDictionaryEnumerator GetEnumerator() { return null; }
  3137. IEnumerator IEnumerable.GetEnumerator() { return null; }
  3138. public bool Contains(object a) { return false; }
  3139. public void CopyTo(Array a, int offs) { }
  3140. public void Remove(object a) { }
  3141. public abstract object this[object i] { get; set; }
  3142. }
  3143. class Handle: MarshalByRefObject {
  3144. object to;
  3145. public Handle(object to) { this.to = to; }
  3146. public static object Unbox(object h) {
  3147. return h == null ? null : ((Handle)h).to;
  3148. }
  3149. public static Handle Wrap(object h) {
  3150. return h == null ? null : new Handle(h);
  3151. }
  3152. public override string ToString() {
  3153. return string.Format("{0}[{1:X}]", to.ToString(), to.GetHashCode());
  3154. }
  3155. }
  3156. public class DowncallReceiver : CallReceiver {
  3157. public override object this[object i] {
  3158. set { }
  3159. get {
  3160. try {
  3161. return Call((object[]) i);
  3162. } catch (Exception ex) {
  3163. return new Exception(ex.ToString());
  3164. }
  3165. }
  3166. }
  3167. static readonly bool TraceDown = Environment.GetEnvironmentVariable("NIECZA_TRACE_DOWNCALLS") != null;
  3168. static object AddLexical(object[] args, LexInfo li) {
  3169. li.owner = (SubInfo)Handle.Unbox(args[1]);
  3170. li.name = (string)args[2];
  3171. li.file = (string)args[3];
  3172. li.line = (int) args[4];
  3173. li.pos = (int) args[5];
  3174. LexInfo other;
  3175. if (li.owner.dylex.TryGetValue(li.name, out other))
  3176. return new object[] { "collision", li.name, li.file, li.line,
  3177. other.file, other.line };
  3178. SubInfo.UsedInScopeInfo uisi;
  3179. if (li.name != "$_" && li.owner.used_in_scope.TryGetValue(li.name, out uisi)) // $_ HACK
  3180. return new object[] { "already-bound", li.name, uisi.levels,
  3181. uisi.line, li.file, li.line, uisi.orig_file, uisi.orig_line };
  3182. li.owner.AddLexical(li.name, li);
  3183. if (li.name.Length >= 1 && li.name[0] == '&')
  3184. return new object[] { "sub", li.name };
  3185. return new object[] { "" };
  3186. }
  3187. static STable ResolveSubClass(Compartment s, string cls) {
  3188. // this happens before lexicals are created, so we can't
  3189. // use lexicals.
  3190. STable rcls = (cls == "Sub") ? s.SubMO :
  3191. (cls == "Routine") ? s.RoutineMO :
  3192. (cls == "Regex") ? s.RegexMO :
  3193. (cls == "Method") ? s.MethodMO :
  3194. (cls == "Submethod") ? s.SubmethodMO :
  3195. (cls == "WhateverCode") ? s.WhateverCodeMO :
  3196. (cls == "Block") ? s.BlockMO :
  3197. (cls == "Code") ? s.CodeMO : null;
  3198. return rcls;
  3199. }
  3200. // XXX delete me after killing JScalar
  3201. internal static LAD BuildLadJ(object treex) {
  3202. object[] tree = (object[]) treex;
  3203. string key = JScalar.S(tree[0]);
  3204. if (key == "CC") {
  3205. int[] nar = JScalar.IA(1, tree);
  3206. return new LADCC(new CC(nar));
  3207. } else if (key == "Imp") {
  3208. return new LADImp();
  3209. } else if (key == "Dot") {
  3210. return new LADDot();
  3211. } else if (key == "None") {
  3212. return new LADNone();
  3213. } else if (key == "Null") {
  3214. return new LADNull();
  3215. } else if (key == "Dispatcher") {
  3216. return new LADDispatcher();
  3217. } else if (key == "Str") {
  3218. return new LADStr(JScalar.S(tree[1]));
  3219. } else if (key == "StrNoCase") {
  3220. return new LADStrNoCase(JScalar.S(tree[1]));
  3221. } else if (key == "Param") {
  3222. return new LADParam(JScalar.S(tree[1]));
  3223. } else if (key == "Method") {
  3224. return new LADMethod(JScalar.S(tree[1]));
  3225. } else if (key == "Quant") {
  3226. return new LADQuant(JScalar.I(tree[1]), BuildLadJ(tree[2]),
  3227. tree.Length > 3 ? BuildLadJ(tree[3]) : null);
  3228. } else if (key == "Sequence" || key == "Any") {
  3229. object[] za = (object[])tree[1];
  3230. LAD[] z = new LAD[za.Length];
  3231. for (int i = 0; i < za.Length; i++)
  3232. z[i] = BuildLadJ(za[i]);
  3233. return (key == "Any") ? (LAD)new LADAny(z) : new LADSequence(z);
  3234. } else {
  3235. throw new Exception("odd lad key " + key);
  3236. }
  3237. }
  3238. static LAD BuildLad(object[] tree) {
  3239. string key = (string) tree[0];
  3240. if (key == "CC") {
  3241. int[] nar = new int[tree.Length-1];
  3242. Array.Copy(tree, 1, nar, 0, nar.Length);
  3243. return new LADCC(new CC(nar));
  3244. } else if (key == "Imp") {
  3245. return new LADImp();
  3246. } else if (key == "Dot") {
  3247. return new LADDot();
  3248. } else if (key == "None") {
  3249. return new LADNone();
  3250. } else if (key == "Null") {
  3251. return new LADNull();
  3252. } else if (key == "Dispatcher") {
  3253. return new LADDispatcher();
  3254. } else if (key == "Str") {
  3255. return new LADStr((string)tree[1]);
  3256. } else if (key == "StrNoCase") {
  3257. return new LADStrNoCase((string)tree[1]);
  3258. } else if (key == "Param") {
  3259. return new LADParam((string)tree[1]);
  3260. } else if (key == "Method") {
  3261. return new LADMethod((string)tree[1]);
  3262. } else if (key == "Quant") {
  3263. return new LADQuant((int)tree[1], BuildLad((object[])tree[2]),
  3264. tree.Length > 3 ? BuildLad((object[])tree[3]) : null);
  3265. } else if (key == "Sequence" || key == "Any") {
  3266. object[] za = (object[])tree[1];
  3267. LAD[] z = new LAD[za.Length];
  3268. for (int i = 0; i < za.Length; i++)
  3269. z[i] = BuildLad((object[])za[i]);
  3270. return (key == "Any") ? (LAD)new LADAny(z) : new LADSequence(z);
  3271. } else {
  3272. throw new Exception("odd lad key " + key);
  3273. }
  3274. }
  3275. static void ShowCall(object[] args) {
  3276. StringBuilder sb = new StringBuilder();
  3277. foreach(object a in args) {
  3278. char ch = (a is int) ? 'i' : (a is Handle) ? 'h' :
  3279. (a is double) ? 'd' :
  3280. (a is string) ? 's' : (a is bool) ? 'b' :
  3281. (a == null) ? 'n' : 'X';
  3282. sb.AppendFormat("{0}:{1}; ", ch, a);
  3283. }
  3284. Console.WriteLine(sb.ToString());
  3285. }
  3286. Dictionary<string, Func<object[],object>> methods;
  3287. public DowncallReceiver() {
  3288. methods = new Dictionary<string, Func<object[],object>>();
  3289. foreach (MethodInfo mi in typeof(DowncallReceiver).GetMethods()) {
  3290. if (mi.ReturnType != typeof(object))
  3291. continue;
  3292. var pis = mi.GetParameters();
  3293. if (pis.Length != 1 || pis[0].ParameterType != typeof(object[]))
  3294. continue;
  3295. methods[mi.Name] = (Func<object[],object>) Delegate.CreateDelegate(typeof(Func<object[],object>), mi);
  3296. }
  3297. }
  3298. object Call(object[] args) {
  3299. if (TraceDown) ShowCall(args);
  3300. string cmd = (string) args[0];
  3301. Func<object[],object> fn;
  3302. if (methods.TryGetValue(cmd, out fn))
  3303. return fn(args);
  3304. else {
  3305. ShowCall(args);
  3306. return new Exception("No handler for downcall " + cmd);
  3307. }
  3308. }
  3309. public static object gettype(object[] args) {
  3310. object o = Handle.Unbox(args[1]);
  3311. return (o is SubInfo) ? "sub" : (o is RuntimeUnit) ? "unit" :
  3312. (o is STable) ? "type" : (o is Frame) ? "frame" :
  3313. (o is Parameter) ? "param" : (o is Variable) ? "value" :
  3314. "unknown";
  3315. }
  3316. public static object set_binding(object[] args) {
  3317. if (Environment.GetEnvironmentVariable("NIECZA_DEFER_TRACE") != null) {
  3318. Kernel.TraceFlags = Kernel.TRACE_CUR;
  3319. Kernel.TraceCount = Kernel.TraceFreq = 1;
  3320. }
  3321. var c = (Compartment)Handle.Unbox(args[1]);
  3322. c.obj_dirs = (args[2] is string) ? new [] { (string)args[2] } : (string[]) args[2];
  3323. c.upcall_receiver = (System.Collections.IDictionary)args[3];
  3324. return null;
  3325. }
  3326. public static object push_compartment(object[] args) {
  3327. var nc = new Compartment();
  3328. Kernel.InitGlobal();
  3329. Kernel.InitCompartment(nc);
  3330. return Handle.Wrap(nc);
  3331. }
  3332. public static object pop_compartment(object[] args) {
  3333. var c = (Compartment)Handle.Unbox(args[1]);
  3334. c.RunEnd();
  3335. return null;
  3336. }
  3337. public static object new_unit(object[] args) {
  3338. object cref = Handle.Unbox(args[1]);
  3339. Compartment comp = (cref as Compartment) ?? ((SubInfo)cref).setting;
  3340. RuntimeUnit ru = new RuntimeUnit(comp, (string)args[2],
  3341. (string)args[3], (string)args[4], (bool)args[5],
  3342. (bool)args[6]);
  3343. if (ru.setting.containerRootUnit == null) {
  3344. // this is a module unit
  3345. Kernel.InitCompartment(ru.setting);
  3346. ru.setting.containerRootUnit = ru;
  3347. ru.depended_units.Add(ru);
  3348. ru.owner = ru;
  3349. ru.globals = ru.setting.currentGlobals =
  3350. new Dictionary<string,StashEnt>();
  3351. } else {
  3352. // needs to use the same globals as the other units in
  3353. // this serialization unit
  3354. ru.globals = ru.setting.currentGlobals;
  3355. ru.owner = ru.setting.containerRootUnit;
  3356. ru.owner.subordinates.Add(ru);
  3357. }
  3358. return new Handle(ru);
  3359. }
  3360. public static object unit_get_incs(object[] args) {
  3361. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3362. StashEnt bv;
  3363. if (!ru.setting.currentGlobals.TryGetValue("\u0008::GLOBAL@INC", out bv))
  3364. return new string[0];
  3365. return Builtins.UnboxLoS(bv.v);
  3366. }
  3367. public static object unit_use_perl5_module(object[] args) {
  3368. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3369. string name = (string)args[2];
  3370. Variable code = Kernel.BoxAnyMO<string>("Niecza::Helpers::use_module('"+name+"')", ru.setting.StrMO);
  3371. string sub = Kernel.UnboxAny<string>(Builtins.eval_perl5(code).Fetch());
  3372. return sub;
  3373. }
  3374. static RuntimeUnit ProbeLoad(Compartment setting, string oname) {
  3375. try {
  3376. return (RuntimeUnit) setting.reg.LoadUnit(oname).root;
  3377. } catch (Exception ex) {
  3378. if (Config.SerFailInfo)
  3379. Console.WriteLine("Thaw {0} failed: >>>{1}<<<", oname, ex);
  3380. }
  3381. // if we're here, the load failed
  3382. // maybe a stale local cache file?
  3383. if (setting.reg.DeleteTopUnit(oname)) {
  3384. try {
  3385. return (RuntimeUnit) setting.reg.LoadUnit(oname).root;
  3386. } catch (Exception) { }
  3387. }
  3388. // ok, recompilation is needed I guess
  3389. object r1 = Builtins.UpCall(setting, new object[] {
  3390. "compile_unit", oname });
  3391. if (r1 != null)
  3392. throw (Exception)r1;
  3393. return (RuntimeUnit) setting.reg.LoadUnit(oname).root;
  3394. }
  3395. public static object unit_need_unit(object[] args) {
  3396. // LinkUnit state is owned by the root
  3397. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3398. string oname = (string)args[2];
  3399. RuntimeUnit tg = ProbeLoad(ru.setting, oname);
  3400. string err = ru.owner.LinkUnit(tg);
  3401. return err == null ? (object)new Handle(tg) : new Exception(err);
  3402. }
  3403. public static object unit_anon_stash(object[] args) {
  3404. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3405. return ru.name + ":" + (ru.nextid++);
  3406. }
  3407. public static object unit_set_bottom(object[] args) {
  3408. ((RuntimeUnit)Handle.Unbox(args[1])).bottom =
  3409. (SubInfo)Handle.Unbox(args[2]);
  3410. return null;
  3411. }
  3412. public static object unit_bottom(object[] args) {
  3413. return Handle.Wrap(((RuntimeUnit)Handle.Unbox(args[1])).bottom);
  3414. }
  3415. public static object unit_mainline(object[] args) {
  3416. return Handle.Wrap(((RuntimeUnit)Handle.Unbox(args[1])).mainline);
  3417. }
  3418. public static object unit_set_mainline(object[] args) {
  3419. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3420. ru.mainline = (SubInfo)Handle.Unbox(args[2]);
  3421. ru.mainline.special |= SubInfo.MAINLINE;
  3422. return null;
  3423. }
  3424. public static object sub_set_ltm(object[] args) {
  3425. ((SubInfo)Handle.Unbox(args[1])).ltm =
  3426. BuildLad((object[])args[2]);
  3427. return null;
  3428. }
  3429. public static object sub_create_static_pad(object[] args) {
  3430. ((SubInfo)Handle.Unbox(args[1])).CreateProtopad(null);
  3431. return null;
  3432. }
  3433. public static object sub_noninlinable(object[] args) {
  3434. ((SubInfo)Handle.Unbox(args[1])).special |=
  3435. SubInfo.CANNOT_INLINE;
  3436. return null;
  3437. }
  3438. public static object sub_set_return_pass(object[] args) {
  3439. ((SubInfo)Handle.Unbox(args[1])).special |=
  3440. SubInfo.RETURN_PASS;
  3441. return null;
  3442. }
  3443. public static object sub_set_transparent(object[] args) {
  3444. ((SubInfo)Handle.Unbox(args[1])).special |=
  3445. SubInfo.TRANSPARENT;
  3446. return null;
  3447. }
  3448. public static object sub_set_run_once(object[] args) {
  3449. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3450. if ((s.outer.special & SubInfo.RUN_ONCE) != 0) {
  3451. s.CreateProtopad(null);
  3452. s.special |= SubInfo.RUN_ONCE;
  3453. }
  3454. return null;
  3455. }
  3456. public static object sub_set_unsafe(object[] args) {
  3457. ((SubInfo)Handle.Unbox(args[1])).special |=
  3458. SubInfo.UNSAFE;
  3459. return null;
  3460. }
  3461. public static object sub_arity(object[] args) {
  3462. return Builtins.sig_arity(((SubInfo)Handle.Unbox(args[1])).sig);
  3463. }
  3464. public static object sub_is_inlinable(object[] args) {
  3465. return ((SubInfo)Handle.Unbox(args[1])).IsInlinable();
  3466. }
  3467. public static object sub_topicalizer(object[] args) {
  3468. return ((SubInfo)Handle.Unbox(args[1])).IsTopicalizer();
  3469. }
  3470. public static object sub_count(object[] args) {
  3471. return Builtins.sig_count(((SubInfo)Handle.Unbox(args[1])).sig);
  3472. }
  3473. public static object sub_set_inlined(object[] args) {
  3474. ((SubInfo)Handle.Unbox(args[1])).SetInlined();
  3475. return null;
  3476. }
  3477. public static object value_get_type(object[] args) {
  3478. return Handle.Wrap(((Variable)Handle.Unbox(args[1])).Fetch().mo);
  3479. }
  3480. public static object value_to_sub(object[] args) {
  3481. var v = ((Variable)Handle.Unbox(args[1])).Fetch();
  3482. return Handle.Wrap(v.Isa(v.mo.setting.CodeMO) ? Kernel.GetInfo(v) : null);
  3483. }
  3484. public static object value_to_string(object[] args) {
  3485. return Builtins.ToStr((Variable)Handle.Unbox(args[1]));
  3486. }
  3487. public static object value_to_string_list(object[] args) {
  3488. return Builtins.UnboxLoS((Variable)Handle.Unbox(args[1]));
  3489. }
  3490. public static object value_enum_type(object[] args) {
  3491. var v = (Variable)Handle.Unbox(args[1]);
  3492. return Builtins.ToStr(Builtins.InvokeMethod("data-type", v));
  3493. }
  3494. public static object value_enum_keys(object[] args) {
  3495. var v = (Variable)Handle.Unbox(args[1]);
  3496. return Builtins.UnboxLoS(Builtins.InvokeMethod("keys", v));
  3497. }
  3498. public static object value_starts_with_pair(object[] args) {
  3499. var ob = ((Variable)Handle.Unbox(args[1])).Fetch();
  3500. if (ob.Isa(ob.mo.setting.PairMO))
  3501. return true;
  3502. if (ob.Isa(ob.mo.setting.ParcelMO) && Kernel.UnboxAny<Variable[]>(ob)[0].Fetch().Isa(ob.mo.setting.PairMO))
  3503. return true;
  3504. return false;
  3505. }
  3506. public static object unit_constant_fold(object[] args) {
  3507. var callee = Handle.Unbox(args[2]);
  3508. var pos = new List<Variable>();
  3509. var nam = new VarHash();
  3510. for (int ix = 3; ix < args.Length; ix += 2) {
  3511. var v = (Variable)Handle.Unbox(args[ix+1]);
  3512. if (v.Rw) return null;
  3513. // this next one is a bit of a hack to get the right results
  3514. // while compiling the setting...
  3515. if (v.Fetch().mo.FindMethod("immutable") != null &&
  3516. !Builtins.ToBool(Builtins.InvokeMethod("immutable", v)))
  3517. return null;
  3518. if (args[ix] == null) {
  3519. pos.Add(v);
  3520. } else {
  3521. nam[(string)args[ix]] = v;
  3522. }
  3523. }
  3524. object r = null;
  3525. try {
  3526. P6any tocall = (callee is Variable) ?
  3527. ((Variable)callee).Fetch() : ((SubInfo)callee).protosub;
  3528. r = Handle.Wrap(Builtins.InvokeSub(tocall, pos.ToArray(), nam));
  3529. } catch (Exception ex) {
  3530. r = ex.ToString();
  3531. }
  3532. return r;
  3533. }
  3534. public static object unit_string_constant(object[] args) {
  3535. RuntimeUnit c = (RuntimeUnit)Handle.Unbox(args[1]);
  3536. return Handle.Wrap(c.setting.MakeStr((string)args[2]));
  3537. }
  3538. public static object unit_numeric_constant(object[] args) {
  3539. RuntimeUnit c = (RuntimeUnit)Handle.Unbox(args[1]);
  3540. if (args.Length == 4) {
  3541. int bas = (int)args[2];
  3542. string digits = (string)args[3];
  3543. return Handle.Wrap(EmitUnit.ExactNum(c.setting, bas, digits));
  3544. } else {
  3545. double d = (args[2] is double) ? (double)args[2] : (int)args[2];
  3546. return Handle.Wrap(c.setting.MakeFloat(d));
  3547. }
  3548. }
  3549. public static object sub_run_BEGIN_raw(object[] args) {
  3550. SubInfo si = (SubInfo)Handle.Unbox(args[1]);
  3551. return new Handle(si.RunBEGIN());
  3552. }
  3553. public static object sub_run_BEGIN_CC(object[] args) {
  3554. SubInfo si = (SubInfo)Handle.Unbox(args[1]);
  3555. Variable v = si.RunBEGIN();
  3556. // no really this is a horrible hack... we need a way for
  3557. // the compiler to directly manipulate MOP values
  3558. return Niecza.UCD.DataSet.CompileCClass(v);
  3559. }
  3560. public static object sub_run_BEGIN(object[] args) {
  3561. SubInfo si = (SubInfo)Handle.Unbox(args[1]);
  3562. Variable v = si.RunBEGIN();
  3563. string cn = (string)args[2];
  3564. while (si != null && !si.dylex.ContainsKey(cn)) si = si.outer;
  3565. LexInfo li = si == null ? null : si.dylex[cn];
  3566. if (li is LIConstant) {
  3567. ((LIConstant)li).value = v;
  3568. } else if (li is LICommon) {
  3569. StashEnt hkey = si.setting.currentGlobals[((LICommon)li).hkey];
  3570. hkey.constant = true;
  3571. hkey.v = v;
  3572. } else {
  3573. return new Exception("cannot bind constant value");
  3574. }
  3575. return null;
  3576. }
  3577. public static object sub_get_unit(object[] args) {
  3578. return new Handle(((SubInfo)Handle.Unbox(args[1])).unit);
  3579. }
  3580. public static object sub_run_once(object[] args) {
  3581. return (((SubInfo)Handle.Unbox(args[1])).special &
  3582. SubInfo.RUN_ONCE) != 0;
  3583. }
  3584. public static object sub_transparent(object[] args) {
  3585. return (((SubInfo)Handle.Unbox(args[1])).special &
  3586. SubInfo.TRANSPARENT) != 0;
  3587. }
  3588. public static object sub_outervar(object[] args) {
  3589. return ((SubInfo)Handle.Unbox(args[1])).outervar;
  3590. }
  3591. public static object sub_name(object[] args) {
  3592. return ((SubInfo)Handle.Unbox(args[1])).name;
  3593. }
  3594. public static object sub_methodof(object[] args) {
  3595. return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).methodof);
  3596. }
  3597. public static object sub_outer(object[] args) {
  3598. return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).outer);
  3599. }
  3600. public static object sub_class(object[] args) {
  3601. return ((SubInfo)Handle.Unbox(args[1])).mo.name;
  3602. }
  3603. public static object sub_body_of(object[] args) {
  3604. return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).body_of);
  3605. }
  3606. public static object sub_in_class(object[] args) {
  3607. return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).in_class);
  3608. }
  3609. public static object sub_cur_pkg(object[] args) {
  3610. return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).cur_pkg);
  3611. }
  3612. public static object sub_set_methodof(object[] args) {
  3613. ((SubInfo)Handle.Unbox(args[1])).methodof =
  3614. (STable)Handle.Unbox(args[2]);
  3615. return null;
  3616. }
  3617. public static object sub_set_body_of(object[] args) {
  3618. ((SubInfo)Handle.Unbox(args[1])).body_of =
  3619. (STable)Handle.Unbox(args[2]);
  3620. return null;
  3621. }
  3622. public static object sub_set_cur_pkg(object[] args) {
  3623. ((SubInfo)Handle.Unbox(args[1])).cur_pkg =
  3624. (STable)Handle.Unbox(args[2]);
  3625. return null;
  3626. }
  3627. public static object sub_set_in_class(object[] args) {
  3628. ((SubInfo)Handle.Unbox(args[1])).in_class =
  3629. (STable)Handle.Unbox(args[2]);
  3630. return null;
  3631. }
  3632. public static object sub_set_outervar(object[] args) {
  3633. ((SubInfo)Handle.Unbox(args[1])).outervar = (string)args[2];
  3634. return null;
  3635. }
  3636. public static object sub_set_name(object[] args) {
  3637. ((SubInfo)Handle.Unbox(args[1])).name = (string)args[2];
  3638. return null;
  3639. }
  3640. public static object sub_set_class(object[] args) {
  3641. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3642. STable c = ResolveSubClass(s.setting, (string)args[2]);
  3643. s.mo = c;
  3644. if (s.protosub != null)
  3645. s.protosub.mo = c;
  3646. return null;
  3647. }
  3648. public static object sub_delete_lex(object[] args) {
  3649. // XXX This leaves a gap in the lexical/number mapping.
  3650. // Don't use it too much.
  3651. SubInfo from = (SubInfo)Handle.Unbox(args[1]);
  3652. string lkey = (string)args[2];
  3653. from.dylex.Remove(lkey);
  3654. return null;
  3655. }
  3656. public static object sub_lookup_lex(object[] args) {
  3657. SubInfo from = (SubInfo)Handle.Unbox(args[1]);
  3658. string lkey = (string)args[2];
  3659. string file = (string)args[3];
  3660. int line = (int)args[4];
  3661. SubInfo csr;
  3662. int levels = 0;
  3663. for (csr = from; csr != null; csr = csr.outer, levels++)
  3664. if (csr.dylex.ContainsKey(lkey))
  3665. break;
  3666. if (csr == null)
  3667. return new object[0];
  3668. LexInfo li = csr.dylex[lkey];
  3669. if (file != null) {
  3670. for (SubInfo csr2 = from;
  3671. csr2.used_in_scope != null && // modify only open units
  3672. !csr2.used_in_scope.ContainsKey(lkey);
  3673. csr2 = csr2.outer, levels--) {
  3674. var uisi = new SubInfo.UsedInScopeInfo();
  3675. uisi.orig_file = li.file;
  3676. uisi.orig_line = li.line;
  3677. uisi.file = file;
  3678. uisi.line = line;
  3679. uisi.levels = levels;
  3680. csr2.used_in_scope[lkey] = uisi;
  3681. if (csr == csr2)
  3682. break; // stop *after* reaching defined scope
  3683. }
  3684. }
  3685. object[] r = null;
  3686. var lalias = li as LIAlias;
  3687. if (lalias != null)
  3688. r = new object[] { "alias",null,null,null, lalias.to };
  3689. var lattralias = li as LIAttrAlias;
  3690. if (lattralias != null)
  3691. r = new object[] { "attralias",null,null,null, new Handle(lattralias.atype), lattralias.aname };
  3692. var lsub = li as LISub;
  3693. if (lsub != null)
  3694. r = new object[] { "sub",null,null,null, new Handle(lsub.def) };
  3695. var lpkg = li as LIPackage;
  3696. if (lpkg != null)
  3697. r = new object[] { "package",null,null,null, new Handle(lpkg.pkg) };
  3698. var lsimp = li as LISimple;
  3699. if (lsimp != null)
  3700. r = new object[] { "simple",null,null,null, lsimp.flags, Handle.Wrap(lsimp.type) };
  3701. var ldisp = li as LIDispatch;
  3702. if (ldisp != null)
  3703. r = new object[] { "dispatch",null,null,null, Handle.Wrap(csr),
  3704. csr.protopad != null ? Handle.Wrap(ldisp.Get(csr.protopad)) : null};
  3705. var llab = li as LILabel;
  3706. if (llab != null)
  3707. r = new object[] { "label",null,null,null };
  3708. var lhint = li as LIConstant;
  3709. if (lhint != null)
  3710. r = new object[] { "hint",null,null,null, Handle.Wrap(lhint.value) };
  3711. var lcomm = li as LICommon;
  3712. if (lcomm != null) {
  3713. StashEnt se;
  3714. csr.setting.currentGlobals.TryGetValue(lcomm.hkey, out se);
  3715. r = new object[] { "common",null,null,null, lcomm.Stash(), lcomm.VarName(), (se.constant ? Handle.Wrap(se.v) : null) };
  3716. }
  3717. r[1] = li.file;
  3718. r[2] = li.line;
  3719. r[3] = li.pos;
  3720. return r;
  3721. }
  3722. public static object lex_names(object[] args) {
  3723. List<object> ret = new List<object>();
  3724. foreach (string k in ((SubInfo)Handle.Unbox(args[1])).dylex.Keys)
  3725. ret.Add(k);
  3726. return ret.ToArray();
  3727. }
  3728. public static object unused_lexicals(object[] args) {
  3729. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3730. List<object> ret = new List<object>();
  3731. foreach (KeyValuePair<string,LexInfo> kv in s.dylex) {
  3732. if (s.used_in_scope.ContainsKey(kv.Key))
  3733. continue;
  3734. ret.Add(kv.Key);
  3735. ret.Add(kv.Value.pos);
  3736. }
  3737. return ret.ToArray();
  3738. }
  3739. public static object unit_stubbed_stashes(object[] args) {
  3740. RuntimeUnit u = (RuntimeUnit)Handle.Unbox(args[1]);
  3741. List<object> ret = new List<object>();
  3742. foreach (KeyValuePair<int,STable> kv in u.stubbed_stashes) {
  3743. ret.Add(kv.Key);
  3744. ret.Add(new Handle(kv.Value));
  3745. }
  3746. return ret.ToArray();
  3747. }
  3748. public static object unit_stub_stash(object[] args) {
  3749. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3750. int pos = (int)args[2];
  3751. STable type = (STable)Handle.Unbox(args[3]);
  3752. ru.stubbed_stashes.Add(new KeyValuePair<int,STable>(pos,type));
  3753. return null;
  3754. }
  3755. public static object unit_name(object[] args) {
  3756. return ((RuntimeUnit)Handle.Unbox(args[1])).name;
  3757. }
  3758. public static object sub_to_unit(object[] args) {
  3759. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3760. while ((s.special & SubInfo.MAINLINE) == 0)
  3761. s = s.outer;
  3762. return new Handle(s);
  3763. }
  3764. public static object equal_handles(object[] args) {
  3765. return Handle.Unbox(args[1]) == Handle.Unbox(args[2]);
  3766. }
  3767. public static object sub_is_routine(object[] args) {
  3768. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3769. return s.mo.HasType(s.setting.RoutineMO);
  3770. }
  3771. public static object sub_is_regex(object[] args) {
  3772. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3773. return s.mo.HasType(s.setting.RegexMO);
  3774. }
  3775. public static object sub_has_lexical(object[] args) {
  3776. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3777. return s.dylex.ContainsKey((string)args[2]);
  3778. }
  3779. public static object sub_lexical_used(object[] args) {
  3780. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3781. return s.used_in_scope.ContainsKey((string)args[2]);
  3782. }
  3783. public static object sub_parameterize_topic(object[] args) {
  3784. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  3785. LISimple li = (LISimple)s.dylex["$_"];
  3786. li.flags = LISimple.NOINIT;
  3787. return null;
  3788. }
  3789. public static object unit_rel_pkg(object[] args) {
  3790. RuntimeUnit c = (RuntimeUnit)Handle.Unbox(args[1]);
  3791. bool auto = (bool)args[2];
  3792. STable pkg = args[3] == null ? null :
  3793. (STable)Handle.Unbox(args[3]);
  3794. for (int i = 4; i < args.Length; i++) {
  3795. string key = (string) args[i];
  3796. string who = "";
  3797. if (pkg != null) {
  3798. if (!pkg.who.Isa(c.setting.StashMO))
  3799. return new Exception(pkg.name + " fails to name a standard package");
  3800. who = Kernel.UnboxAny<string>(pkg.who);
  3801. }
  3802. StashEnt v;
  3803. string hkey = (char)who.Length + who + key;
  3804. if (c.globals.TryGetValue(hkey, out v)) {
  3805. if (v.v.Rw || v.v.Fetch().IsDefined())
  3806. return new Exception((who + "::" + key).Substring(2) + " names a non-package");
  3807. pkg = v.v.Fetch().mo;
  3808. } else if (!auto) {
  3809. return new Exception((who + "::" + key).Substring(2) + " does not name any package");
  3810. } else {
  3811. c.globals[hkey] = v = new StashEnt();
  3812. v.constant = true;
  3813. v.v = StashCursor.MakePackage(c.setting, (who + "::" + key).Substring(2), Kernel.BoxRaw<string>(who + "::" + key, c.setting.StashMO));
  3814. pkg = v.v.Fetch().mo;
  3815. }
  3816. }
  3817. return new Handle(pkg);
  3818. }
  3819. public static object unit_list_stash(object[] args) {
  3820. RuntimeUnit c = (RuntimeUnit) Handle.Unbox(args[1]);
  3821. string who = (string)args[2];
  3822. var r = new List<object>();
  3823. string filter = ((char)who.Length) + who;
  3824. foreach (KeyValuePair<string,StashEnt> kv in c.globals) {
  3825. if (!Utils.StartsWithInvariant(filter, kv.Key))
  3826. continue;
  3827. r.Add(kv.Key.Substring(filter.Length));
  3828. StashEnt b = kv.Value;
  3829. if (!b.v.Rw && !b.v.Fetch().IsDefined()) {
  3830. r.Add(new Handle(b.v.Fetch().mo));
  3831. } else if (!b.v.Rw && b.v.Fetch().Isa(c.setting.CodeMO)) {
  3832. r.Add(new Handle(b.v.Fetch().GetSlot(c.setting.CodeMO, "$!info")));
  3833. } else {
  3834. r.Add(null);
  3835. }
  3836. }
  3837. return r.ToArray();
  3838. }
  3839. public static object unit_get(object[] args) {
  3840. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3841. string who = (string)args[2];
  3842. string key = (string)args[3];
  3843. string hkey = (char)who.Length + who + key;
  3844. StashEnt b;
  3845. if (ru.globals.TryGetValue(hkey, out b)) {
  3846. if (!b.v.Rw && !b.v.Fetch().IsDefined()) {
  3847. return new Handle(b.v.Fetch().mo);
  3848. } else if (!b.v.Rw && b.v.Fetch().Isa(ru.setting.CodeMO)) {
  3849. return new Handle(b.v.Fetch().GetSlot(ru.setting.CodeMO, "$!info"));
  3850. } else return null;
  3851. } else {
  3852. return null;
  3853. }
  3854. }
  3855. public static object unit_exists(object[] args) {
  3856. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3857. string who = (string)args[2];
  3858. string key = (string)args[3];
  3859. string hkey = (char)who.Length + who + key;
  3860. return ru.globals.ContainsKey(hkey);
  3861. }
  3862. public static object unit_bind(object[] args) {
  3863. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3864. string who = (string)args[2];
  3865. string name = (string)args[3];
  3866. object item = Handle.Unbox(args[4]);
  3867. string file = (string)args[5];
  3868. int line = (int)args[6];
  3869. Variable vitm = null;
  3870. if (item is STable)
  3871. vitm = ((STable)item).typeObj;
  3872. else if (item is SubInfo)
  3873. vitm = ((SubInfo)item).protosub;
  3874. else if (item == null)
  3875. vitm = null;
  3876. else
  3877. return new Exception("weird thing to bind");
  3878. string err = ru.NsBind(who, name, vitm, file, line);
  3879. return err == null ? null : new Exception(err);
  3880. }
  3881. public static object type_CAN(object[] args) {
  3882. STable st = (STable)Handle.Unbox(args[1]);
  3883. //string meth = (string)args[2];
  3884. return (st.mo.type != P6how.PACKAGE && st.mo.type != P6how.MODULE);
  3885. }
  3886. public static object type_add_super(object[] args) {
  3887. STable st = (STable)Handle.Unbox(args[1]);
  3888. STable su = (STable)Handle.Unbox(args[2]);
  3889. st.mo.superclasses.Add(Kernel.ToInheritable(su));
  3890. return null;
  3891. }
  3892. public static object type_add_role(object[] args) {
  3893. STable st = (STable)Handle.Unbox(args[1]);
  3894. STable su = (STable)Handle.Unbox(args[2]);
  3895. st.mo.local_roles.Add(su);
  3896. return null;
  3897. }
  3898. public static object type_add_attribute(object[] args) {
  3899. STable add_to = (STable)Handle.Unbox(args[1]);
  3900. string name = (string)args[2];
  3901. string sigil = (string)args[3];
  3902. bool access = (bool)args[4];
  3903. STable type = (STable)Handle.Unbox(args[5]);
  3904. string file = (string)args[6];
  3905. int line = (int)args[7];
  3906. foreach (P6how.AttrInfo ai in add_to.mo.local_attr)
  3907. if (ai.name == name)
  3908. return new Exception("Two definitions of attribute " + name + Backend.LocStr(ai.file, ai.line, file, line));
  3909. int flags = (sigil == "@") ? P6how.A_ARRAY :
  3910. (sigil == "%") ? P6how.A_HASH : 0;
  3911. if (access) flags |= P6how.A_PUBLIC;
  3912. add_to.mo.AddAttributePos(name, flags, null, type, file, line);
  3913. return null;
  3914. }
  3915. public static object type_add_initializer(object[] args) {
  3916. STable add_to = (STable)Handle.Unbox(args[1]);
  3917. string name = (string)args[2];
  3918. SubInfo init = (SubInfo)Handle.Unbox(args[3]);
  3919. for (int i = 0; i < add_to.mo.local_attr.Count; i++) {
  3920. var ai = add_to.mo.local_attr[i];
  3921. if (ai.name == name) {
  3922. ai.init = init.protosub;
  3923. add_to.mo.local_attr[i] = ai;
  3924. break;
  3925. }
  3926. }
  3927. return null;
  3928. }
  3929. public static object type_add_method(object[] args) {
  3930. STable add_to = (STable)Handle.Unbox(args[1]);
  3931. int mode = (int)args[2];
  3932. string name = (string)args[3];
  3933. SubInfo sub = (SubInfo)Handle.Unbox(args[4]);
  3934. string file = (string)args[5];
  3935. int line = (int)args[6];
  3936. //int pos = (int)args[7];
  3937. if ((mode & P6how.M_MASK) == P6how.M_ONLY) {
  3938. foreach (P6how.MethodInfo mi in add_to.mo.lmethods) {
  3939. if (mi.Name() == name &&
  3940. ((mi.flags ^ mode) & P6how.V_MASK) == 0) {
  3941. return new Exception("Two definitions of method " +
  3942. name + Backend.LocStr(mi.file, mi.line, file, line));
  3943. }
  3944. }
  3945. }
  3946. add_to.mo.AddMethodPos(mode, name, sub.protosub, file, line);
  3947. return null;
  3948. }
  3949. public static object type_set_instantiation_block(object[] args) {
  3950. STable add_to = (STable)Handle.Unbox(args[1]);
  3951. SubInfo block = (SubInfo)Handle.Unbox(args[2]);
  3952. add_to.mo.roleFactory = block.protosub;
  3953. return null;
  3954. }
  3955. public static object type_add_trustee(object[] args) {
  3956. STable st = (STable)Handle.Unbox(args[1]);
  3957. STable nw = (STable)Handle.Unbox(args[2]);
  3958. st.mo.trustees.Add(nw);
  3959. return null;
  3960. }
  3961. public static object type_trusts(object[] args) {
  3962. STable st = (STable)Handle.Unbox(args[1]);
  3963. STable nw = (STable)Handle.Unbox(args[2]);
  3964. return st == nw || st.mo.trustees.Contains(nw);
  3965. }
  3966. public static object type_closed(object[] args) {
  3967. STable st = (STable)Handle.Unbox(args[1]);
  3968. return st.mo.isComposed;
  3969. }
  3970. public static object type_close(object[] args) {
  3971. STable st = (STable)Handle.Unbox(args[1]);
  3972. string err = st.mo.Compose();
  3973. if (err != null)
  3974. return new Exception(err);
  3975. return null;
  3976. }
  3977. public static object type_kind(object[] args) {
  3978. STable st = (STable)Handle.Unbox(args[1]);
  3979. return st.mo.rtype;
  3980. }
  3981. public static object type_name(object[] args) {
  3982. STable st = (STable)Handle.Unbox(args[1]);
  3983. return st.name;
  3984. }
  3985. public static object type_who(object[] args) {
  3986. STable st = (STable)Handle.Unbox(args[1]);
  3987. return Kernel.UnboxAny<string>(st.who);
  3988. }
  3989. public static object type_create(object[] args) {
  3990. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  3991. string name = (string)args[2];
  3992. string type = (string)args[3];
  3993. string who = (string)args[4];
  3994. FieldInfo mof = ru.name == "CORE" ?
  3995. typeof(Compartment).GetField(name + "MO") : null;
  3996. FieldInfo pf = ru.name == "CORE" ?
  3997. typeof(Compartment).GetField(name + "P") : null;
  3998. STable nst = mof == null ? null : (STable)mof.GetValue(ru.setting);
  3999. if (nst == null) { // not all FooMO are initialized by kernel
  4000. nst = new STable(ru.setting, name);
  4001. if (mof != null) mof.SetValue(ru.setting, nst);
  4002. }
  4003. // Hack - we don't clear the MRO here, because we might need
  4004. // to call methods on the type in the process of defining the
  4005. // type itself.
  4006. nst.mo.superclasses.Clear();
  4007. // OTOH, it needs call structures set up to avoid internal errors
  4008. nst.mo.Revalidate();
  4009. if (nst.typeObj == null) // AnyMO.typeObj is set up early
  4010. nst.typeObj = new P6opaque(nst, 0);
  4011. ((P6opaque)nst.typeObj).slots = null;
  4012. if (ru.name == "CORE" && name == "Nil") {
  4013. // anomalously requires an iterable value
  4014. ru.setting.Nil = Kernel.NewRWListVar(nst.typeObj);
  4015. }
  4016. if (pf != null)
  4017. pf.SetValue(ru.setting, nst.typeObj);
  4018. nst.initObj = nst.typeObj;
  4019. nst.who = Kernel.BoxRaw(who, ru.setting.StashMO);
  4020. nst.how = Kernel.BoxRaw<STable>(nst, ru.setting.ClassHOWMO);
  4021. nst.mo.rtype = type;
  4022. nst.mo.type =
  4023. type == "package" ? P6how.PACKAGE :
  4024. type == "module" ? P6how.MODULE :
  4025. type == "class" ? P6how.CLASS :
  4026. type == "grammar" ? P6how.GRAMMAR :
  4027. type == "role" ? P6how.ROLE :
  4028. type == "prole" ? P6how.PARAMETRIZED_ROLE :
  4029. type == "subset" ? P6how.SUBSET :
  4030. -1;
  4031. if (nst.mo.type < 0)
  4032. return new Exception(type);
  4033. return new Handle(nst);
  4034. }
  4035. public static object type_set_basetype(object[] args) {
  4036. STable subset = (STable)Handle.Unbox(args[1]);
  4037. STable basety = (STable)Handle.Unbox(args[2]);
  4038. subset.mo.FillSubset(basety);
  4039. subset.initObj = basety.initObj;
  4040. return null;
  4041. }
  4042. public static object type_get_basetype(object[] args) {
  4043. return Handle.Wrap(((STable)Handle.Unbox(args[1])).mo.superclasses[0]);
  4044. }
  4045. public static object type_get_type_var(object[] args) {
  4046. return Handle.Wrap(((STable)Handle.Unbox(args[1])).typeObj);
  4047. }
  4048. public static object type_set_where(object[] args) {
  4049. STable subset = (STable)Handle.Unbox(args[1]);
  4050. SubInfo where = (SubInfo)Handle.Unbox(args[2]);
  4051. subset.mo.subsetWhereThunk = where.protosub;
  4052. return null;
  4053. }
  4054. public static object create_sub(object[] args) {
  4055. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  4056. string name = (string)args[2];
  4057. SubInfo outer = (SubInfo)Handle.Unbox(args[3]);
  4058. string cls = (string)args[4];
  4059. STable pkg = (STable)Handle.Unbox(args[5]);
  4060. STable icl = (STable)Handle.Unbox(args[6]);
  4061. bool once = (bool)args[7];
  4062. Frame outer_frame = (Frame)Handle.Unbox(args[8]);
  4063. if (outer_frame != null && outer_frame.info != outer) {
  4064. Console.WriteLine("MISMATCHED OUTER FRAME!!!");
  4065. outer_frame = null;
  4066. }
  4067. STable rcls = ResolveSubClass(ru.setting, cls);
  4068. if (rcls == null)
  4069. return new Exception("sub-class lookup fail for " + cls);
  4070. SubInfo n = new SubInfo(ru, name, outer, rcls, pkg, once,
  4071. outer_frame);
  4072. n.in_class = icl;
  4073. if (n.outer != null && n.outer.unit == ru)
  4074. n.outer.children.Add(n);
  4075. ru.our_subs.Add(n);
  4076. if (outer == null) {
  4077. /* Hack - embed build information */
  4078. var info = new VarHash();
  4079. info["name"] = ru.setting.MakeStr("niecza");
  4080. string vers = "(unknown)\n";
  4081. try {
  4082. string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
  4083. Path.Combine("..", "VERSION"));
  4084. vers = File.ReadAllText(path);
  4085. } catch (Exception) {
  4086. // ignore
  4087. }
  4088. info["version"] = ru.setting.MakeStr(
  4089. vers.Substring(0, vers.Length - 1));
  4090. info["build-time"] = Builtins.now(new Constants { setting = ru.setting });
  4091. var li = new LIConstant(Kernel.BoxAnyMO(info, ru.setting.HashMO));
  4092. n.AddLexical("$?PERL", li);
  4093. }
  4094. return new Handle(n);
  4095. }
  4096. public static object add_my_name(object[] args) {
  4097. STable type = (STable)Handle.Unbox(args[6]);
  4098. int flags = (int) args[7];
  4099. return AddLexical(args, new LISimple(flags, type));
  4100. }
  4101. public static object add_hint(object[] args) {
  4102. SubInfo sub = (SubInfo)Handle.Unbox(args[1]);
  4103. return AddLexical(args, new LIConstant(sub.setting.AnyP));
  4104. }
  4105. public static object add_label(object[] args) {
  4106. return AddLexical(args, new LILabel());
  4107. }
  4108. public static object add_dispatcher(object[] args) {
  4109. return AddLexical(args, new LIDispatch());
  4110. }
  4111. public static object add_common_name(object[] args) {
  4112. SubInfo sub = (SubInfo)Handle.Unbox(args[1]);
  4113. STable pkg = (STable)Handle.Unbox(args[6]);
  4114. string pname = (string)args[7];
  4115. if (!pkg.who.Isa(sub.setting.StashMO))
  4116. return new Exception("NYI usage of a nonstandard package");
  4117. string who = Kernel.UnboxAny<string>(pkg.who);
  4118. string err = sub.unit.NsBind(who, pname, null,
  4119. (string)args[3], (int)args[4]);
  4120. if (err != null) return new Exception(err);
  4121. return AddLexical(args, new LICommon((char)who.Length + who + pname));
  4122. }
  4123. public static object add_state_name(object[] args) {
  4124. SubInfo sub = (SubInfo)Handle.Unbox(args[1]);
  4125. SubInfo outer = (sub.special & SubInfo.MAINLINE) != 0 ?
  4126. sub : sub.outer;
  4127. STable type = (STable)Handle.Unbox(args[6]);
  4128. int flags = (int) args[7];
  4129. string back = (string)args[8];
  4130. string name = (string)args[2];
  4131. args[1] = Handle.Wrap(outer);
  4132. args[2] = back;
  4133. AddLexical(args, new LISimple(flags, type));
  4134. if (name != null) {
  4135. args[1] = Handle.Wrap(sub);
  4136. args[2] = name;
  4137. return AddLexical(args, new LIAlias(back));
  4138. } else {
  4139. return new object[] { "" };
  4140. }
  4141. }
  4142. public static object add_alias(object[] args) {
  4143. return AddLexical(args, new LIAlias((string)args[6]));
  4144. }
  4145. public static object add_attr_alias(object[] args) {
  4146. return AddLexical(args, new LIAttrAlias((STable)Handle.Unbox(args[6]),
  4147. (string)args[7]));
  4148. }
  4149. public static object add_my_stash(object[] args) {
  4150. STable type = (STable)Handle.Unbox(args[6]);
  4151. return AddLexical(args, new LIPackage(type));
  4152. }
  4153. public static object add_my_sub(object[] args) {
  4154. SubInfo body = (SubInfo)Handle.Unbox(args[6]);
  4155. return AddLexical(args, new LISub(body));
  4156. }
  4157. public static object sub_no_signature(object[] args) {
  4158. SubInfo tgt = (SubInfo)Handle.Unbox(args[1]);
  4159. tgt.sig = null;
  4160. return null;
  4161. }
  4162. public static object param_new(object[] args) {
  4163. SubInfo tgt = (SubInfo)Handle.Unbox(args[1]);
  4164. int ix = 2;
  4165. List<string> names = new List<string>();
  4166. int flags = (int) args[ix++];
  4167. string name = (string)args[ix++];
  4168. string slot = (string)args[ix++];
  4169. while(true) {
  4170. string a_name = (string)args[ix++];
  4171. if (a_name == null) break;
  4172. names.Add(a_name);
  4173. }
  4174. object deflt = Handle.Unbox(args[ix++]);
  4175. STable type = (STable)Handle.Unbox(args[ix++]);
  4176. if (deflt != null) flags |= Parameter.HASDEFAULT;
  4177. if (type != null) flags |= Parameter.HASTYPE;
  4178. string attr = (string)args[ix++];
  4179. STable atype = (STable)Handle.Unbox(args[ix++]);
  4180. return Handle.Wrap(new Parameter(tgt.setting, flags,
  4181. (slot == null ? -1 : tgt.dylex[slot].SigIndex()),
  4182. name, (names.Count == 0 ? null : names.ToArray()),
  4183. deflt, type ?? tgt.setting.AnyMO, attr, atype));
  4184. }
  4185. public static object param_constraints(object[] args) {
  4186. Parameter tgt = (Parameter)Handle.Unbox(args[1]);
  4187. tgt.post_constraints = new object[args.Length - 2];
  4188. for (int ix = 2; ix != args.Length; ix++)
  4189. tgt.post_constraints[ix-2] = (args[ix] is Handle) ?
  4190. Handle.Unbox(args[ix]) : args[ix];
  4191. return null;
  4192. }
  4193. public static object param_subsig(object[] args) {
  4194. Parameter tgt = (Parameter)Handle.Unbox(args[1]);
  4195. int ix = 2;
  4196. List<Parameter> sig = new List<Parameter>();
  4197. while (ix != args.Length)
  4198. sig.Add((Parameter)Handle.Unbox(args[ix++]));
  4199. object[] pc = tgt.post_constraints;
  4200. Array.Resize(ref pc, pc == null ? 1 : pc.Length + 1);
  4201. pc[pc.Length - 1] = new Signature(tgt.mo.setting, sig.ToArray());
  4202. tgt.post_constraints = pc;
  4203. return null;
  4204. }
  4205. public static object set_signature(object[] args) {
  4206. SubInfo tgt = (SubInfo)Handle.Unbox(args[1]);
  4207. int ix = 2;
  4208. List<Parameter> sig = new List<Parameter>();
  4209. while (ix != args.Length)
  4210. sig.Add((Parameter)Handle.Unbox(args[ix++]));
  4211. tgt.sig = new Signature(tgt.setting, sig.ToArray());
  4212. return null;
  4213. }
  4214. public static object sub_contains_phaser(object[] args) {
  4215. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4216. int p = (int)args[2];
  4217. foreach (SubInfo z in s.children)
  4218. if (z.phaser == p)
  4219. return true;
  4220. return false;
  4221. }
  4222. public static object sub_set_phaser(object[] args) {
  4223. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4224. int p = (int)args[2];
  4225. s.phaser = p;
  4226. if (p == Kernel.PHASER_CATCH)
  4227. s.outer.catch_ = s;
  4228. if (p == Kernel.PHASER_CONTROL)
  4229. s.outer.control = s;
  4230. if (p == Kernel.PHASER_INIT)
  4231. s.setting.init.Add(s, true);
  4232. if (p == Kernel.PHASER_CHECK)
  4233. s.setting.check.Add(s, true);
  4234. if (p == Kernel.PHASER_END)
  4235. s.setting.end.Add(s, true);
  4236. return null;
  4237. }
  4238. public static object sub_set_extend(object[] args) {
  4239. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4240. object[] val = new object[args.Length - 3];
  4241. Array.Copy(args, 3, val, 0, val.Length);
  4242. if (s.extend == null)
  4243. s.extend = new Dictionary<string,object[]>();
  4244. s.extend[(string)args[2]] = val;
  4245. return null;
  4246. }
  4247. public static object sub_get_extend(object[] args) {
  4248. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4249. object[] ret = null;
  4250. if (s.extend != null)
  4251. s.extend.TryGetValue((string)args[2], out ret);
  4252. return ret ?? new object[0];
  4253. }
  4254. public static object sub_finish(object[] args) {
  4255. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4256. s.nam_str = (string)args[2];
  4257. s.nam_refs = new object[args.Length - 3];
  4258. for (int i = 0; i < s.nam_refs.Length; i++)
  4259. s.nam_refs[i] = Handle.Unbox(args[i+3]);
  4260. s.code = RuntimeUnit.JitCompileSub;
  4261. if (s.protopad != null)
  4262. s.protopad.code = s.code;
  4263. return null;
  4264. }
  4265. public static object sub_finish_dispatcher(object[] args) {
  4266. SubInfo s = (SubInfo)Handle.Unbox(args[1]);
  4267. string k = (string)args[2];
  4268. if (k == "regex")
  4269. s.code = Lexer.StandardProtoC;
  4270. else if (k == "multi")
  4271. s.code = Kernel.StandardTypeProtoC;
  4272. else
  4273. return new Exception("Unknown dispatcher type " + k);
  4274. if (s.protopad != null)
  4275. s.protopad.code = s.code;
  4276. return null;
  4277. }
  4278. public static object save_unit(object[] args) {
  4279. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  4280. if (!ru.is_mainish && ru.bottom == null)
  4281. ru.RunMainline();
  4282. if (ru.is_mainish)
  4283. ru.setting.check.Run();
  4284. ru.Save();
  4285. return null;
  4286. }
  4287. public static object run_unit(object[] args) {
  4288. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  4289. bool evalmode = (bool)args[2];
  4290. Kernel.commandArgs = new string[args.Length - 3];
  4291. Array.Copy(args, 3, Kernel.commandArgs, 0, args.Length - 3);
  4292. ru.setting.currentGlobals = ru.globals;
  4293. ru.PrepareEval();
  4294. ru.setting.check.Run();
  4295. ru.setting.init.Run();
  4296. if (!evalmode)
  4297. Kernel.RunMain(ru);
  4298. return null;
  4299. }
  4300. public static object setnames(object[] args) {
  4301. Builtins.execName = (string)args[1];
  4302. Builtins.programName = (string)args[2];
  4303. return null;
  4304. }
  4305. public static object unit_replrun(object[] args) {
  4306. RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
  4307. Frame fret = null;
  4308. ru.setting.check.Run();
  4309. ru.setting.init.Run();
  4310. StashEnt b = ru.setting.GetVar("::PROCESS", "$OUTPUT_USED");
  4311. b.Bind(ru.setting.FalseV);
  4312. Frame ir = Kernel.GetInferiorRoot(ru.setting);
  4313. fret = ru.mainline.protosub.Invoke(ir, Variable.None, null);
  4314. fret.MarkShared();
  4315. Variable r = Kernel.RunInferior(fret);
  4316. if (!b.v.Fetch().mo.mro_raw_Bool.Get(b.v)) {
  4317. Variable pl = Builtins.InvokeMethod("gist", r);
  4318. Console.WriteLine(pl.Fetch().mo.mro_raw_Str.Get(pl));
  4319. }
  4320. return new Handle(fret);
  4321. }
  4322. public static object safemode(object[] args) {
  4323. Kernel.SaferMode = true;
  4324. return null;
  4325. }
  4326. public static object get_codepoint(object[] args) {
  4327. return Niecza.UCD.DataSet.GetCodepoint((string)args[1]);
  4328. }
  4329. public static object getline_init(object[] args) {
  4330. return new Handle( new LineEditor( (string)args[1], (int)args[2] ) );
  4331. }
  4332. public static object getline_edit(object[] args) {
  4333. var edit = (LineEditor) Handle.Unbox(args[1]);
  4334. return edit.Edit( (string)args[2], (string)args[3] );
  4335. }
  4336. public static object getline_close(object[] args) {
  4337. var edit = (LineEditor) Handle.Unbox(args[1]);
  4338. edit.SaveHistory();
  4339. return null;
  4340. }
  4341. }
  4342. }