clu.clu 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. % CLU CLU
  2. %
  3. % These are the top level procedures of the CLU compiler.
  4. BEGIN
  5. # include "clusys/absyn3.clu"
  6. END
  7. % CLU takes an uppercase string which is the name of the input file to compile.
  8. % There are standard defaults when only the first name is given.
  9. clu = proc (fs: string) returns (string);
  10. clu_time: string := nice_date() || " " || nice_time();
  11. timer: realval := time();
  12. head: string := "***** CLU COMPILER " || clu_version() ||
  13. " ***** " || clu_time || " *****\n";
  14. curfile: file;
  15. non_empty: bool;
  16. fname, name1, dir, pstart, errors: string;
  17. globs: globals;
  18. puts(head);
  19. curfile := file$open_read(get_filename(fs))
  20. except open_fail: return ("Source open failed!"); end;
  21. fname := file$name(curfile);
  22. name1 := file$name1(curfile);
  23. dir := file$dir(curfile) || ";";
  24. pstart := dir || name1 || " ";
  25. errors := pstart || "ERRORS";
  26. file$close(curfile);
  27. puts("\tCompiling "); puts(fname); puts("\n\n\tPass 1\n");
  28. % Run the parser
  29. globs := parse(fname, errors);
  30. % Print the ERRORS file, and abort if non-empty.
  31. curfile := file$open_read(errors);
  32. except open_fail: return ("ERRORS file not found!"); end;
  33. non_empty := true;
  34. while non_empty do
  35. if file$eof(curfile)
  36. then non_empty := false
  37. else if char$c2i(file$getc(curfile)) > 31
  38. then begin
  39. file$print(curfile);
  40. putc('\n');
  41. return ("Compilation aborted.");
  42. end;
  43. % Run pass 2
  44. pass2(dir, name1, head, globs)
  45. except pass2_fail(why: string): return (why); end;
  46. file$delete(errors);
  47. % Save statistics
  48. curfile := file$open_append(stat_file())
  49. except open_fail: return ("No CLU STAT file!"); end;
  50. file$puts(curfile, clu_version()); file$putc(curfile, '\t');
  51. file$puts(curfile, xuname()); file$putc(curfile, '\t');
  52. file$puts(curfile, clu_time); file$putc(curfile, '\t');
  53. file$puts(curfile, realstring(time() - timer));
  54. file$putc(curfile, '\t');
  55. file$puts(curfile, fname); file$putc(curfile, '\n');
  56. file$close(curfile);
  57. return ("Compilation complete.");
  58. end clu;
  59. % Pass 2 reads sets up the state of the world
  60. pass2 = proc(dir, name1, head: string, globs: globals) signals (pass2_fail(string));
  61. pstart: string := dir || name1 || " ";
  62. envn: env;
  63. z: zen;
  64. cmac: string := dir || "_CMAC_ " || name1;
  65. out_file: file := file$open_write(cmac)
  66. except open_fail: signal pass2_fail("Output open failed!"); end;
  67. % Set defaults
  68. set_ddsko(out_file);
  69. set_idntab(globals$get_idntab(globs));
  70. set_strtab(globals$get_strtab(globs));
  71. bputs("\n;"); bputs(head);
  72. envn := env$create();
  73. z := zen$create();
  74. pe_environment(globals$get_environment(globs), envn);
  75. puts("\tPass 2\n");
  76. % Process modules
  77. process_mods(globs, envn, z);
  78. file$close(out_file);
  79. no_ddsko();
  80. % Fix up PROC headers
  81. final_phase(pstart, cmac, z);
  82. file$delete(cmac);
  83. end pass2;
  84. % Read in and process each module.
  85. process_mods = proc(globs: globals, envn: env, z: zen);
  86. need_fake: bool := true;
  87. while globals$still_modules(globs) do
  88. begin
  89. mod: module := pe_module(globals$next_module(globs), envn);
  90. zen$new_module(z, envn, get_module_name(mod));
  91. tc_module(mod);
  92. tagcase mod in
  93. p: if need_fake
  94. then begin
  95. bputs("\ncluster ,0,0\n");
  96. need_fake := false;
  97. end;
  98. c: if ~need_fake
  99. then begin
  100. bputs("\nretsulc\n");
  101. need_fake := true;
  102. end;
  103. end;
  104. cg_module(z, mod);
  105. putc('\n');
  106. end;
  107. if need_fake then return;
  108. bputs("\nretsulc\n");
  109. end process_mods;
  110. % Run the typechecker.
  111. tc_module = proc (mod: module);
  112. mname: string;
  113. the_du: DU;
  114. the_ver: version;
  115. if ~type_checking() then return;
  116. mname := get_module_name(mod);
  117. the_du := DU$create(name$u(mname), "test");
  118. the_ver := version$create(the_du);
  119. type_checker(mod, the_ver, the_alist());
  120. end tc_module;
  121. final_phase = proc (pstart: string, cmac: string, z: zen) signals (pass2_fail(string));
  122. in_file: file := file$open_read(cmac)
  123. except open_fail: signal pass2_fail("_CMAC_ file not found!"); end;
  124. out_file: file := file$open_write(pstart || "_CLUMA")
  125. except open_fail: signal pass2_fail("Output open failed!"); end;
  126. file$puts(out_file, ".insrt clusys;alpha >\n");
  127. repeat
  128. begin
  129. s: string := file$gets(in_file, '\n');
  130. file$puts(out_file,
  131. (if s = "proc" then zen$next_head(z) else s) || "\n");
  132. end
  133. until file$eof(in_file);
  134. file$puts(out_file, "\n.insrt clusys;omega >\n");
  135. file$rename(out_file, pstart || "CLUMAC");
  136. file$close(out_file);
  137. file$close(in_file);
  138. end final_phase;
  139. % Return a module's name.
  140. get_module_name = proc (m: module) returns (string);
  141. tagcase m in
  142. p: return (idn$getstring(m.name));
  143. c: return (idn$getstring(m.name));
  144. end;
  145. end get_module_name;
  146. % Try to find a source file name.
  147. get_filename = proc (fs: string) returns (string);
  148. ns: string;
  149. if (string$index(fs, ":") >= 0) |
  150. (string$index(fs, ";") >= 0) |
  151. (string$index(fs, " ") >= 0)
  152. then return (fs);
  153. ns := fs || " CLU";
  154. if file$exists(ns) then return (ns);
  155. if file$exists("ARC:" || ns) then return ("ARC:" || ns);
  156. if file$exists("AR1:" || ns) then return ("AR1:" || ns);
  157. if file$exists("AR2:" || ns) then return ("AR2:" || ns);
  158. if file$exists("AR3:" || ns) then return ("AR3:" || ns);
  159. if file$exists("AR4:" || ns) then return ("AR4:" || ns);
  160. if file$exists(fs || " >") then return (fs || " >");
  161. if file$exists("ARC:" || fs) then return ("ARC:" || fs);
  162. if file$exists("AR1:" || fs) then return ("AR1:" || fs);
  163. if file$exists("AR2:" || fs) then return ("AR2:" || fs);
  164. if file$exists("AR3:" || fs) then return ("AR4:" || fs);
  165. return (fs || " >");
  166. end get_filename;
  167. % This cluster holds stuff which the parser returns.
  168. globals = cluster is create, % Create a global
  169. get_idntab, % Return the identifier table
  170. get_strtab, % Return the string table
  171. get_environment,% Return environment
  172. next_module, % Return the next module
  173. still_modules; % Test if still modules left
  174. as = array[string];
  175. idntab = as;
  176. strtab = as;
  177. am = array[module];
  178. % These will eventually go away,
  179. idntabfake = string;
  180. strtabfake = oneof[n: null, tab: strtab];
  181. environmentfake = string;
  182. amfake = oneof[n: null, f: file];
  183. % The rep will be unfaked,
  184. rep = record[itab: idntabfake,
  185. stab: strtabfake,
  186. envir: environmentfake,
  187. mods: amfake];
  188. % And the operations rewritten.
  189. create = oper (tab: string, par: string) returns (cvt);
  190. return ({itab: tab,
  191. stab: strtabfake$make_n(nil),
  192. envir: par,
  193. mods: amfake$make_n(nil)});
  194. end create;
  195. get_idntab = oper (g: cvt) returns (idntab);
  196. fake: string := g.itab;
  197. tabfile: file := file$open_readobj(fake);
  198. itab: idntab := file$readobj(tabfile);
  199. g.stab := strtabfake$make_tab(file$readobj(tabfile));
  200. file$close(tabfile);
  201. file$delete(fake);
  202. return (itab);
  203. end get_idntab;
  204. get_strtab = oper (g: cvt) returns (strtab);
  205. fake: strtabfake := g.stab;
  206. tagcase fake in
  207. tab: return (fake);
  208. end;
  209. end get_strtab;
  210. get_environment = oper (g: cvt) returns (environment);
  211. fake: string := g.envir;
  212. parfile: file := file$open_readobj(fake);
  213. envir: environment := FUDGE(file$readobj(parfile));
  214. g.mods := amfake$make_f(parfile);
  215. return (envir);
  216. end get_environment;
  217. still_modules = oper (g: cvt) returns (bool);
  218. fake: amfake := g.mods;
  219. tagcase fake in
  220. f: if file$eof(fake)
  221. then begin
  222. ns: string := file$name(fake);
  223. file$close(fake);
  224. file$delete(ns);
  225. return (false);
  226. end
  227. else return (true);
  228. end;
  229. end still_modules;
  230. next_module = oper (g: cvt) returns (module);
  231. fake: amfake := g.mods;
  232. tagcase fake in
  233. f: return (FUDGE(file$readobj(fake)));
  234. end;
  235. end next_module;
  236. end globals;
  237. % For error messages
  238. err1 = proc (lineno: int, message: string)
  239. if (lineno >= 0) then putc ('\n');
  240. if (lineno > 0) then {putd (lineno); puts (": ")};
  241. puts (message);
  242. end err1;