LSC.Mod.txt 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. MODULE LSC; (*Lola System Compiler, NW 8.1.95 / 27.8.2018 for RISC (LSCX)*)
  2. IMPORT Texts, Oberon, LSB, LSS;
  3. VAR sym: INTEGER;
  4. err: BOOLEAN; (*used at end of Unit*)
  5. top, bot, undef: LSB.Object;
  6. factor: PROCEDURE (VAR x: LSB.Item); (*to avoid forward references*)
  7. expression: PROCEDURE (VAR x: LSB.Item);
  8. Unit: PROCEDURE (VAR locals: LSB.Object);
  9. W: Texts.Writer;
  10. PROCEDURE Err(n: INTEGER);
  11. BEGIN LSS.Mark("type error"); Texts.WriteInt(W, n, 4);
  12. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  13. END Err;
  14. PROCEDURE Log(m: LONGINT): LONGINT;
  15. VAR n: LONGINT;
  16. BEGIN n := 1;
  17. WHILE m > 1 DO m := m DIV 2; INC(n) END ;
  18. RETURN n
  19. END Log;
  20. PROCEDURE New(tag: INTEGER; a, b: LSB.Item): LSB.Item;
  21. VAR z: LSB.Item;
  22. BEGIN NEW(z); z.tag := tag; z.a := a; z.b := b; z.val := b.val; RETURN z
  23. END New;
  24. PROCEDURE NewObj(class: INTEGER): LSB.Object; (*insert at end, before BIT*)
  25. VAR new, x: LSB.Object;
  26. BEGIN x := top;
  27. WHILE (x.next # bot) & (x.next.name # LSS.id) DO x := x.next END ;
  28. IF x.next = bot THEN
  29. NEW(new); new.name := LSS.id; new.tag := class; new.next := bot; x.next := new
  30. ELSE LSS.Mark("mult def"); new := x
  31. END ;
  32. RETURN new
  33. END NewObj;
  34. PROCEDURE ThisObj(id: LSS.Ident): LSB.Object; (*find object with name = identifier last read*)
  35. VAR x: LSB.Object;
  36. BEGIN x := top.next;
  37. WHILE (x # NIL) & (x.name # id) DO x := x.next END ;
  38. IF x = NIL THEN LSS.Mark("undef"); x := undef END ;
  39. RETURN x
  40. END ThisObj;
  41. PROCEDURE CheckTypes(x, y, z: LSB.Item); (*z.type = result type*)
  42. VAR xtyp, ytyp: LSB.Type;
  43. BEGIN xtyp := x.type; ytyp := y.type; z.type := xtyp; z.size := x.size; z.val := x.val;
  44. IF xtyp = LSB.bitType THEN
  45. IF ytyp = LSB.integer THEN (* b + 0 *)
  46. IF y.val >= 2 THEN Err(20); LSS.Mark("only 0 or 1") END
  47. ELSIF ytyp = LSB.string THEN (* b + {...} *) Err(21)
  48. ELSIF ytyp # LSB.bitType THEN Err(22)
  49. END
  50. ELSIF xtyp IS LSB.ArrayType THEN
  51. IF xtyp(LSB.ArrayType).eltyp = LSB.bitType THEN
  52. IF (ytyp IS LSB.ArrayType) & (xtyp(LSB.ArrayType).eltyp = LSB.bitType) THEN
  53. IF xtyp.size # ytyp.size THEN Err(33) END (* x + y *)
  54. ELSIF ytyp = LSB.integer THEN (* w + 5 *)
  55. IF xtyp.size < Log(y.val) THEN Err(30) END
  56. ELSIF ytyp = LSB.string THEN (*x + {...} *)
  57. IF xtyp.size # y.size THEN Err(31) END
  58. ELSE Err(34)
  59. END
  60. ELSIF (ytyp IS LSB.ArrayType) & (xtyp(LSB.ArrayType).eltyp = ytyp(LSB.ArrayType).eltyp) THEN
  61. IF (xtyp.size # ytyp.size) THEN Err(40) END
  62. ELSE Err(41)
  63. END
  64. ELSIF xtyp = LSB.string THEN
  65. IF ytyp = LSB.bitType THEN (* {...} + b *) Err(12)
  66. ELSIF (ytyp IS LSB.ArrayType) & (ytyp(LSB.ArrayType).eltyp = LSB.bitType) THEN (* {...} + w *)
  67. IF x.size # ytyp.size THEN Err(13) END
  68. ELSIF ytyp = LSB.integer THEN (* {...} + 5*)
  69. IF x.size < Log(y.val) THEN Err(10) END
  70. ELSIF ytyp = LSB.string THEN (* {...} + {...} *)
  71. IF x.size # y.size THEN Err(11) END ;
  72. ELSE Err(14)
  73. END
  74. ELSIF xtyp = LSB.integer THEN
  75. IF (ytyp IS LSB.ArrayType) & (ytyp(LSB.ArrayType).eltyp = LSB.bitType) THEN (* 5 + w *)
  76. IF Log(x.val) > ytyp.size THEN Err(3); LSS.Mark("const too large") END
  77. ELSIF ytyp = LSB.bitType THEN (* 5 + b *)
  78. IF x.val >= 2 THEN Err(2) END
  79. ELSIF ytyp = LSB.integer THEN (* 5 + 5 *)
  80. ELSIF ytyp = LSB.string THEN (* 5 + {...} *)
  81. IF Log(x.val) > y.size THEN Err(12) END
  82. ELSE Err(4)
  83. END
  84. END
  85. END CheckTypes;
  86. PROCEDURE selector(VAR x: LSB.Item);
  87. VAR y, z: LSB.Item; obj: LSB.Object;
  88. eltyp: LSB.Type; len, kind: LONGINT;
  89. BEGIN
  90. WHILE (sym = LSS.lbrak) OR (sym = LSS.period) DO
  91. IF sym = LSS.lbrak THEN
  92. eltyp := x.type(LSB.ArrayType).eltyp; LSS.Get(sym); expression(y);
  93. IF sym = LSS.colon THEN (*range*)
  94. LSS.Get(sym); expression(z);
  95. IF (y.tag = LSB.lit) & (z.tag = LSB.lit) THEN
  96. len := y.val - z.val + 1; y := New(LSB.range, y, z); x := New(LSB.sel, x, y); x.type := LSB.string; x.size := len
  97. END
  98. ELSE kind := x.val; x := New(LSB.sel, x, y); x.type := eltyp; x.val := kind
  99. END ;
  100. IF sym = LSS.rbrak THEN LSS.Get(sym) ELSE LSS.Mark("rbrak ?") END
  101. ELSE (*sym = LSS.period*) LSS.Get(sym); factor(y);
  102. IF (y.tag = LSB.lit) & (y.val >= x.type.len) THEN LSS.Mark("too large") END ;
  103. eltyp := x.type(LSB.ArrayType).eltyp; kind := x.val; x := New(LSB.sel, x, y); x.type := eltyp; x.val := kind
  104. END
  105. END
  106. END selector;
  107. PROCEDURE elem(VAR x: LSB.Item; VAR len: LONGINT);
  108. VAR y, z: LSB.Item; m, n: LONGINT;
  109. BEGIN expression(x);
  110. IF (x.type = LSB.integer) OR (x.type = LSB.string) THEN m := x.size ELSE m := x.type.size END ;
  111. IF sym = LSS.repl THEN
  112. LSS.Get(sym);
  113. IF sym = LSS.integer THEN
  114. NEW(y); y.tag := LSB.lit; n := LSS.val; y.val := n; y.type := LSB.integer; LSS.Get(sym);
  115. x := New(LSB.repl, x, y)
  116. END
  117. ELSE n := 1
  118. END ;
  119. len := m*n
  120. END elem;
  121. PROCEDURE constructor(VAR x: LSB.Item);
  122. VAR y: LSB.Item; n, len: LONGINT;
  123. BEGIN elem(x, len);
  124. WHILE sym = LSS.comma DO
  125. LSS.Get(sym); elem(y, n); INC(len, n); x := New(LSB.cons, x, y); x.val := len
  126. END ;
  127. x.size := len; x.type := LSB.string;
  128. IF sym = LSS.rbrace THEN LSS.Get(sym) ELSE LSS.Mark("rbrace ?") END
  129. END constructor;
  130. PROCEDURE factor0(VAR x: LSB.Item);
  131. VAR obj: LSB.Object; y, z: LSB.Item;
  132. n, len: LONGINT; t: LSB.ArrayType;
  133. BEGIN
  134. IF sym = LSS.ident THEN
  135. x := ThisObj(LSS.id); LSS.Get(sym);
  136. IF x.tag = LSB.var THEN selector(x)
  137. ELSIF x.tag = LSB.const THEN n := x.b.val; NEW(x); x.tag := LSB.lit; x.val := n; x.type := LSB.integer
  138. ELSE LSS.Mark("bad factor")
  139. END
  140. ELSIF sym = LSS.lparen THEN
  141. LSS.Get(sym); expression(x);
  142. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END
  143. ELSIF sym = LSS.integer THEN
  144. NEW(x); x.tag := LSB.lit; x.val := LSS.val; x.type := LSB.integer; LSS.Get(sym);
  145. IF sym = LSS.apo THEN LSS.Get(sym);
  146. IF sym = LSS.integer THEN
  147. len := LSS.val; LSS.Get(sym);
  148. IF len < Log(x.val) THEN LSS.Mark("value too large") END
  149. ELSE LSS.Mark("integer ?"); len := 0
  150. END
  151. ELSE len := 0
  152. END ;
  153. x.size := len
  154. ELSIF sym = LSS.not THEN
  155. LSS.Get(sym); factor(x); y := New(LSB.not, NIL, x); y.type := x.type; y.size := x.size; x := y
  156. ELSIF sym = LSS.lbrace THEN LSS.Get(sym); constructor(x)
  157. ELSE LSS.Mark("bad factor")
  158. END
  159. END factor0;
  160. PROCEDURE term(VAR x: LSB.Item);
  161. VAR y, z: LSB.Item; op: INTEGER;
  162. BEGIN factor(x);
  163. WHILE (sym >= LSS.times) & (sym <= LSS.and) DO
  164. IF sym = LSS.and THEN op := LSB.and
  165. ELSIF sym = LSS.times THEN op := LSB.mul
  166. ELSIF sym = LSS.div THEN op := LSB.div
  167. END ;
  168. LSS.Get(sym); factor(y); z := New(op, x, y); CheckTypes(x, y, z); x := z
  169. END
  170. END term;
  171. PROCEDURE SimpleExpression(VAR x: LSB.Item);
  172. VAR y, z: LSB.Item; op: INTEGER;
  173. BEGIN
  174. IF sym = LSS.minus THEN LSS.Get(sym); term(y);
  175. IF y.tag = LSB.lit THEN x := y; x.val := -y.val
  176. ELSE x := New(LSB.sub, NIL, y); x.type := y.type; x.size := y.size
  177. END
  178. ELSIF sym = LSS.plus THEN LSS.Get(sym); term(x);
  179. ELSE term(x)
  180. END ;
  181. WHILE (sym >= LSS.plus) & (sym <= LSS.xor) DO
  182. IF sym = LSS.or THEN op := LSB.or
  183. ELSIF sym = LSS.xor THEN op := LSB.xor
  184. ELSIF sym = LSS.plus THEN op := LSB.add
  185. ELSIF sym = LSS.minus THEN op := LSB.sub
  186. END ;
  187. LSS.Get(sym); term(y); z := New(op, x, y); CheckTypes(x, y, z); x := z
  188. END
  189. END SimpleExpression;
  190. PROCEDURE UncondExpression(VAR x: LSB.Item);
  191. VAR y, z: LSB.Item; rel: INTEGER;
  192. BEGIN SimpleExpression(x);
  193. IF (sym >= LSS.eql) & (sym <= LSS.geq) THEN
  194. IF sym = LSS.eql THEN rel := LSB.eql
  195. ELSIF sym = LSS.neq THEN rel := LSB.neq
  196. ELSIF sym = LSS.lss THEN rel := LSB.lss
  197. ELSIF sym = LSS.geq THEN rel := LSB.geq
  198. ELSIF sym = LSS.leq THEN rel := LSB.leq
  199. ELSE rel := LSB.gtr
  200. END ;
  201. LSS.Get(sym); SimpleExpression(y); z := New(rel, x, y); CheckTypes(x, y, z); z.type := LSB.bitType; x := z
  202. END
  203. END UncondExpression;
  204. PROCEDURE expression0(VAR x: LSB.Item);
  205. VAR y, z, w: LSB.Item;
  206. BEGIN UncondExpression(x);
  207. IF sym = LSS.then THEN
  208. IF x.type # LSB.bitType THEN LSS.Mark("Boolean?") END ;
  209. LSS.Get(sym); expression(y);
  210. IF sym = LSS.colon THEN
  211. LSS.Get(sym); expression(z); w := New(LSB.else, y, z); CheckTypes(y, z, w);
  212. x := New(LSB.then, x, w); x.type := w.type; x.size := w.size
  213. ELSE LSS.Mark("colon ?")
  214. END
  215. END
  216. END expression0;
  217. PROCEDURE CheckAssign(x, y: LSB.Item);
  218. VAR xtyp, ytyp: LSB.Type;
  219. BEGIN xtyp := x.type; ytyp := y.type;
  220. IF xtyp # ytyp THEN
  221. IF xtyp = LSB.bitType THEN
  222. IF (ytyp # LSB.integer) OR (y.val >= 2) THEN Err(70); END
  223. ELSIF xtyp IS LSB.ArrayType THEN
  224. IF xtyp(LSB.ArrayType).eltyp = LSB.bitType THEN
  225. IF (ytyp IS LSB.ArrayType) & (xtyp(LSB.ArrayType).eltyp = LSB.bitType) THEN (*w := w*)
  226. IF xtyp.size # ytyp.size THEN Err(71) END (* x + y *)
  227. ELSIF ytyp = LSB.integer THEN (* w := 5 *)
  228. IF xtyp.size < Log(y.val) THEN Err(72) END
  229. ELSIF ytyp = LSB.string THEN (* w := {...} *)
  230. IF xtyp.size # y.size THEN Err(73) END
  231. ELSE Err(74)
  232. END
  233. ELSE Err(74)
  234. END
  235. END
  236. END
  237. END CheckAssign;
  238. PROCEDURE Param(fpar: LSB.Object; VAR apar: LSB.Item);
  239. VAR y, z: LSB.Item;
  240. BEGIN expression(y); apar := New(LSB.next, NIL, y); CheckAssign(fpar, y);
  241. IF fpar.val IN {3, 4} THEN (*OUT or INOUT parameter*)
  242. IF ~(y.tag IN {3, 7}) THEN (*actual param is expression?*) LSS.Mark("bad actual param")
  243. ELSIF y.b = NIL THEN y.b := undef
  244. END
  245. END
  246. END Param;
  247. PROCEDURE Statement;
  248. VAR x, y, z, w, apar, npar: LSB.Item;
  249. unit: LSB.UnitType; fpar: LSB.Object;
  250. BEGIN
  251. IF sym < LSS.ident THEN LSS.Mark("bad factor");
  252. REPEAT LSS.Get(sym) UNTIL sym >= LSS.ident
  253. END ;
  254. IF sym = LSS.ident THEN
  255. x := ThisObj(LSS.id); z := x; LSS.Get(sym); selector(z);
  256. IF sym = LSS.becomes THEN LSS.Get(sym);
  257. IF x.val >= 5 THEN LSS.Mark("assignment to read-only") END ;
  258. IF (x.b # NIL) & ~(x.type IS LSB.ArrayType) THEN LSS.Mark("mult assign") END ;
  259. expression(y); CheckAssign(z, y); x.b := y; (*tricky*)
  260. IF z # x THEN x.a := z.b; x.val := 1 (*overwriting clk field x.a *) END
  261. ELSIF sym = LSS.lparen THEN LSS.Get(sym); (*unit instantiation*)
  262. IF x.type IS LSB.UnitType THEN
  263. unit := x.type(LSB.UnitType); fpar := unit.firstobj;
  264. IF sym # LSS.rparen THEN
  265. Param(fpar, apar); x.b := apar; fpar := fpar.next;
  266. WHILE sym # LSS.rparen DO
  267. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  268. Param(fpar, npar);
  269. IF fpar.tag >= 3 THEN fpar := fpar.next; apar.a := npar; apar := npar
  270. ELSE LSS.Mark("too many params")
  271. END
  272. END ;
  273. IF fpar.val >= 3 THEN LSS.Mark("too few params") END
  274. END ;
  275. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END
  276. ELSE LSS.Mark("not a module")
  277. END
  278. ELSE LSS.Mark("bad statement")
  279. END
  280. ELSIF sym = LSS.ts THEN (*tri-state*) LSS.Get(sym);
  281. IF sym = LSS.lparen THEN LSS.Get(sym) ELSE LSS.Mark("( missing") END ;
  282. IF sym = LSS.ident THEN
  283. x := ThisObj(LSS.id); x.b := undef; (*INOUT parameter*)
  284. IF x.val # 5 THEN LSS.Mark("not INOUT") END ;
  285. LSS.Get(sym);
  286. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  287. IF sym = LSS.ident THEN y := ThisObj(LSS.id); CheckAssign(x, y); y.b := undef END ; (*output from gate*)
  288. LSS.Get(sym);
  289. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  290. expression(z);
  291. IF (z.tag = LSB.lit) & (z.val <= 1) THEN z.type := LSB.bitType END ;
  292. CheckAssign(x, z); LSS.Get(sym);
  293. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  294. expression(w); (*control*)
  295. IF w.type # LSB.bitType THEN CheckAssign(x, w) END ;
  296. w := New(LSB.next, z, w); x.b := New(LSB.ts, y, w);
  297. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark(") missing") END
  298. END
  299. END
  300. END Statement;
  301. PROCEDURE StatSequence;
  302. BEGIN Statement;
  303. WHILE sym <= LSS.semicolon DO
  304. IF sym < LSS.semicolon THEN LSS.Mark("semicolon missing?") END ;
  305. WHILE sym = LSS.semicolon DO LSS.Get(sym) END ;
  306. Statement
  307. END ;
  308. IF sym = LSS.end THEN LSS.Get(sym) ELSE LSS.Mark("END ?") END
  309. END StatSequence;
  310. (*---------------------------------------------------*)
  311. (* for variables and registers,, obj.val has the meaning
  312. 0 register
  313. 1 --
  314. 2 variable
  315. 3 output parameter
  316. 4 --
  317. 5 inout parameter
  318. 6 input parameter *)
  319. PROCEDURE ConstDeclaration;
  320. VAR obj: LSB.Object;
  321. BEGIN
  322. IF sym = LSS.ident THEN
  323. obj := NewObj(LSB.const); LSS.Get(sym);
  324. IF sym = LSS.eql THEN LSS.Get(sym) ELSE LSS.Mark(":= ?") END ;
  325. expression(obj.b); obj.type := LSB.integer;
  326. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END
  327. ELSE LSS.Mark("ident ?")
  328. END
  329. END ConstDeclaration;
  330. PROCEDURE Type0(VAR type: LSB.Type);
  331. VAR obj: LSB.Object; len, size: LONGINT;
  332. eltyp: LSB.Type; arrtyp: LSB.ArrayType;
  333. BEGIN len := 1;
  334. IF sym = LSS.lbrak THEN (*array*) LSS.Get(sym);
  335. IF sym = LSS.integer THEN len := LSS.val; LSS.Get(sym)
  336. ELSIF sym = LSS.ident THEN obj := ThisObj(LSS.id); len := obj.val
  337. END ;
  338. IF sym = LSS.rbrak THEN LSS.Get(sym) ELSE LSS.Mark("rbrak ?") END ;
  339. Type0(eltyp); NEW(arrtyp); size := eltyp.size * len;
  340. arrtyp.eltyp := eltyp; type := arrtyp; type.len := len; type.size := size
  341. ELSIF sym = LSS.ident THEN
  342. obj := ThisObj(LSS.id); LSS.Get(sym);
  343. IF obj # NIL THEN
  344. IF obj.tag = LSB.typ THEN type := obj.type ELSE LSS.Mark("not a type"); type := LSB.bitType END
  345. ELSE LSS.Mark("type ?")
  346. END
  347. ELSE type := LSB.bitType; LSS.Mark("ident or [")
  348. END
  349. END Type0;
  350. PROCEDURE TypeDeclaration;
  351. VAR obj: LSB.Object; utyp: LSB.UnitType;
  352. BEGIN
  353. IF sym = LSS.ident THEN
  354. obj := NewObj(LSB.typ); LSS.Get(sym);
  355. IF sym = LSS.eql THEN LSS.Get(sym) ELSE LSS.Mark(":= ?") END ;
  356. IF sym = LSS.module THEN
  357. LSS.Get(sym); NEW(utyp); Unit(utyp.firstobj); obj.type := utyp; obj.type.typobj := obj
  358. ELSE Type0(obj.type)
  359. END ;
  360. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END
  361. ELSE LSS.Mark("ident ?")
  362. END
  363. END TypeDeclaration;
  364. PROCEDURE VarList(kind: INTEGER; clk: LSB.Item);
  365. VAR first, new, obj: LSB.Object; type: LSB.Type;
  366. BEGIN obj := NIL;
  367. WHILE sym = LSS.ident DO
  368. new := NewObj(LSB.var); new.name := LSS.id; new.val := kind; first := new; LSS.Get(sym);
  369. IF sym = LSS.comma THEN LSS.Get(sym) ELSIF sym = LSS.ident THEN LSS.Mark("comma missing") END ;
  370. WHILE sym = LSS.ident DO
  371. new := NewObj(LSB.var); new.name := LSS.id; new.val := kind; LSS.Get(sym);
  372. IF sym = LSS.comma THEN LSS.Get(sym) ELSIF sym = LSS.ident THEN LSS.Mark("comma missing") END
  373. END ;
  374. IF sym = LSS.colon THEN
  375. LSS.Get(sym); Type0(type); obj := first;
  376. WHILE obj # bot DO obj.type := type; obj.a := clk; obj := obj.next END
  377. ELSE LSS.Mark("colon ?")
  378. END ;
  379. IF sym = LSS.semicolon THEN LSS.Get(sym)
  380. ELSIF sym # LSS.rparen THEN LSS.Mark("semicolon or rparen missing")
  381. END
  382. END
  383. END VarList;
  384. PROCEDURE ParamList;
  385. VAR kind: INTEGER;
  386. BEGIN
  387. IF sym = LSS.in THEN LSS.Get(sym); kind := 6
  388. ELSIF sym = LSS.out THEN LSS.Get(sym); kind := 3
  389. ELSIF sym = LSS.inout THEN LSS.Get(sym); kind := 5
  390. END ;
  391. VarList(kind, NIL)
  392. END ParamList;
  393. PROCEDURE Traverse(x: LSB.Item);
  394. BEGIN
  395. IF x # NIL THEN
  396. IF x IS LSB.Object THEN
  397. IF (x.tag = LSB.var) & (x.val >= 2) THEN (*not reg*)
  398. IF x(LSB.Object).marked THEN (*loop*)
  399. Texts.WriteString(W, x(LSB.Object).name); Texts.Write(W, " "); err := TRUE
  400. ELSIF x.b # NIL THEN x(LSB.Object).marked := TRUE; Traverse(x.b)
  401. END ;
  402. x(LSB.Object).marked := FALSE
  403. END
  404. ELSE Traverse(x.a); Traverse(x.b)
  405. END
  406. END
  407. END Traverse;
  408. PROCEDURE Unit0(VAR locals: LSB.Object);
  409. VAR obj, oldtop: LSB.Object; kind: INTEGER; clock: LSB.Item;
  410. BEGIN oldtop := top.next; top.next := LSB.root; (*top is dummy*)
  411. IF sym = LSS.lparen THEN LSS.Get(sym) ELSE LSS.Mark("lparen ?") END ;
  412. WHILE (sym = LSS.in) OR (sym = LSS.out) OR (sym = LSS.inout) DO ParamList END ;
  413. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END ;
  414. IF sym = LSS.xor (*arrow*) THEN LSS.Get(sym); locals := top.next
  415. ELSE
  416. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END ;
  417. IF sym = LSS.const THEN LSS.Get(sym);
  418. WHILE sym = LSS.ident DO ConstDeclaration END
  419. END ;
  420. IF sym = LSS.type THEN LSS.Get(sym);
  421. WHILE sym = LSS.ident DO TypeDeclaration END
  422. END ;
  423. WHILE (sym = LSS.var) OR (sym = LSS.reg) DO
  424. IF sym = LSS.var THEN LSS.Get(sym);
  425. WHILE sym = LSS.ident DO VarList(2, NIL) END
  426. ELSE (*reg*) kind := 0; LSS.Get(sym);
  427. IF sym = LSS.lparen THEN (*clock*)
  428. LSS.Get(sym); expression(clock);
  429. IF clock.type # LSB.bitType THEN LSS.Mark("clock must be bitType") END ;
  430. IF (clock IS LSB.Object) & (clock(LSB.Object).name = "clk") THEN kind := 1; clock := NIL END ;
  431. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END
  432. ELSE LSS.Mark("lparen expected"); clock := undef
  433. END ;
  434. WHILE sym = LSS.ident DO VarList(kind, clock) END
  435. END
  436. END ;
  437. locals := top.next;
  438. IF sym = LSS.begin THEN LSS.Get(sym); StatSequence END ;
  439. obj := locals; err := FALSE; (*find unassigned variables*)
  440. WHILE obj # LSB.root DO
  441. IF (obj.tag = LSB.var) & (obj.val < 5) THEN
  442. IF (obj.b = NIL) & (obj.val < 4) THEN Texts.WriteString(W, obj.name); Texts.Write(W, " "); err := TRUE
  443. ELSIF obj.b = undef THEN obj.b := NIL
  444. END
  445. END ;
  446. obj := obj.next
  447. END ;
  448. IF err THEN Texts.WriteString(W, " unassigned"); Texts.WriteLn(W)
  449. ELSE obj := locals; err := FALSE; (*find combinatorial loops*)
  450. WHILE obj # LSB.root DO
  451. IF obj.tag = LSB.var THEN obj.marked := TRUE; Traverse(obj.b); obj.marked := FALSE END ;
  452. obj := obj.next
  453. END ;
  454. IF err THEN Texts.WriteString(W, "in loop"); Texts.WriteLn(W) END
  455. END
  456. END ;
  457. IF err THEN Texts.Append(Oberon.Log, W.buf) END ;
  458. top.next := oldtop
  459. END Unit0;
  460. PROCEDURE Module(T: Texts.Text; pos: LONGINT);
  461. VAR root: LSB.Object; modname: ARRAY 32 OF CHAR;
  462. BEGIN Texts.WriteString(W, "compiling Lola: ");
  463. bot := LSB.root; top.next := bot; LSS.Init(T, pos); LSS.Get(sym);
  464. IF sym = LSS.module THEN
  465. LSS.Get(sym);
  466. IF sym = LSS.ident THEN
  467. modname := LSS.id; Texts.WriteString(W, LSS.id); LSS.Get(sym);
  468. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  469. ELSE LSS.Mark("ident ?")
  470. END ;
  471. Unit(root);
  472. IF sym = LSS.ident THEN LSS.Get(sym);
  473. IF LSS.id # modname THEN LSS.Mark("no match") END
  474. END ;
  475. IF sym # LSS.period THEN LSS.Mark("period ?") END ;
  476. IF ~LSS.error THEN LSB.Register(modname, root)
  477. ELSE Texts.WriteString(W, "compilation failed"); Texts.WriteLn(W); LSB.Register("", LSB.root)
  478. END
  479. ELSE LSS.Mark("module ?")
  480. END ;
  481. Texts.Append(Oberon.Log, W.buf)
  482. END Module;
  483. PROCEDURE Compile*;
  484. VAR beg, end, time: LONGINT;
  485. S: Texts.Scanner; T: Texts.Text;
  486. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  487. IF S.class = Texts.Char THEN
  488. IF S.c = "*" THEN
  489. ELSIF S.c = "@" THEN
  490. Oberon.GetSelection(T, beg, end, time);
  491. IF time >= 0 THEN Module(T, beg) END
  492. END
  493. ELSIF S.class = Texts.Name THEN
  494. NEW(T); Texts.Open(T, S.s); Module(T, 0)
  495. END ;
  496. Texts.Append(Oberon.Log, W.buf)
  497. END Compile;
  498. BEGIN Texts.OpenWriter(W);
  499. Texts.WriteString(W, "Lola compiler; NW 27.8.2018"); Texts.WriteLn(W);
  500. factor := factor0; expression := expression0; Unit := Unit0;
  501. NEW(top); bot := LSB.root;
  502. NEW(undef); undef.tag := LSB.typ; undef.type := LSB.bitType; undef.next := NIL
  503. END LSC.