LSC.Mod.txt 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. MODULE LSC; (*Lola System Compiler, NW 8.1.95 / 26.9.2015 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 z.type := xtyp;
  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. ELSIF ytyp # LSB.bitType THEN 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. x.size := len
  152. ELSE len := 0
  153. END ;
  154. x.size := len
  155. ELSIF sym = LSS.not THEN
  156. LSS.Get(sym); factor(x); y := New(LSB.not, NIL, x); y.type := x.type; y.size := x.size; x := y
  157. ELSIF sym = LSS.lbrace THEN LSS.Get(sym); constructor(x)
  158. ELSE LSS.Mark("bad factor")
  159. END
  160. END factor0;
  161. PROCEDURE term(VAR x: LSB.Item);
  162. VAR y, z: LSB.Item; op: INTEGER;
  163. BEGIN factor(x);
  164. WHILE (sym >= LSS.times) & (sym <= LSS.and) DO
  165. IF sym = LSS.and THEN op := LSB.and
  166. ELSIF sym = LSS.times THEN op := LSB.mul
  167. ELSIF sym = LSS.div THEN op := LSB.div
  168. END ;
  169. LSS.Get(sym); factor(y); z := New(op, x, y); CheckTypes(x, y, z); x := z
  170. END
  171. END term;
  172. PROCEDURE SimpleExpression(VAR x: LSB.Item);
  173. VAR y, z: LSB.Item; op: INTEGER;
  174. BEGIN
  175. IF sym = LSS.minus THEN LSS.Get(sym); term(y);
  176. IF y.tag = LSB.lit THEN x := y; x.val := -y.val
  177. ELSE x := New(LSB.sub, NIL, y); x.type := y.type; x.size := y.siz
  178. END
  179. ELSIF sym = LSS.plus THEN LSS.Get(sym); term(x);
  180. ELSE term(x)
  181. END ;
  182. WHILE (sym >= LSS.plus) & (sym <= LSS.xor) DO
  183. IF sym = LSS.or THEN op := LSB.or
  184. ELSIF sym = LSS.xor THEN op := LSB.xor
  185. ELSIF sym = LSS.plus THEN op := LSB.add
  186. ELSIF sym = LSS.minus THEN op := LSB.sub
  187. END ;
  188. LSS.Get(sym); term(y); z := New(op, x, y); CheckTypes(x, y, z); x := z
  189. END
  190. END SimpleExpression;
  191. PROCEDURE UncondExpression(VAR x: LSB.Item);
  192. VAR y, z: LSB.Item; rel: INTEGER;
  193. BEGIN SimpleExpression(x);
  194. IF (sym >= LSS.eql) & (sym <= LSS.geq) THEN
  195. IF sym = LSS.eql THEN rel := LSB.eql
  196. ELSIF sym = LSS.neq THEN rel := LSB.neq
  197. ELSIF sym = LSS.lss THEN rel := LSB.lss
  198. ELSIF sym = LSS.geq THEN rel := LSB.geq
  199. ELSIF sym = LSS.leq THEN rel := LSB.leq
  200. ELSE rel := LSB.gtr
  201. END ;
  202. LSS.Get(sym); SimpleExpression(y); z := New(rel, x, y); CheckTypes(x, y, z); z.type := LSB.bitType; x := z
  203. END
  204. END UncondExpression;
  205. PROCEDURE expression0(VAR x: LSB.Item);
  206. VAR y, z, w: LSB.Item;
  207. BEGIN UncondExpression(x);
  208. IF sym = LSS.then THEN
  209. IF x.type # LSB.bitType THEN LSS.Mark("Boolean?") END ;
  210. LSS.Get(sym); expression(y);
  211. IF sym = LSS.colon THEN
  212. LSS.Get(sym); expression(z); w := New(LSB.else, y, z); CheckTypes(y, z, w);
  213. x := New(LSB.then, x, w); x.type := w.type; x.size := w.size
  214. ELSE LSS.Mark("colon ?")
  215. END
  216. END
  217. END expression0;
  218. PROCEDURE CheckAssign(x, y: LSB.Item);
  219. VAR xtyp, ytyp: LSB.Type;
  220. BEGIN xtyp := x.type; ytyp := y.type;
  221. IF xtyp # ytyp THEN
  222. IF xtyp = LSB.bitType THEN
  223. IF (ytyp # LSB.integer) OR (y.val >= 2) THEN Err(70); END
  224. ELSIF xtyp IS LSB.ArrayType THEN
  225. IF xtyp(LSB.ArrayType).eltyp = LSB.bitType THEN
  226. IF (ytyp IS LSB.ArrayType) & (xtyp(LSB.ArrayType).eltyp = LSB.bitType) THEN (*w := w*)
  227. IF xtyp.size # ytyp.size THEN Err(71) END (* x + y *)
  228. ELSIF ytyp = LSB.integer THEN (* w := 5 *)
  229. IF xtyp.size < Log(y.val) THEN Err(72) END
  230. ELSIF ytyp = LSB.string THEN (* w := {...} *)
  231. IF xtyp.size # y.size THEN Err(73) END
  232. ELSE Err(74)
  233. END
  234. ELSE Err(74)
  235. END
  236. END
  237. END
  238. END CheckAssign;
  239. PROCEDURE Param(fpar: LSB.Object; VAR apar: LSB.Item);
  240. VAR y, z: LSB.Item;
  241. BEGIN expression(y); apar := New(LSB.next, NIL, y); CheckAssign(fpar, y);
  242. IF fpar.val IN {3, 4} THEN (*OUT or INOUT parameter*)
  243. IF ~(y.tag IN {3, 7}) THEN (*actual param is expression?*) LSS.Mark("bad actual param")
  244. ELSIF y.b = NIL THEN y.b := undef
  245. END
  246. END
  247. END Param;
  248. PROCEDURE Statement;
  249. VAR x, y, z, apar, npar: LSB.Item;
  250. unit: LSB.UnitType; fpar: LSB.Object;
  251. BEGIN
  252. IF sym < LSS.ident THEN LSS.Mark("bad factor");
  253. REPEAT LSS.Get(sym) UNTIL sym >= LSS.ident
  254. END ;
  255. IF sym = LSS.ident THEN
  256. x := ThisObj(LSS.id); z := x; LSS.Get(sym); selector(z);
  257. IF sym = LSS.becomes THEN LSS.Get(sym);
  258. IF x.val >= 5 THEN LSS.Mark("assignment to read-only") END ;
  259. IF (x.b # NIL) & ~(x.type IS LSB.ArrayType) THEN LSS.Mark("mult assign") END ;
  260. expression(y); CheckAssign(z, y); x.b := y; (*tricky*)
  261. IF z # x THEN x.a := z.b; x.val := 1 (*overwriting clk field x.a *) END
  262. ELSIF sym = LSS.lparen THEN LSS.Get(sym); (*unit instantiation*)
  263. IF x.type IS LSB.UnitType THEN
  264. unit := x.type(LSB.UnitType); fpar := unit.firstobj;
  265. IF sym # LSS.rparen THEN
  266. Param(fpar, apar); x.b := apar; fpar := fpar.next;
  267. WHILE sym # LSS.rparen DO
  268. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  269. Param(fpar, npar);
  270. IF fpar.tag >= 3 THEN fpar := fpar.next; apar.a := npar; apar := npar
  271. ELSE LSS.Mark("too many params")
  272. END
  273. END ;
  274. IF fpar.val >= 3 THEN LSS.Mark("too few params") END
  275. END ;
  276. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END
  277. ELSE LSS.Mark("not a module")
  278. END
  279. ELSE LSS.Mark("bad statement")
  280. END
  281. ELSIF sym = LSS.ts THEN (*tri-state*) LSS.Get(sym);
  282. IF sym = LSS.lparen THEN LSS.Get(sym) ELSE LSS.Mark("( missing") END ;
  283. IF sym = LSS.ident THEN
  284. x := ThisObj(LSS.id); x.b := undef; (*INOUT parameter*)
  285. IF x.val # 5 THEN LSS.Mark("not INOUT") END ;
  286. LSS.Get(sym);
  287. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  288. IF sym = LSS.ident THEN y := ThisObj(LSS.id); CheckAssign(x, y); y.b := undef END ; (*output from gate*)
  289. LSS.Get(sym);
  290. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  291. expression(z);
  292. IF (z.tag = LSB.lit) & (z.val <= 1) THEN z.type := LSB.bitType END ;
  293. CheckAssign(x, z); LSS.Get(sym);
  294. IF sym = LSS.comma THEN LSS.Get(sym) END ;
  295. expression(w); (*control*)
  296. IF w.type # LSB.bitType THEN CheckAssign(x, w) END ;
  297. w := New(LSB.next, z, w); x.b := New(LSB.ts, y, w);
  298. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark(") missing") END
  299. END
  300. END
  301. END Statement;
  302. PROCEDURE StatSequence;
  303. BEGIN Statement;
  304. WHILE sym <= LSS.semicolon DO
  305. IF sym < LSS.semicolon THEN LSS.Mark("semicolon missing?") END ;
  306. WHILE sym = LSS.semicolon DO LSS.Get(sym) END ;
  307. Statement
  308. END ;
  309. IF sym = LSS.end THEN LSS.Get(sym) ELSE LSS.Mark("END ?") END
  310. END StatSequence;
  311. (*---------------------------------------------------*)
  312. (* for variables and registers,, obj.val has the meaning
  313. 0 register
  314. 1 register with imlicit clock "clk"
  315. 2 variable
  316. 3 output parameter
  317. 4 output parameter with register
  318. 5 inout parameter
  319. 6 input parameter *)
  320. PROCEDURE ConstDeclaration;
  321. VAR obj: LSB.Object;
  322. BEGIN
  323. IF sym = LSS.ident THEN
  324. obj := NewObj(LSB.const); LSS.Get(sym);
  325. IF (sym = LSS.becomes) OR (sym = LSS.eql) THEN LSS.Get(sym) ELSE LSS.Mark(":= ?") END ;
  326. expression(obj.b); obj.type := LSB.integer;
  327. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END
  328. ELSE LSS.Mark("ident ?")
  329. END
  330. END ConstDeclaration;
  331. PROCEDURE Type0(VAR type: LSB.Type);
  332. VAR obj: LSB.Object; len, size: LONGINT;
  333. eltyp: LSB.Type; arrtyp: LSB.ArrayType;
  334. BEGIN len := 1;
  335. IF sym = LSS.lbrak THEN (*array*) LSS.Get(sym);
  336. IF sym = LSS.integer THEN len := LSS.val; LSS.Get(sym)
  337. ELSIF sym = LSS.ident THEN obj := ThisObj(LSS.id); len := obj.val
  338. END ;
  339. IF sym = LSS.rbrak THEN LSS.Get(sym) ELSE LSS.Mark("rbrak ?") END ;
  340. Type0(eltyp); NEW(arrtyp); size := eltyp.size * len;
  341. arrtyp.eltyp := eltyp; type := arrtyp; type.len := len; type.size := size
  342. ELSIF sym = LSS.ident THEN
  343. obj := ThisObj(LSS.id); LSS.Get(sym);
  344. IF obj # NIL THEN
  345. IF obj.tag = LSB.typ THEN type := obj.type ELSE LSS.Mark("not a type"); type := LSB.bitType END
  346. ELSE LSS.Mark("type ?")
  347. END
  348. ELSE type := LSB.bitType; LSS.Mark("ident or [")
  349. END
  350. END Type0;
  351. PROCEDURE TypeDeclaration;
  352. VAR obj: LSB.Object; utyp: LSB.UnitType;
  353. BEGIN
  354. IF sym = LSS.ident THEN
  355. obj := NewObj(LSB.typ); LSS.Get(sym);
  356. IF (sym = LSS.becomes) OR (sym = LSS.eql) THEN LSS.Get(sym) ELSE LSS.Mark(":= ?") END ;
  357. IF sym = LSS.module THEN
  358. LSS.Get(sym); NEW(utyp); Unit(utyp.firstobj); obj.type := utyp; obj.type.typobj := obj
  359. ELSE Type0(obj.type)
  360. END ;
  361. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END
  362. ELSE LSS.Mark("ident ?")
  363. END
  364. END TypeDeclaration;
  365. PROCEDURE VarList(kind: INTEGER; clk: LSB.Item);
  366. VAR first, new, obj: LSB.Object; type: LSB.Type;
  367. BEGIN obj := NIL;
  368. WHILE sym = LSS.ident DO
  369. new := NewObj(LSB.var); new.name := LSS.id; new.val := kind; first := new; LSS.Get(sym);
  370. IF sym = LSS.comma THEN LSS.Get(sym) ELSIF sym = LSS.ident THEN LSS.Mark("comma missing") END ;
  371. WHILE sym = LSS.ident DO
  372. new := NewObj(LSB.var); new.name := LSS.id; new.val := kind; LSS.Get(sym);
  373. IF sym = LSS.comma THEN LSS.Get(sym) ELSIF sym = LSS.ident THEN LSS.Mark("comma missing") END
  374. END ;
  375. IF sym = LSS.colon THEN
  376. LSS.Get(sym); Type0(type); obj := first;
  377. WHILE obj # bot DO obj.type := type; obj.a := clk; obj := obj.next END
  378. ELSE LSS.Mark("colon ?")
  379. END ;
  380. IF sym = LSS.semicolon THEN LSS.Get(sym)
  381. ELSIF sym # LSS.rparen THEN LSS.Mark("semicolon or rparen missing")
  382. END
  383. END
  384. END VarList;
  385. PROCEDURE ParamList;
  386. VAR kind: INTEGER;
  387. BEGIN
  388. IF sym = LSS.in THEN LSS.Get(sym); kind := 6
  389. ELSIF sym = LSS.out THEN LSS.Get(sym);
  390. IF sym = LSS.reg THEN LSS.Get(sym); kind := 4 ELSE kind := 3 END
  391. ELSIF sym = LSS.inout THEN LSS.Get(sym); kind := 5
  392. END ;
  393. VarList(kind, NIL)
  394. END ParamList;
  395. PROCEDURE Traverse(x: LSB.Item);
  396. BEGIN
  397. IF x # NIL THEN
  398. IF x IS LSB.Object THEN
  399. IF (x.tag = LSB.var) & (x.val >= 2) THEN (*not reg*)
  400. IF x(LSB.Object).marked THEN (*loop*)
  401. Texts.WriteString(W, x(LSB.Object).name); Texts.Write(W, " "); err := TRUE
  402. ELSIF x.b # NIL THEN x(LSB.Object).marked := TRUE; Traverse(x.b)
  403. END ;
  404. x(LSB.Object).marked := FALSE
  405. END
  406. ELSE Traverse(x.a); Traverse(x.b)
  407. END
  408. END
  409. END Traverse;
  410. PROCEDURE Unit0(VAR locals: LSB.Object);
  411. VAR obj, oldtop: LSB.Object; kind: INTEGER; clock: LSB.Item;
  412. BEGIN oldtop := top.next; top.next := LSB.root; (*top is dummy*)
  413. IF sym = LSS.lparen THEN LSS.Get(sym) ELSE LSS.Mark("lparen ?") END ;
  414. WHILE (sym = LSS.in) OR (sym = LSS.out) OR (sym = LSS.inout) DO ParamList END ;
  415. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END ;
  416. IF sym = LSS.xor (*arrow*) THEN LSS.Get(sym); locals := top.next
  417. ELSE
  418. IF sym = LSS.semicolon THEN LSS.Get(sym) ELSE LSS.Mark("semicolon ?") END ;
  419. IF sym = LSS.const THEN LSS.Get(sym);
  420. WHILE sym = LSS.ident DO ConstDeclaration END
  421. END ;
  422. IF sym = LSS.type THEN LSS.Get(sym);
  423. WHILE sym = LSS.ident DO TypeDeclaration END
  424. END ;
  425. WHILE (sym = LSS.var) OR (sym = LSS.reg) DO
  426. IF sym = LSS.var THEN LSS.Get(sym);
  427. WHILE sym = LSS.ident DO VarList(2, NIL) END
  428. ELSE (*reg*) kind := 0; LSS.Get(sym);
  429. IF sym = LSS.lparen THEN (*clock*)
  430. LSS.Get(sym); expression(clock);
  431. IF clock.type # LSB.bitType THEN LSS.Mark("clock must be bitType") END ;
  432. IF (clock IS LSB.Object) & (clock(LSB.Object).name = "clk") THEN kind := 1; clock := NIL END ;
  433. IF sym = LSS.rparen THEN LSS.Get(sym) ELSE LSS.Mark("rparen ?") END
  434. ELSE LSS.Mark("lparen expected"); clock := undef
  435. END ;
  436. WHILE sym = LSS.ident DO VarList(kind, clock) END
  437. END
  438. END ;
  439. locals := top.next;
  440. IF sym = LSS.begin THEN LSS.Get(sym); StatSequence END ;
  441. obj := locals; err := FALSE; (*find unassigned variables*)
  442. WHILE obj # LSB.root DO
  443. IF (obj.tag = LSB.var) & (obj.val < 5) THEN
  444. IF (obj.b = NIL) & (obj.val < 4) THEN Texts.WriteString(W, obj.name); Texts.Write(W, " "); err := TRUE
  445. ELSIF obj.b = undef THEN obj.b := NIL
  446. END
  447. END ;
  448. obj := obj.next
  449. END ;
  450. IF err THEN Texts.WriteString(W, " unassigned"); Texts.WriteLn(W)
  451. ELSE obj := locals; err := FALSE; (*find combinatorial loops*)
  452. WHILE obj # LSB.root DO
  453. IF obj.tag = LSB.var THEN obj.marked := TRUE; Traverse(obj.b); obj.marked := FALSE END ;
  454. obj := obj.next
  455. END ;
  456. IF err THEN Texts.WriteString(W, "in loop"); Texts.WriteLn(W) END
  457. END
  458. END ;
  459. IF err THEN Texts.Append(Oberon.Log, W.buf) END ;
  460. top.next := oldtop
  461. END Unit0;
  462. PROCEDURE Module(T: Texts.Text; pos: LONGINT);
  463. VAR root: LSB.Object; modname: ARRAY 32 OF CHAR;
  464. BEGIN Texts.WriteString(W, "compiling Lola: ");
  465. bot := LSB.root; top.next := bot; LSS.Init(T, pos); LSS.Get(sym);
  466. IF sym = LSS.module THEN
  467. LSS.Get(sym);
  468. IF sym = LSS.ident THEN
  469. modname := LSS.id; Texts.WriteString(W, LSS.id); LSS.Get(sym);
  470. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  471. ELSE LSS.Mark("ident ?")
  472. END ;
  473. Unit(root);
  474. IF sym = LSS.ident THEN LSS.Get(sym);
  475. IF LSS.id # modname THEN LSS.Mark("no match") END
  476. END ;
  477. IF sym # LSS.period THEN LSS.Mark("period ?") END ;
  478. IF ~LSS.error THEN LSB.Register(modname, root)
  479. ELSE Texts.WriteString(W, "compilation failed"); Texts.WriteLn(W); LSB.Register("", LSB.root)
  480. END
  481. ELSE LSS.Mark("module ?")
  482. END ;
  483. Texts.Append(Oberon.Log, W.buf)
  484. END Module;
  485. PROCEDURE Compile*;
  486. VAR beg, end, time: LONGINT;
  487. S: Texts.Scanner; T: Texts.Text;
  488. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  489. IF S.class = Texts.Char THEN
  490. IF S.c = "*" THEN
  491. ELSIF S.c = "@" THEN
  492. Oberon.GetSelection(T, beg, end, time);
  493. IF time >= 0 THEN Module(T, beg) END
  494. END
  495. ELSIF S.class = Texts.Name THEN
  496. NEW(T); Texts.Open(T, S.s); Module(T, 0)
  497. END ;
  498. Texts.Append(Oberon.Log, W.buf)
  499. END Compile;
  500. BEGIN Texts.OpenWriter(W);
  501. Texts.WriteString(W, "Lola compiler; NW 6.7.2015"); Texts.WriteLn(W);
  502. NEW(top); bot := LSB.root; NEW(undef); undef.tag := 2; undef.type := LSB.bitType
  503. END LSC.