LSC.Mod.txt 20 KB

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