ncg3.clu 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. % NCG3 CLU special for NCLU
  2. BEGIN
  3. # include "clu/absyn2.clu"
  4. idntype = oneof [ var, parm, op: typespec,
  5. undec: null ];
  6. END
  7. % Expressions are emitted much like statements, in a big
  8. % switch with lots of routine calls. A few are emitted here,
  9. % most have their own routines.
  10. cg_expr = proc (z: zen, x: expr);
  11. e: exprabs := expr$d(x);
  12. tagcase e in
  13. % Binary expressions.
  14. add: cg_binexp(z, "add", e);
  15. sub: cg_binexp(z, "sub", e);
  16. mul: cg_binexp(z, "mul", e);
  17. div: cg_binexp(z, "div", e);
  18. pow: cg_binexp(z, "power", e);
  19. and: cg_binexp(z, "and", e);
  20. or: cg_binexp(z, "or", e);
  21. cat: cg_binexp(z, "concat", e);
  22. mod: cg_binexp(z, "mod", e);
  23. eq: cg_binexp(z, "equal", e);
  24. ne: begin
  25. em$las("NOT");
  26. cg_binexp(z, "equal", e);
  27. em$ra();
  28. end;
  29. lt: cg_binexp(z, "lt", e);
  30. le: cg_binexp(z, "le", e);
  31. ge: cg_binexp(z, "ge", e);
  32. gt: cg_binexp(z, "gt", e);
  33. % Unary expressions
  34. not: cg_not(z, e);
  35. minus: cg_minus(z, e);
  36. upop: cg_expr(z, e);
  37. downop: cg_expr(z, e);
  38. % Assignments
  39. assn: cg_assn(z, e, true);
  40. % Condition expressions
  41. condexp:begin
  42. em$lcondl();
  43. cg_expr(z, e.test);
  44. cg_expr(z, e.t);
  45. em$ss(") (T");
  46. cg_expr(z, e.f);
  47. em$ss(")>");
  48. end;
  49. % Procedure and operation invocations
  50. invoke: cg_invoke(z, e);
  51. % Object constructors
  52. reccon: cg_reccon(z, e);
  53. arrcon: cg_arrcon(z, e);
  54. fill: cg_fill(z, e);
  55. boolcon: if e then em$t() else em$nix();
  56. stringcon: cg_stringcon(z, e);
  57. intcon: em$ds(e);
  58. charcon: begin
  59. em$ss("#CHARACTER");
  60. em$ds(char$c2i(e));
  61. end;
  62. typecon: cg_typespec (z, e);
  63. nilcon: em$ss ("NIL");
  64. op: cg_op(z, e);
  65. % Right hand sides for cell refs
  66. recref: cg_callstring (z, gt_expr (z, e.r),
  67. "get_" || name$d(e.sel), [e.r]);
  68. arrayref:
  69. cg_callstring (z, gt_expr (z, e.l), "fetch", [e.l,e.r]);
  70. % array fetch can signal an error
  71. idn: cg_idn (z, e);
  72. caste: cg_caste (z, e);
  73. Zforce: cg_force (z, e);
  74. % Fancy procedure objects
  75. oneup: cg_oneup (z, e);
  76. recget: cg_recget (z, e);
  77. recput: cg_recput (z, e);
  78. Zdu: cg_du (z, e);
  79. out: oops (z, "Illegal expression to cg_expr");
  80. end;
  81. end cg_expr;
  82. % Now let's get rid of some small routines that have been
  83. % used above. There isn't much to say about them.
  84. cg_binexp = proc (z: zen, s: string, be: binexp);
  85. l: expr := be.l;
  86. r: expr := be.r;
  87. cg_callstring(z, gt_binexp(z, l, r), s, [l, r] );
  88. end cg_binexp;
  89. cg_not = proc (z: zen, e: expr);
  90. cg_callit(z, "not", [e]);
  91. end cg_not;
  92. cg_minus = proc (z: zen, e: expr);
  93. cg_callit(z, "minus", [e]);
  94. end cg_minus;
  95. cg_exprlist = proc (z: zen, el: exprlist);
  96. for i:int := exprlist$low(el) to exprlist$high(el)
  97. do cg_expr(z, el[i]);
  98. end cg_exprlist;
  99. % The record constructor routine must emit a sorted list
  100. % of expressions since that is what the canonical form of the
  101. % record is. As in declarations, the expressions are evaluated
  102. % once per identifier. In this case, once per selector.
  103. % This approach is quite common in CLU.
  104. %
  105. cg_reccon = proc (z: zen, r: reccon);
  106. ft = record[ s: string, e: expr];
  107. at = array of ft;
  108. f: ft;
  109. a: at := at$new();
  110. for i:int := reccon$low(r) to reccon$high(r)
  111. do begin
  112. fd: field := r[i];
  113. sels: namelist := fd.sels;
  114. for j:int := namelist$low(sels) to namelist$high(sels)
  115. do at$extendh(a, {s: name$d (sels[j]),
  116. e: fd.val});
  117. end;
  118. for i:int := at$low(a) to at$high(a)-1
  119. do for j:int := i+1 to at$high(a)
  120. do if a[i].s > a[j].s
  121. then begin
  122. f := a[i];
  123. a[i] := a[j];
  124. a[j] := f;
  125. end;
  126. em$lb(); % A record is a MUDDLE vector
  127. for i:int := at$low(a) to at$high(a)
  128. do begin
  129. f := a[i]; % f is a type kludge
  130. cg_expr(z, f.e);
  131. end;
  132. em$rb();
  133. end cg_reccon;
  134. % There are two array constructors. One creates an array
  135. % from an optional low bound and list of values, the other fills
  136. % an array with a single value between two limits (inclusive).
  137. % The fill constructor evaluates the expression it is filling
  138. % with only once, assigning to the elements by sharing. The
  139. % constructor which fills with a list of values also assigns by
  140. % sharing.
  141. %
  142. cg_arrcon = proc (z: zen, ac: arrcon);
  143. cg_sexp(z, "<NEWARR", ac.l); % low limit
  144. cg_exprlist(z, ac.vals); % list of expressions
  145. em$ra();
  146. end cg_arrcon;
  147. cg_fill = proc (z: zen, f: fill);
  148. cg_sbexp(z, "<ARRAY$FILL", f.r.l, f.r.h);
  149. cg_expr(z, f.val); % value to fill with
  150. em$ra();
  151. end cg_fill;
  152. % This routine emits a load of an identifier
  153. % (needs expression and closing bracket).
  154. cg_lhsidn = proc (z: zen, id: idn);
  155. em$lset(); % emit <SET
  156. cg_idlit(z, id); % and identifier
  157. idn$set_change(id); % show identifier changed
  158. end cg_lhsidn;
  159. % This routine emits an identifier as a literal.
  160. cg_idlit = proc (z: zen, id: idn);
  161. idt: idntype := idn$get_type (id);
  162. tagcase idt in
  163. var, parm: em$s ("$");
  164. undec, op: em$s (":");
  165. end;
  166. em$ss (idn$getstring (id));
  167. end cg_idlit;
  168. % This routine puts out the right-hand-side identifiers
  169. cg_idn = proc (z: zen, id: idn);
  170. idt: idntype := idn$get_type (id);
  171. tagcase idt in
  172. var, parm: em$s (".$");
  173. undec, op: em$s (",:");
  174. end;
  175. em$ss (idn$getstring (id));
  176. end cg_idn;
  177. % This routine obtains the values of procedure modules.
  178. cg_du = proc (z: zen, d: du);
  179. em$s (",:");
  180. em$ss (name$d (du$get_unique (d)));
  181. end cg_du;
  182. % To generate a range test, call cg_range...
  183. cg_range = proc (z: zen, ex: expr, r: range);
  184. cg_trange(z, gt_expr(z, ex), ex, r);
  185. end cg_range;
  186. % cg_trange emits code which yields a boolean result which
  187. % is true if the expression is in the range.
  188. %
  189. cg_trange = proc (z: zen,
  190. ty: typespec,
  191. ex: expr,
  192. r: range);
  193. em$las("NOT <OR");
  194. cg_callstring(z, ty, "lt", [ex, r.l]);
  195. cg_callstring(z, ty, "gt", [ex, r.h]);
  196. em$rra();
  197. end cg_trange;
  198. % If only the cluster operation and arguments are known,
  199. % use cg_callop, which finds out a few things and passes the buck.
  200. cg_callop = proc (z: zen,
  201. x: clustop,
  202. el: exprlist);
  203. cg_callstring( z,
  204. x.typ,
  205. name$d (x.op),
  206. el);
  207. end cg_callop;
  208. % If only the operation name and the expression list
  209. % are known, use cg_callit. It assumes that the type of
  210. % the operation is the same as the type of the first
  211. % expression in the argument list.
  212. cg_callit = proc (z: zen, s: string, el: exprlist);
  213. cg_callstring(z, gt_expr(z, exprlist$bottom(el)), s, el);
  214. end cg_callit;
  215. % When the same information is known as in
  216. % cg_callstring but the special cases fail, this routine
  217. % is used. It gets the operation directly from the type,
  218. % which may be very inefficient, but it is very general.
  219. % This is used mostly for record and oneof operations,
  220. % and for parameter type operations.
  221. cg_gencall = proc(z: zen, % code gen environment
  222. ty: typespec, % operation type
  223. s: string, % operation name
  224. el: exprlist); % argument list
  225. em$las("APPLYOP"); % Open form, call support for invocations
  226. cg_typespec (z, ty); % Type object
  227. em$ss(s); % Selector name
  228. cg_exprlist(z, el); % Arguments to operation
  229. cg_escope(zen$escope(z)); % Error Handler Specification
  230. em$ra(); % Close up the form
  231. end cg_gencall;
  232. % If the operation type, name and arguments are available,
  233. % cg_callstring will take care of everything for you.
  234. cg_callstring = proc ( z: zen, % environment
  235. t: typespec, % operation type
  236. s: string, % operation name
  237. el: exprlist); % argument list
  238. ty: typespecabs := typespec$dn (t);
  239. es: int := zen$escope(z); % Error scope number in this context
  240. tagcase ty in
  241. oneoftype:
  242. begin;
  243. if (exprlist$size (el) = 1 & s ~= "copy")
  244. then begin
  245. op, sel: string;
  246. need_sigs: bool := false;
  247. if string$substr (s, 0, 5) = "make_"
  248. then begin op := "MAKE"; sel := string$rest (s, 5); end;
  249. else if string$substr (s, 0, 3) = "is_"
  250. then begin op := "IS"; sel := string$rest (s, 3); end;
  251. else if string$substr (s, 0, 6) = "value_"
  252. then begin
  253. op := "VALUE";
  254. sel := string$rest (s, 6);
  255. need_sigs := true;
  256. end;
  257. else begin
  258. oops (z, "Bad ONEOF operation: " || s);
  259. return;
  260. end;
  261. em$las("ONEOF$" || op);
  262. em$ds(gk_tag(z, ty, name$u(sel)) + 1);
  263. cg_expr(z, exprlist$bottom(el));
  264. if (need_sigs & es > 0) then cg_escope (es);
  265. em$ra ();
  266. end;
  267. else case s in
  268. "equal", "similar", "copy", "encode", "decode":
  269. cg_gencall(z, t, s, el);
  270. out: oops (z, "Bad ONEOF operation: " || s);
  271. end;
  272. end;
  273. recordtype:
  274. case s in
  275. "equal","copy1": cg_op_call(z, "RECORD", s, el, false);
  276. "copy","similar1","similar","encode","decode":
  277. cg_gencall(z, t, s, el);
  278. out: begin % "get_*" or "put_*" operations
  279. em$las("RECORD$" || string$substr(s, 0, 3));
  280. em$ds(gk_recordop(z, ty, s) + 1);
  281. cg_exprlist(z, el);
  282. em$ra ();
  283. end;
  284. end;
  285. atype: begin;
  286. id: idn := ty.name;
  287. if (if gk_is_fake (z, id) then true else gk_is_parm (z, id))
  288. then cg_gencall (z, t, s, el)
  289. else cg_op_callp (z, gs$idname (id), s, el,
  290. ty.args, true);
  291. end;
  292. parm: cg_gencall (z, t, s, el);
  293. dutype: begin;
  294. d: DU := ty.mod;
  295. if (d ~= get_array_DU ()) then
  296. begin
  297. cg_du_callp (z, ty.mod, s, el, ty.args, true);
  298. return;
  299. end;
  300. case s in
  301. "trim","fill","fetch","bottom","top","store","remh","reml":
  302. cg_op_call (z, "ARRAY", s, el, true);
  303. "fill_copy":
  304. cg_du_callp (z, ty.mod, s, el, ty.args, true);
  305. "similar","similar1","copy":
  306. cg_du_callp (z, ty.mod, s, el, ty.args, false);
  307. out: cg_op_call (z, "ARRAY", s, el, false);
  308. end;
  309. end;
  310. inttype: case s in
  311. "div","power","mod":
  312. cg_op_call(z, "INT", s, el, true);
  313. out: cg_op_call(z, "INT", s, el, false);
  314. end;
  315. stringtype: case s in
  316. "fetch","substr","rest":
  317. cg_op_call(z, "STRING", s, el, true);
  318. out: cg_op_call(z, "STRING", s, el, false);
  319. end;
  320. chartype: case s in
  321. "i2c": cg_op_call(z, "CHAR", s, el, true);
  322. out: cg_op_call(z, "CHAR", s, el, false);
  323. end;
  324. booltype: cg_op_call(z, "BOOL", s, el, false);
  325. out: begin
  326. em$la();
  327. cg_simpop(z, t, s);
  328. cg_exprlist(z, el);
  329. if (es>0) then cg_escope(es);
  330. em$ra();
  331. end;
  332. end;
  333. end cg_callstring;