ORP.Mod.txt 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. MODULE ORP; (*N. Wirth 1.7.97 / 8.2.2020 Oberon compiler for RISC in Oberon-07*)
  2. IMPORT Texts, Oberon, ORS, ORB, ORG;
  3. (*Author: Niklaus Wirth, 2014.
  4. Parser of Oberon-RISC compiler. Uses Scanner ORS to obtain symbols (tokens),
  5. ORB for definition of data structures and for handling import and export, and
  6. ORG to produce binary code. ORP performs type checking and data allocation.
  7. Parser is target-independent, except for part of the handling of allocations.*)
  8. TYPE PtrBase = POINTER TO PtrBaseDesc;
  9. PtrBaseDesc = RECORD (*list of names of pointer base types*)
  10. name: ORS.Ident; type: ORB.Type; next: PtrBase
  11. END ;
  12. VAR sym: INTEGER; (*last symbol read*)
  13. dc: LONGINT; (*data counter*)
  14. level, exno, version: INTEGER;
  15. newSF: BOOLEAN; (*option flag*)
  16. expression: PROCEDURE (VAR x: ORG.Item); (*to avoid forward reference*)
  17. Type: PROCEDURE (VAR type: ORB.Type);
  18. FormalType: PROCEDURE (VAR typ: ORB.Type; dim: INTEGER);
  19. modid: ORS.Ident;
  20. pbsList: PtrBase; (*list of names of pointer base types*)
  21. dummy: ORB.Object;
  22. W: Texts.Writer;
  23. PROCEDURE Check(s: INTEGER; msg: ARRAY OF CHAR);
  24. BEGIN
  25. IF sym = s THEN ORS.Get(sym) ELSE ORS.Mark(msg) END
  26. END Check;
  27. PROCEDURE qualident(VAR obj: ORB.Object);
  28. BEGIN obj := ORB.thisObj(); ORS.Get(sym);
  29. IF obj = NIL THEN ORS.Mark("undef"); obj := dummy END ;
  30. IF (sym = ORS.period) & (obj.class = ORB.Mod) THEN
  31. ORS.Get(sym);
  32. IF sym = ORS.ident THEN obj := ORB.thisimport(obj); ORS.Get(sym);
  33. IF obj = NIL THEN ORS.Mark("undef"); obj := dummy END
  34. ELSE ORS.Mark("identifier expected"); obj := dummy
  35. END
  36. END
  37. END qualident;
  38. PROCEDURE CheckBool(VAR x: ORG.Item);
  39. BEGIN
  40. IF x.type.form # ORB.Bool THEN ORS.Mark("not Boolean"); x.type := ORB.boolType END
  41. END CheckBool;
  42. PROCEDURE CheckInt(VAR x: ORG.Item);
  43. BEGIN
  44. IF x.type.form # ORB.Int THEN ORS.Mark("not Integer"); x.type := ORB.intType END
  45. END CheckInt;
  46. PROCEDURE CheckReal(VAR x: ORG.Item);
  47. BEGIN
  48. IF x.type.form # ORB.Real THEN ORS.Mark("not Real"); x.type := ORB.realType END
  49. END CheckReal;
  50. PROCEDURE CheckSet(VAR x: ORG.Item);
  51. BEGIN
  52. IF x.type.form # ORB.Set THEN ORS.Mark("not Set"); x.type := ORB.setType END
  53. END CheckSet;
  54. PROCEDURE CheckSetVal(VAR x: ORG.Item);
  55. BEGIN
  56. IF x.type.form # ORB.Int THEN ORS.Mark("not Int"); x.type := ORB.setType
  57. ELSIF x.mode = ORB.Const THEN
  58. IF (x.a < 0) OR (x.a >= 32) THEN ORS.Mark("invalid set") END
  59. END
  60. END CheckSetVal;
  61. PROCEDURE CheckConst(VAR x: ORG.Item);
  62. BEGIN
  63. IF x.mode # ORB.Const THEN ORS.Mark("not a constant"); x.mode := ORB.Const END
  64. END CheckConst;
  65. PROCEDURE CheckReadOnly(VAR x: ORG.Item);
  66. BEGIN
  67. IF x.rdo THEN ORS.Mark("read-only") END
  68. END CheckReadOnly;
  69. PROCEDURE CheckExport(VAR expo: BOOLEAN);
  70. BEGIN
  71. IF sym = ORS.times THEN
  72. expo := TRUE; ORS.Get(sym);
  73. IF level # 0 THEN ORS.Mark("remove asterisk") END
  74. ELSE expo := FALSE
  75. END
  76. END CheckExport;
  77. PROCEDURE IsExtension(t0, t1: ORB.Type): BOOLEAN;
  78. BEGIN (*t1 is an extension of t0*)
  79. RETURN (t0 = t1) OR (t1 # NIL) & IsExtension(t0, t1.base)
  80. END IsExtension;
  81. (* expressions *)
  82. PROCEDURE TypeTest(VAR x: ORG.Item; T: ORB.Type; guard: BOOLEAN);
  83. VAR xt: ORB.Type;
  84. BEGIN xt := x.type;
  85. IF (T.form = xt.form ) & ((T.form = ORB.Pointer) OR (T.form = ORB.Record) & (x.mode = ORB.Par)) THEN
  86. WHILE (xt # T) & (xt # NIL) DO xt := xt.base END ;
  87. IF xt # T THEN xt := x.type;
  88. IF xt.form = ORB.Pointer THEN
  89. IF IsExtension(xt.base, T.base) THEN ORG.TypeTest(x, T.base, FALSE, guard); x.type := T
  90. ELSE ORS.Mark("not an extension")
  91. END
  92. ELSIF (xt.form = ORB.Record) & (x.mode = ORB.Par) THEN
  93. IF IsExtension(xt, T) THEN ORG.TypeTest(x, T, TRUE, guard); x.type := T
  94. ELSE ORS.Mark("not an extension")
  95. END
  96. ELSE ORS.Mark("incompatible types")
  97. END
  98. ELSIF ~guard THEN ORG.TypeTest(x, NIL, FALSE, FALSE)
  99. END
  100. ELSE ORS.Mark("type mismatch")
  101. END ;
  102. IF ~guard THEN x.type := ORB.boolType END
  103. END TypeTest;
  104. PROCEDURE selector(VAR x: ORG.Item);
  105. VAR y: ORG.Item; obj: ORB.Object;
  106. BEGIN
  107. WHILE (sym = ORS.lbrak) OR (sym = ORS.period) OR (sym = ORS.arrow)
  108. OR (sym = ORS.lparen) & (x.type.form IN {ORB.Record, ORB.Pointer}) DO
  109. IF sym = ORS.lbrak THEN
  110. REPEAT ORS.Get(sym); expression(y);
  111. IF x.type.form = ORB.Array THEN
  112. CheckInt(y); ORG.Index(x, y); x.type := x.type.base
  113. ELSE ORS.Mark("not an array")
  114. END
  115. UNTIL sym # ORS.comma;
  116. Check(ORS.rbrak, "no ]")
  117. ELSIF sym = ORS.period THEN ORS.Get(sym);
  118. IF sym = ORS.ident THEN
  119. IF x.type.form = ORB.Pointer THEN ORG.DeRef(x); x.type := x.type.base END ;
  120. IF x.type.form = ORB.Record THEN
  121. obj := ORB.thisfield(x.type); ORS.Get(sym);
  122. IF obj # NIL THEN ORG.Field(x, obj); x.type := obj.type
  123. ELSE ORS.Mark("undef")
  124. END
  125. ELSE ORS.Mark("not a record")
  126. END
  127. ELSE ORS.Mark("ident?")
  128. END
  129. ELSIF sym = ORS.arrow THEN
  130. ORS.Get(sym);
  131. IF x.type.form = ORB.Pointer THEN ORG.DeRef(x); x.type := x.type.base
  132. ELSE ORS.Mark("not a pointer")
  133. END
  134. ELSIF (sym = ORS.lparen) & (x.type.form IN {ORB.Record, ORB.Pointer}) THEN (*type guard*)
  135. ORS.Get(sym);
  136. IF sym = ORS.ident THEN
  137. qualident(obj);
  138. IF obj.class = ORB.Typ THEN TypeTest(x, obj.type, TRUE)
  139. ELSE ORS.Mark("guard type expected")
  140. END
  141. ELSE ORS.Mark("not an identifier")
  142. END ;
  143. Check(ORS.rparen, " ) missing")
  144. END
  145. END
  146. END selector;
  147. PROCEDURE EqualSignatures(t0, t1: ORB.Type): BOOLEAN;
  148. VAR p0, p1: ORB.Object; com: BOOLEAN;
  149. BEGIN com := TRUE;
  150. IF (t0.base = t1.base) & (t0.nofpar = t1.nofpar) THEN
  151. p0 := t0.dsc; p1 := t1.dsc;
  152. WHILE p0 # NIL DO
  153. IF (p0.class = p1.class) & (p0.rdo = p1.rdo) &
  154. ((p0.type = p1.type) OR
  155. (p0.type.form = ORB.Array) & (p1.type.form = ORB.Array) & (p0.type.len = p1.type.len) & (p0.type.base = p1.type.base) OR
  156. (p0.type.form = ORB.Proc) & (p1.type.form = ORB.Proc) & EqualSignatures(p0.type, p1.type))
  157. THEN p0 := p0.next; p1 := p1.next
  158. ELSE p0 := NIL; com := FALSE
  159. END
  160. END
  161. ELSE com := FALSE
  162. END ;
  163. RETURN com
  164. END EqualSignatures;
  165. PROCEDURE CompTypes(t0, t1: ORB.Type; varpar: BOOLEAN): BOOLEAN;
  166. BEGIN (*check for assignment compatibility*)
  167. RETURN (t0 = t1) (*openarray assignment disallowed in ORG*)
  168. OR (t0.form = ORB.Array) & (t1.form = ORB.Array) & (t0.base = t1.base) & (t0.len = t1.len)
  169. OR (t0.form = ORB.Record) & (t1.form = ORB.Record) & IsExtension(t0, t1)
  170. OR ~varpar &
  171. ((t0.form = ORB.Pointer) & (t1.form = ORB.Pointer) & IsExtension(t0.base, t1.base)
  172. OR (t0.form = ORB.Proc) & (t1.form = ORB.Proc) & EqualSignatures(t0, t1)
  173. OR (t0.form IN {ORB.Pointer, ORB.Proc}) & (t1.form = ORB.NilTyp))
  174. END CompTypes;
  175. PROCEDURE Parameter(par: ORB.Object);
  176. VAR x: ORG.Item; varpar: BOOLEAN;
  177. BEGIN expression(x);
  178. IF par # NIL THEN
  179. varpar := par.class = ORB.Par;
  180. IF CompTypes(par.type, x.type, varpar) THEN
  181. IF ~varpar THEN ORG.ValueParam(x)
  182. ELSE (*par.class = Par*)
  183. IF ~par.rdo THEN CheckReadOnly(x) END ;
  184. ORG.VarParam(x, par.type)
  185. END
  186. ELSIF (x.type.form = ORB.Array) & (par.type.form = ORB.Array) &
  187. (x.type.base = par.type.base) & (par.type.len < 0) THEN
  188. IF ~par.rdo THEN CheckReadOnly(x) END ;
  189. ORG.OpenArrayParam(x)
  190. ELSIF (x.type.form = ORB.String) & varpar & par.rdo & (par.type.form = ORB.Array) &
  191. (par.type.base.form = ORB.Char) & (par.type.len < 0) THEN ORG.StringParam(x)
  192. ELSIF ~varpar & (par.type.form = ORB.Int) & (x.type.form = ORB.Int) THEN ORG.ValueParam(x) (*BYTE*)
  193. ELSIF (x.type.form = ORB.String) & (x.b = 2) & (par.class = ORB.Var) & (par.type.form = ORB.Char) THEN
  194. ORG.StrToChar(x); ORG.ValueParam(x)
  195. ELSIF (par.type.form = ORB.Array) & (par.type.base = ORB.byteType) &
  196. (par.type.len >= 0) & (par.type.size = x.type.size) THEN
  197. ORG.VarParam(x, par.type)
  198. ELSE ORS.Mark("incompatible parameters")
  199. END
  200. END
  201. END Parameter;
  202. PROCEDURE ParamList(VAR x: ORG.Item);
  203. VAR n: INTEGER; par: ORB.Object;
  204. BEGIN par := x.type.dsc; n := 0;
  205. IF sym # ORS.rparen THEN
  206. Parameter(par); n := 1;
  207. WHILE sym <= ORS.comma DO
  208. Check(sym, "comma?");
  209. IF par # NIL THEN par := par.next END ;
  210. INC(n); Parameter(par)
  211. END ;
  212. Check(ORS.rparen, ") missing")
  213. ELSE ORS.Get(sym);
  214. END ;
  215. IF n < x.type.nofpar THEN ORS.Mark("too few params")
  216. ELSIF n > x.type.nofpar THEN ORS.Mark("too many params")
  217. END
  218. END ParamList;
  219. PROCEDURE StandFunc(VAR x: ORG.Item; fct: LONGINT; restyp: ORB.Type);
  220. VAR y: ORG.Item; n, npar: LONGINT;
  221. BEGIN Check(ORS.lparen, "no (");
  222. npar := fct MOD 10; fct := fct DIV 10; expression(x); n := 1;
  223. WHILE sym = ORS.comma DO ORS.Get(sym); expression(y); INC(n) END ;
  224. Check(ORS.rparen, "no )");
  225. IF n = npar THEN
  226. IF fct = 0 THEN (*ABS*)
  227. IF x.type.form IN {ORB.Int, ORB.Real} THEN ORG.Abs(x); restyp := x.type ELSE ORS.Mark("bad type") END
  228. ELSIF fct = 1 THEN (*ODD*) CheckInt(x); ORG.Odd(x)
  229. ELSIF fct = 2 THEN (*FLOOR*) CheckReal(x); ORG.Floor(x)
  230. ELSIF fct = 3 THEN (*FLT*) CheckInt(x); ORG.Float(x)
  231. ELSIF fct = 4 THEN (*ORD*)
  232. IF x.type.form <= ORB.Proc THEN ORG.Ord(x)
  233. ELSIF (x.type.form = ORB.String) & (x.b = 2) THEN ORG.StrToChar(x)
  234. ELSE ORS.Mark("bad type")
  235. END
  236. ELSIF fct = 5 THEN (*CHR*) CheckInt(x); ORG.Ord(x)
  237. ELSIF fct = 6 THEN (*LEN*)
  238. IF x.type.form = ORB.Array THEN ORG.Len(x) ELSE ORS.Mark("not an array") END
  239. ELSIF fct IN {7, 8, 9} THEN (*LSL, ASR, ROR*) CheckInt(y);
  240. IF x.type.form IN {ORB.Int, ORB.Set} THEN ORG.Shift(fct-7, x, y); restyp := x.type ELSE ORS.Mark("bad type") END
  241. ELSIF fct = 11 THEN (*ADC*) ORG.ADC(x, y)
  242. ELSIF fct = 12 THEN (*SBC*) ORG.SBC(x, y)
  243. ELSIF fct = 13 THEN (*UML*) ORG.UML(x, y)
  244. ELSIF fct = 14 THEN (*BIT*) CheckInt(x); CheckInt(y); ORG.Bit(x, y)
  245. ELSIF fct = 15 THEN (*REG*) CheckConst(x); CheckInt(x); ORG.Register(x)
  246. ELSIF fct = 16 THEN (*VAL*)
  247. IF (x.mode= ORB.Typ) & (x.type.size <= y.type.size) THEN restyp := x.type; x := y
  248. ELSE ORS.Mark("casting not allowed")
  249. END
  250. ELSIF fct = 17 THEN (*ADR*) ORG.Adr(x)
  251. ELSIF fct = 18 THEN (*SIZE*)
  252. IF x.mode = ORB.Typ THEN ORG.MakeConstItem(x, ORB.intType, x.type.size)
  253. ELSE ORS.Mark("must be a type")
  254. END
  255. ELSIF fct = 19 THEN (*COND*) CheckConst(x); CheckInt(x); ORG.Condition(x)
  256. ELSIF fct = 20 THEN (*H*) CheckConst(x); CheckInt(x); ORG.H(x)
  257. END ;
  258. x.type := restyp
  259. ELSE ORS.Mark("wrong nof params")
  260. END
  261. END StandFunc;
  262. PROCEDURE element(VAR x: ORG.Item);
  263. VAR y: ORG.Item;
  264. BEGIN expression(x); CheckSetVal(x);
  265. IF sym = ORS.upto THEN ORS.Get(sym); expression(y); CheckSetVal(y); ORG.Set(x, y)
  266. ELSE ORG.Singleton(x)
  267. END ;
  268. x.type := ORB.setType
  269. END element;
  270. PROCEDURE set(VAR x: ORG.Item);
  271. VAR y: ORG.Item;
  272. BEGIN
  273. IF sym >= ORS.if THEN
  274. IF sym # ORS.rbrace THEN ORS.Mark(" } missing") END ;
  275. ORG.MakeConstItem(x, ORB.setType, 0) (*empty set*)
  276. ELSE element(x);
  277. WHILE (sym < ORS.rparen) OR (sym > ORS.rbrace) DO
  278. IF sym = ORS.comma THEN ORS.Get(sym)
  279. ELSIF sym # ORS.rbrace THEN ORS.Mark("missing comma")
  280. END ;
  281. element(y); ORG.SetOp(ORS.plus, x, y)
  282. END
  283. END
  284. END set;
  285. PROCEDURE factor(VAR x: ORG.Item);
  286. VAR obj: ORB.Object; rx: LONGINT;
  287. BEGIN (*sync*)
  288. IF (sym < ORS.char) OR (sym > ORS.ident) THEN ORS.Mark("expression expected");
  289. REPEAT ORS.Get(sym) UNTIL (sym >= ORS.char) & (sym <= ORS.for) OR (sym >= ORS.then)
  290. END ;
  291. IF sym = ORS.ident THEN
  292. qualident(obj);
  293. IF obj.class = ORB.SFunc THEN StandFunc(x, obj.val, obj.type)
  294. ELSE ORG.MakeItem(x, obj, level); selector(x);
  295. IF sym = ORS.lparen THEN
  296. ORS.Get(sym);
  297. IF (x.type.form = ORB.Proc) & (x.type.base.form # ORB.NoTyp) THEN
  298. ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx); x.type := x.type.base
  299. ELSE ORS.Mark("not a function"); ParamList(x)
  300. END
  301. END
  302. END
  303. ELSIF sym = ORS.int THEN ORG.MakeConstItem(x, ORB.intType, ORS.ival); ORS.Get(sym)
  304. ELSIF sym = ORS.real THEN ORG.MakeRealItem(x, ORS.rval); ORS.Get(sym)
  305. ELSIF sym = ORS.char THEN ORG.MakeConstItem(x, ORB.charType, ORS.ival); ORS.Get(sym)
  306. ELSIF sym = ORS.nil THEN ORS.Get(sym); ORG.MakeConstItem(x, ORB.nilType, 0)
  307. ELSIF sym = ORS.string THEN ORG.MakeStringItem(x, ORS.slen); ORS.Get(sym)
  308. ELSIF sym = ORS.lparen THEN ORS.Get(sym); expression(x); Check(ORS.rparen, "no )")
  309. ELSIF sym = ORS.lbrace THEN ORS.Get(sym); set(x); Check(ORS.rbrace, "no }")
  310. ELSIF sym = ORS.not THEN ORS.Get(sym); factor(x); CheckBool(x); ORG.Not(x)
  311. ELSIF sym = ORS.false THEN ORS.Get(sym); ORG.MakeConstItem(x, ORB.boolType, 0)
  312. ELSIF sym = ORS.true THEN ORS.Get(sym); ORG.MakeConstItem(x, ORB.boolType, 1)
  313. ELSE ORS.Mark("not a factor"); ORG.MakeConstItem(x, ORB.intType, 0)
  314. END
  315. END factor;
  316. PROCEDURE term(VAR x: ORG.Item);
  317. VAR y: ORG.Item; op, f: INTEGER;
  318. BEGIN factor(x); f := x.type.form;
  319. WHILE (sym >= ORS.times) & (sym <= ORS.and) DO
  320. op := sym; ORS.Get(sym);
  321. IF op = ORS.times THEN
  322. IF f = ORB.Int THEN factor(y); CheckInt(y); ORG.MulOp(x, y)
  323. ELSIF f = ORB.Real THEN factor(y); CheckReal(y); ORG.RealOp(op, x, y)
  324. ELSIF f = ORB.Set THEN factor(y); CheckSet(y); ORG.SetOp(op, x, y)
  325. ELSE ORS.Mark("bad type")
  326. END
  327. ELSIF (op = ORS.div) OR (op = ORS.mod) THEN
  328. CheckInt(x); factor(y); CheckInt(y); ORG.DivOp(op, x, y)
  329. ELSIF op = ORS.rdiv THEN
  330. IF f = ORB.Real THEN factor(y); CheckReal(y); ORG.RealOp(op, x, y)
  331. ELSIF f = ORB.Set THEN factor(y); CheckSet(y); ORG.SetOp(op, x, y)
  332. ELSE ORS.Mark("bad type")
  333. END
  334. ELSE (*op = and*) CheckBool(x); ORG.And1(x); factor(y); CheckBool(y); ORG.And2(x, y)
  335. END
  336. END
  337. END term;
  338. PROCEDURE SimpleExpression(VAR x: ORG.Item);
  339. VAR y: ORG.Item; op: INTEGER;
  340. BEGIN
  341. IF sym = ORS.minus THEN ORS.Get(sym); term(x);
  342. IF x.type.form IN {ORB.Int, ORB.Real, ORB.Set} THEN ORG.Neg(x) ELSE CheckInt(x) END
  343. ELSIF sym = ORS.plus THEN ORS.Get(sym); term(x);
  344. ELSE term(x)
  345. END ;
  346. WHILE (sym >= ORS.plus) & (sym <= ORS.or) DO
  347. op := sym; ORS.Get(sym);
  348. IF op = ORS.or THEN ORG.Or1(x); CheckBool(x); term(y); CheckBool(y); ORG.Or2(x, y)
  349. ELSIF x.type.form = ORB.Int THEN term(y); CheckInt(y); ORG.AddOp(op, x, y)
  350. ELSIF x.type.form = ORB.Real THEN term(y); CheckReal(y); ORG.RealOp(op, x, y)
  351. ELSE CheckSet(x); term(y); CheckSet(y); ORG.SetOp(op, x, y)
  352. END
  353. END
  354. END SimpleExpression;
  355. PROCEDURE expression0(VAR x: ORG.Item);
  356. VAR y: ORG.Item; obj: ORB.Object; rel, xf, yf: INTEGER;
  357. BEGIN SimpleExpression(x);
  358. IF (sym >= ORS.eql) & (sym <= ORS.geq) THEN
  359. rel := sym; ORS.Get(sym); SimpleExpression(y); xf := x.type.form; yf := y.type.form;
  360. IF x.type = y.type THEN
  361. IF (xf IN {ORB.Char, ORB.Int}) THEN ORG.IntRelation(rel, x, y)
  362. ELSIF xf = ORB.Real THEN ORG.RealRelation(rel, x, y)
  363. ELSIF (xf IN {ORB.Set, ORB.Pointer, ORB.Proc, ORB.NilTyp, ORB.Bool}) THEN
  364. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  365. ELSIF (xf = ORB.Array) & (x.type.base.form = ORB.Char) OR (xf = ORB.String) THEN
  366. ORG.StringRelation(rel, x, y)
  367. ELSE ORS.Mark("illegal comparison")
  368. END
  369. ELSIF (xf IN {ORB.Pointer, ORB.Proc}) & (yf = ORB.NilTyp)
  370. OR (yf IN {ORB.Pointer, ORB.Proc}) & (xf = ORB.NilTyp) THEN
  371. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  372. ELSIF (xf = ORB.Pointer) & (yf = ORB.Pointer) &
  373. (IsExtension(x.type.base, y.type.base) OR IsExtension(y.type.base, x.type.base))
  374. OR (xf = ORB.Proc) & (yf = ORB.Proc) & EqualSignatures(x.type, y.type) THEN
  375. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  376. ELSIF (xf = ORB.Array) & (x.type.base.form = ORB.Char) &
  377. ((yf = ORB.String) OR (yf = ORB.Array) & (y.type.base.form = ORB.Char))
  378. OR (yf = ORB.Array) & (y.type.base.form = ORB.Char) & (xf = ORB.String) THEN
  379. ORG.StringRelation(rel, x, y)
  380. ELSIF (xf = ORB.Char) & (yf = ORB.String) & (y.b = 2) THEN
  381. ORG.StrToChar(y); ORG.IntRelation(rel, x, y)
  382. ELSIF (yf = ORB.Char) & (xf = ORB.String) & (x.b = 2) THEN
  383. ORG.StrToChar(x); ORG.IntRelation(rel, x, y)
  384. ELSIF (xf = ORB.Int) & (yf = ORB.Int) THEN ORG.IntRelation(rel, x, y) (*BYTE*)
  385. ELSE ORS.Mark("illegal comparison")
  386. END ;
  387. x.type := ORB.boolType
  388. ELSIF sym = ORS.in THEN
  389. ORS.Get(sym); CheckInt(x); SimpleExpression(y); CheckSet(y); ORG.In(x, y) ;
  390. x.type := ORB.boolType
  391. ELSIF sym = ORS.is THEN
  392. ORS.Get(sym); qualident(obj); TypeTest(x, obj.type, FALSE) ;
  393. x.type := ORB.boolType
  394. END
  395. END expression0;
  396. (* statements *)
  397. PROCEDURE StandProc(pno: LONGINT);
  398. VAR nap, npar: LONGINT; (*nof actual/formal parameters*)
  399. x, y, z: ORG.Item;
  400. BEGIN Check(ORS.lparen, "no (");
  401. npar := pno MOD 10; pno := pno DIV 10; expression(x); nap := 1;
  402. IF sym = ORS.comma THEN
  403. ORS.Get(sym); expression(y); nap := 2; z.type := ORB.noType;
  404. WHILE sym = ORS.comma DO ORS.Get(sym); expression(z); INC(nap) END
  405. ELSE y.type := ORB.noType
  406. END ;
  407. Check(ORS.rparen, "no )");
  408. IF (npar = nap) OR (pno IN {0, 1}) THEN
  409. IF pno IN {0, 1} THEN (*INC, DEC*)
  410. CheckInt(x); CheckReadOnly(x);
  411. IF y.type # ORB.noType THEN CheckInt(y) END ;
  412. ORG.Increment(pno, x, y)
  413. ELSIF pno IN {2, 3} THEN (*INCL, EXCL*)
  414. CheckSet(x); CheckReadOnly(x); CheckInt(y); ORG.Include(pno-2, x, y)
  415. ELSIF pno = 4 THEN CheckBool(x); ORG.Assert(x)
  416. ELSIF pno = 5 THEN(*NEW*) CheckReadOnly(x);
  417. IF (x.type.form = ORB.Pointer) & (x.type.base.form = ORB.Record) THEN ORG.New(x)
  418. ELSE ORS.Mark("not a pointer to record")
  419. END
  420. ELSIF pno = 6 THEN CheckReal(x); CheckInt(y); CheckReadOnly(x); ORG.Pack(x, y)
  421. ELSIF pno = 7 THEN CheckReal(x); CheckInt(y); CheckReadOnly(x); ORG.Unpk(x, y)
  422. ELSIF pno = 8 THEN
  423. IF x.type.form <= ORB.Set THEN ORG.Led(x) ELSE ORS.Mark("bad type") END
  424. ELSIF pno = 10 THEN CheckInt(x); ORG.Get(x, y)
  425. ELSIF pno = 11 THEN CheckInt(x); ORG.Put(x, y)
  426. ELSIF pno = 12 THEN CheckInt(x); CheckInt(y); CheckInt(z); ORG.Copy(x, y, z)
  427. ELSIF pno = 13 THEN CheckConst(x); CheckInt(x); ORG.LDPSR(x)
  428. ELSIF pno = 14 THEN CheckInt(x); ORG.LDREG(x, y)
  429. END
  430. ELSE ORS.Mark("wrong nof parameters")
  431. END
  432. END StandProc;
  433. PROCEDURE StatSequence;
  434. VAR obj: ORB.Object;
  435. orgtype: ORB.Type; (*original type of case var*)
  436. x, y, z, w: ORG.Item;
  437. L0, L1, rx: LONGINT;
  438. PROCEDURE TypeCase(obj: ORB.Object; VAR x: ORG.Item);
  439. VAR typobj: ORB.Object;
  440. BEGIN
  441. IF sym = ORS.ident THEN
  442. qualident(typobj); ORG.MakeItem(x, obj, level);
  443. IF typobj.class # ORB.Typ THEN ORS.Mark("not a type") END ;
  444. TypeTest(x, typobj.type, FALSE); obj.type := typobj.type;
  445. ORG.CFJump(x); Check(ORS.colon, ": expected"); StatSequence
  446. ELSE ORG.CFJump(x); ORS.Mark("type id expected")
  447. END
  448. END TypeCase;
  449. PROCEDURE SkipCase;
  450. BEGIN
  451. WHILE sym # ORS.colon DO ORS.Get(sym) END ;
  452. ORS.Get(sym); StatSequence
  453. END SkipCase;
  454. BEGIN (* StatSequence *)
  455. REPEAT (*sync*) obj := NIL;
  456. IF ~((sym >= ORS.ident) & (sym <= ORS.for) OR (sym >= ORS.semicolon)) THEN
  457. ORS.Mark("statement expected");
  458. REPEAT ORS.Get(sym) UNTIL (sym >= ORS.ident)
  459. END ;
  460. IF sym = ORS.ident THEN
  461. qualident(obj); ORG.MakeItem(x, obj, level);
  462. IF x.mode = ORB.SProc THEN StandProc(obj.val)
  463. ELSE selector(x);
  464. IF sym = ORS.becomes THEN (*assignment*)
  465. ORS.Get(sym); CheckReadOnly(x); expression(y);
  466. IF CompTypes(x.type, y.type, FALSE) THEN
  467. IF (x.type.form <= ORB.Pointer) OR (x.type.form = ORB.Proc) THEN ORG.Store(x, y)
  468. ELSE ORG.StoreStruct(x, y)
  469. END
  470. ELSIF (x.type.form = ORB.Array) & (y.type.form = ORB.Array) & (x.type.base = y.type.base) & (y.type.len < 0) THEN
  471. ORG.StoreStruct(x, y)
  472. ELSIF (x.type.form = ORB.Array) & (x.type.base.form = ORB.Char) & (y.type.form = ORB.String) THEN
  473. ORG.CopyString(x, y)
  474. ELSIF (x.type.form = ORB.Int) & (y.type.form = ORB.Int) THEN ORG.Store(x, y) (*BYTE*)
  475. ELSIF (x.type.form = ORB.Char) & (y.type.form = ORB.String) & (y.b = 2) THEN
  476. ORG.StrToChar(y); ORG.Store(x, y)
  477. ELSE ORS.Mark("illegal assignment")
  478. END
  479. ELSIF sym = ORS.eql THEN ORS.Mark("should be :="); ORS.Get(sym); expression(y)
  480. ELSIF sym = ORS.lparen THEN (*procedure call*)
  481. ORS.Get(sym);
  482. IF (x.type.form = ORB.Proc) & (x.type.base.form = ORB.NoTyp) THEN
  483. ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx)
  484. ELSE ORS.Mark("not a procedure"); ParamList(x)
  485. END
  486. ELSIF x.type.form = ORB.Proc THEN (*procedure call without parameters*)
  487. IF x.type.nofpar > 0 THEN ORS.Mark("missing parameters") END ;
  488. IF x.type.base.form = ORB.NoTyp THEN ORG.PrepCall(x, rx); ORG.Call(x, rx) ELSE ORS.Mark("not a procedure") END
  489. ELSIF x.mode = ORB.Typ THEN ORS.Mark("illegal assignment")
  490. ELSE ORS.Mark("not a procedure")
  491. END
  492. END
  493. ELSIF sym = ORS.if THEN
  494. ORS.Get(sym); expression(x); CheckBool(x); ORG.CFJump(x);
  495. Check(ORS.then, "no THEN");
  496. StatSequence; L0 := 0;
  497. WHILE sym = ORS.elsif DO
  498. ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); expression(x); CheckBool(x);
  499. ORG.CFJump(x); Check(ORS.then, "no THEN"); StatSequence
  500. END ;
  501. IF sym = ORS.else THEN ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); StatSequence
  502. ELSE ORG.Fixup(x)
  503. END ;
  504. ORG.FixLink(L0); Check(ORS.end, "no END")
  505. ELSIF sym = ORS.while THEN
  506. ORS.Get(sym); L0 := ORG.Here(); expression(x); CheckBool(x); ORG.CFJump(x);
  507. Check(ORS.do, "no DO"); StatSequence; ORG.BJump(L0);
  508. WHILE sym = ORS.elsif DO
  509. ORS.Get(sym); ORG.Fixup(x); expression(x); CheckBool(x); ORG.CFJump(x);
  510. Check(ORS.do, "no DO"); StatSequence; ORG.BJump(L0)
  511. END ;
  512. ORG.Fixup(x); Check(ORS.end, "no END")
  513. ELSIF sym = ORS.repeat THEN
  514. ORS.Get(sym); L0 := ORG.Here(); StatSequence;
  515. IF sym = ORS.until THEN
  516. ORS.Get(sym); expression(x); CheckBool(x); ORG.CBJump(x, L0)
  517. ELSE ORS.Mark("missing UNTIL")
  518. END
  519. ELSIF sym = ORS.for THEN
  520. ORS.Get(sym);
  521. IF sym = ORS.ident THEN
  522. qualident(obj); ORG.MakeItem(x, obj, level); CheckInt(x); CheckReadOnly(x);
  523. IF sym = ORS.becomes THEN
  524. ORS.Get(sym); expression(y); CheckInt(y); ORG.For0(x, y); L0 := ORG.Here();
  525. Check(ORS.to, "no TO"); expression(z); CheckInt(z); obj.rdo := TRUE;
  526. IF sym = ORS.by THEN ORS.Get(sym); expression(w); CheckConst(w); CheckInt(w)
  527. ELSE ORG.MakeConstItem(w, ORB.intType, 1)
  528. END ;
  529. Check(ORS.do, "no DO"); ORG.For1(x, y, z, w, L1);
  530. StatSequence; Check(ORS.end, "no END");
  531. ORG.For2(x, y, w); ORG.BJump(L0); ORG.FixLink(L1); obj.rdo := FALSE
  532. ELSE ORS.Mark(":= expected")
  533. END
  534. ELSE ORS.Mark("identifier expected")
  535. END
  536. ELSIF sym = ORS.case THEN
  537. ORS.Get(sym);
  538. IF sym = ORS.ident THEN
  539. qualident(obj); orgtype := obj.type;
  540. IF (orgtype.form = ORB.Pointer) OR (orgtype.form = ORB.Record) & (obj.class = ORB.Par) THEN
  541. Check(ORS.of, "OF expected"); TypeCase(obj, x); L0 := 0;
  542. WHILE sym = ORS.bar DO
  543. ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); obj.type := orgtype; TypeCase(obj, x)
  544. END ;
  545. ORG.Fixup(x); ORG.FixLink(L0); obj.type := orgtype
  546. ELSE ORS.Mark("numeric case not implemented");
  547. Check(ORS.of, "OF expected"); SkipCase;
  548. WHILE sym = ORS.bar DO SkipCase END
  549. END
  550. ELSE ORS.Mark("ident expected")
  551. END ;
  552. Check(ORS.end, "no END")
  553. END ;
  554. ORG.CheckRegs;
  555. IF sym = ORS.semicolon THEN ORS.Get(sym)
  556. ELSIF sym < ORS.semicolon THEN ORS.Mark("missing semicolon?")
  557. END
  558. UNTIL sym > ORS.semicolon
  559. END StatSequence;
  560. (* Types and declarations *)
  561. PROCEDURE IdentList(class: INTEGER; VAR first: ORB.Object);
  562. VAR obj: ORB.Object;
  563. BEGIN
  564. IF sym = ORS.ident THEN
  565. ORB.NewObj(first, ORS.id, class); ORS.Get(sym); CheckExport(first.expo);
  566. WHILE sym = ORS.comma DO
  567. ORS.Get(sym);
  568. IF sym = ORS.ident THEN ORB.NewObj(obj, ORS.id, class); ORS.Get(sym); CheckExport(obj.expo)
  569. ELSE ORS.Mark("ident?")
  570. END
  571. END;
  572. IF sym = ORS.colon THEN ORS.Get(sym) ELSE ORS.Mark(":?") END
  573. ELSE first := NIL
  574. END
  575. END IdentList;
  576. PROCEDURE ArrayType(VAR type: ORB.Type);
  577. VAR x: ORG.Item; typ: ORB.Type; len: LONGINT;
  578. BEGIN NEW(typ); typ.form := ORB.NoTyp;
  579. expression(x);
  580. IF (x.mode = ORB.Const) & (x.type.form = ORB.Int) & (x.a >= 0) THEN len := x.a
  581. ELSE len := 1; ORS.Mark("not a valid length")
  582. END ;
  583. IF sym = ORS.of THEN ORS.Get(sym); Type(typ.base);
  584. IF (typ.base.form = ORB.Array) & (typ.base.len < 0) THEN ORS.Mark("dyn array not allowed") END
  585. ELSIF sym = ORS.comma THEN ORS.Get(sym); ArrayType(typ.base)
  586. ELSE ORS.Mark("missing OF"); typ.base := ORB.intType
  587. END ;
  588. typ.size := (len * typ.base.size + 3) DIV 4 * 4;
  589. typ.form := ORB.Array; typ.len := len; type := typ
  590. END ArrayType;
  591. PROCEDURE RecordType(VAR type: ORB.Type);
  592. VAR obj, obj0, new, bot, base: ORB.Object;
  593. typ, tp: ORB.Type;
  594. offset, off, n: LONGINT;
  595. BEGIN NEW(typ); typ.form := ORB.NoTyp; typ.base := NIL; typ.mno := -level; typ.nofpar := 0; offset := 0; bot := NIL;
  596. IF sym = ORS.lparen THEN
  597. ORS.Get(sym); (*record extension*)
  598. IF level # 0 THEN ORS.Mark("extension of local types not implemented") END ;
  599. IF sym = ORS.ident THEN
  600. qualident(base);
  601. IF base.class = ORB.Typ THEN
  602. IF base.type.form = ORB.Record THEN typ.base := base.type
  603. ELSE typ.base := ORB.intType; ORS.Mark("invalid extension")
  604. END ;
  605. typ.nofpar := typ.base.nofpar + 1; (*"nofpar" here abused for extension level*)
  606. bot := typ.base.dsc; offset := typ.base.size
  607. ELSE ORS.Mark("type expected")
  608. END
  609. ELSE ORS.Mark("ident expected")
  610. END ;
  611. Check(ORS.rparen, "no )")
  612. END ;
  613. WHILE sym = ORS.ident DO (*fields*)
  614. n := 0; obj := bot;
  615. WHILE sym = ORS.ident DO
  616. obj0 := obj;
  617. WHILE (obj0 # NIL) & (obj0.name # ORS.id) DO obj0 := obj0.next END ;
  618. IF obj0 # NIL THEN ORS.Mark("mult def") END ;
  619. NEW(new); ORS.CopyId(new.name); new.class := ORB.Fld; new.next := obj; obj := new; INC(n);
  620. ORS.Get(sym); CheckExport(new.expo);
  621. IF (sym # ORS.comma) & (sym # ORS.colon) THEN ORS.Mark("comma expected")
  622. ELSIF sym = ORS.comma THEN ORS.Get(sym)
  623. END
  624. END ;
  625. Check(ORS.colon, "colon expected"); Type(tp);
  626. IF (tp.form = ORB.Array) & (tp.len < 0) THEN ORS.Mark("dyn array not allowed") END ;
  627. IF tp.size > 1 THEN offset := (offset+3) DIV 4 * 4 END ;
  628. offset := offset + n * tp.size; off := offset; obj0 := obj;
  629. WHILE obj0 # bot DO obj0.type := tp; obj0.lev := 0; off := off - tp.size; obj0.val := off; obj0 := obj0.next END ;
  630. bot := obj;
  631. IF sym = ORS.semicolon THEN ORS.Get(sym) ELSIF sym # ORS.end THEN ORS.Mark(" ; or END") END
  632. END ;
  633. typ.form := ORB.Record; typ.dsc := bot; typ.size := (offset + 3) DIV 4 * 4; type := typ
  634. END RecordType;
  635. PROCEDURE FPSection(VAR adr: LONGINT; VAR nofpar: INTEGER);
  636. VAR obj, first: ORB.Object; tp: ORB.Type;
  637. parsize: LONGINT; cl: INTEGER; rdo: BOOLEAN;
  638. BEGIN
  639. IF sym = ORS.var THEN ORS.Get(sym); cl := ORB.Par ELSE cl := ORB.Var END ;
  640. IdentList(cl, first); FormalType(tp, 0); rdo := FALSE;
  641. IF (cl = ORB.Var) & (tp.form >= ORB.Array) THEN cl := ORB.Par; rdo := TRUE END ;
  642. IF (tp.form = ORB.Array) & (tp.len < 0) OR (tp.form = ORB.Record) THEN
  643. parsize := 2*ORG.WordSize (*open array or record, needs second word for length or type tag*)
  644. ELSE parsize := ORG.WordSize
  645. END ;
  646. obj := first;
  647. WHILE obj # NIL DO
  648. INC(nofpar); obj.class := cl; obj.type := tp; obj.rdo := rdo; obj.lev := level; obj.val := adr;
  649. adr := adr + parsize; obj := obj.next
  650. END ;
  651. IF adr >= 52 THEN ORS.Mark("too many parameters") END
  652. END FPSection;
  653. PROCEDURE ProcedureType(ptype: ORB.Type; VAR parblksize: LONGINT);
  654. VAR obj: ORB.Object; size: LONGINT; nofpar: INTEGER;
  655. BEGIN ptype.base := ORB.noType; size := parblksize; nofpar := 0; ptype.dsc := NIL;
  656. IF sym = ORS.lparen THEN
  657. ORS.Get(sym);
  658. IF sym = ORS.rparen THEN ORS.Get(sym)
  659. ELSE FPSection(size, nofpar);
  660. WHILE sym = ORS.semicolon DO ORS.Get(sym); FPSection(size, nofpar) END ;
  661. Check(ORS.rparen, "no )")
  662. END ;
  663. IF sym = ORS.colon THEN (*function*)
  664. ORS.Get(sym);
  665. IF sym = ORS.ident THEN
  666. qualident(obj); ptype.base := obj.type;
  667. IF ~((obj.class = ORB.Typ) & (obj.type.form IN {ORB.Byte .. ORB.Pointer, ORB.Proc})) THEN
  668. ORS.Mark("illegal function type")
  669. END
  670. ELSE ORS.Mark("type identifier expected")
  671. END
  672. END
  673. END ;
  674. ptype.nofpar := nofpar; parblksize := size
  675. END ProcedureType;
  676. PROCEDURE FormalType0(VAR typ: ORB.Type; dim: INTEGER);
  677. VAR obj: ORB.Object; dmy: LONGINT;
  678. BEGIN
  679. IF sym = ORS.ident THEN
  680. qualident(obj);
  681. IF obj.class = ORB.Typ THEN typ := obj.type ELSE ORS.Mark("not a type"); typ := ORB.intType END
  682. ELSIF sym = ORS.array THEN
  683. ORS.Get(sym); Check(ORS.of, "OF ?");
  684. IF dim >= 1 THEN ORS.Mark("multi-dimensional open arrays not implemented") END ;
  685. NEW(typ); typ.form := ORB.Array; typ.len := -1; typ.size := 2*ORG.WordSize;
  686. FormalType(typ.base, dim+1)
  687. ELSIF sym = ORS.procedure THEN
  688. ORS.Get(sym); ORB.OpenScope;
  689. NEW(typ); typ.form := ORB.Proc; typ.size := ORG.WordSize; dmy := 0; ProcedureType(typ, dmy);
  690. typ.dsc := ORB.topScope.next; ORB.CloseScope
  691. ELSE ORS.Mark("identifier expected"); typ := ORB.noType
  692. END
  693. END FormalType0;
  694. PROCEDURE CheckRecLevel(lev: INTEGER);
  695. BEGIN
  696. IF lev # 0 THEN ORS.Mark("ptr base must be global") END
  697. END CheckRecLevel;
  698. PROCEDURE Type0(VAR type: ORB.Type);
  699. VAR dmy: LONGINT; obj: ORB.Object; ptbase: PtrBase;
  700. BEGIN type := ORB.intType; (*sync*)
  701. IF (sym # ORS.ident) & (sym < ORS.array) THEN ORS.Mark("not a type");
  702. REPEAT ORS.Get(sym) UNTIL (sym = ORS.ident) OR (sym >= ORS.array)
  703. END ;
  704. IF sym = ORS.ident THEN
  705. qualident(obj);
  706. IF obj.class = ORB.Typ THEN
  707. IF (obj.type # NIL) & (obj.type.form # ORB.NoTyp) THEN type := obj.type END
  708. ELSE ORS.Mark("not a type or undefined")
  709. END
  710. ELSIF sym = ORS.array THEN ORS.Get(sym); ArrayType(type)
  711. ELSIF sym = ORS.record THEN
  712. ORS.Get(sym); RecordType(type); Check(ORS.end, "no END")
  713. ELSIF sym = ORS.pointer THEN
  714. ORS.Get(sym); Check(ORS.to, "no TO");
  715. NEW(type); type.form := ORB.Pointer; type.size := ORG.WordSize; type.base := ORB.intType;
  716. IF sym = ORS.ident THEN
  717. obj := ORB.thisObj();
  718. IF obj # NIL THEN
  719. IF (obj.class = ORB.Typ) & (obj.type.form IN {ORB.Record, ORB.NoTyp}) THEN
  720. CheckRecLevel(obj.lev); type.base := obj.type
  721. ELSIF obj.class = ORB.Mod THEN ORS.Mark("external base type not implemented")
  722. ELSE ORS.Mark("no valid base type")
  723. END
  724. ELSE CheckRecLevel(level); (*enter into list of forward references to be fixed in Declarations*)
  725. NEW(ptbase); ORS.CopyId(ptbase.name); ptbase.type := type; ptbase.next := pbsList; pbsList := ptbase
  726. END ;
  727. ORS.Get(sym)
  728. ELSE Type(type.base);
  729. IF (type.base.form # ORB.Record) OR (type.base.typobj = NIL) THEN ORS.Mark("must point to named record") END ;
  730. CheckRecLevel(level)
  731. END
  732. ELSIF sym = ORS.procedure THEN
  733. ORS.Get(sym); ORB.OpenScope;
  734. NEW(type); type.form := ORB.Proc; type.size := ORG.WordSize; dmy := 0;
  735. ProcedureType(type, dmy); type.dsc := ORB.topScope.next; ORB.CloseScope
  736. ELSE ORS.Mark("illegal type")
  737. END
  738. END Type0;
  739. PROCEDURE Declarations(VAR varsize: LONGINT);
  740. VAR obj, first: ORB.Object;
  741. x: ORG.Item; tp: ORB.Type; ptbase: PtrBase;
  742. expo: BOOLEAN; id: ORS.Ident;
  743. BEGIN (*sync*) pbsList := NIL;
  744. IF (sym < ORS.const) & (sym # ORS.end) & (sym # ORS.return) THEN ORS.Mark("declaration?");
  745. REPEAT ORS.Get(sym) UNTIL (sym >= ORS.const) OR (sym = ORS.end) OR (sym = ORS.return)
  746. END ;
  747. IF sym = ORS.const THEN
  748. ORS.Get(sym);
  749. WHILE sym = ORS.ident DO
  750. ORS.CopyId(id); ORS.Get(sym); CheckExport(expo);
  751. IF sym = ORS.eql THEN ORS.Get(sym) ELSE ORS.Mark("= ?") END;
  752. expression(x);
  753. IF (x.type.form = ORB.String) & (x.b = 2) THEN ORG.StrToChar(x) END ;
  754. ORB.NewObj(obj, id, ORB.Const); obj.expo := expo;
  755. IF x.mode = ORB.Const THEN obj.val := x.a; obj.lev := x.b; obj.type := x.type
  756. ELSE ORS.Mark("expression not constant"); obj.type := ORB.intType
  757. END;
  758. Check(ORS.semicolon, "; missing")
  759. END
  760. END ;
  761. IF sym = ORS.type THEN
  762. ORS.Get(sym);
  763. WHILE sym = ORS.ident DO
  764. ORS.CopyId(id); ORS.Get(sym); CheckExport(expo);
  765. IF sym = ORS.eql THEN ORS.Get(sym) ELSE ORS.Mark("=?") END ;
  766. Type(tp);
  767. ORB.NewObj(obj, id, ORB.Typ); obj.type := tp; obj.expo := expo; obj.lev := level;
  768. IF tp.typobj = NIL THEN tp.typobj := obj END ;
  769. IF expo & (obj.type.form = ORB.Record) THEN obj.exno := exno; INC(exno) ELSE obj.exno := 0 END ;
  770. IF tp.form = ORB.Record THEN
  771. ptbase := pbsList; (*check whether this is base of a pointer type; search and fixup*)
  772. WHILE ptbase # NIL DO
  773. IF obj.name = ptbase.name THEN ptbase.type.base := obj.type END ;
  774. ptbase := ptbase.next
  775. END ;
  776. IF level = 0 THEN ORG.BuildTD(tp, dc) END (*type descriptor; len used as its address*)
  777. END ;
  778. Check(ORS.semicolon, "; missing")
  779. END
  780. END ;
  781. IF sym = ORS.var THEN
  782. ORS.Get(sym);
  783. WHILE sym = ORS.ident DO
  784. IdentList(ORB.Var, first); Type(tp);
  785. obj := first;
  786. WHILE obj # NIL DO
  787. obj.type := tp; obj.lev := level;
  788. IF tp.size > 1 THEN varsize := (varsize + 3) DIV 4 * 4 (*align*) END ;
  789. obj.val := varsize; varsize := varsize + obj.type.size;
  790. IF obj.expo THEN obj.exno := exno; INC(exno) END ;
  791. obj := obj.next
  792. END ;
  793. Check(ORS.semicolon, "; missing")
  794. END
  795. END ;
  796. varsize := (varsize + 3) DIV 4 * 4;
  797. ptbase := pbsList;
  798. WHILE ptbase # NIL DO
  799. IF ptbase.type.base.form = ORB.Int THEN ORS.Mark("undefined pointer base of") END ;
  800. ptbase := ptbase.next
  801. END ;
  802. IF (sym >= ORS.const) & (sym <= ORS.var) THEN ORS.Mark("declaration in bad order") END
  803. END Declarations;
  804. PROCEDURE ProcedureDecl;
  805. VAR proc: ORB.Object;
  806. type: ORB.Type;
  807. procid: ORS.Ident;
  808. x: ORG.Item;
  809. locblksize, parblksize, L: LONGINT;
  810. int: BOOLEAN;
  811. BEGIN (* ProcedureDecl *) int := FALSE; ORS.Get(sym);
  812. IF sym = ORS.times THEN ORS.Get(sym); int := TRUE END ;
  813. IF sym = ORS.ident THEN
  814. ORS.CopyId(procid); ORS.Get(sym);
  815. ORB.NewObj(proc, ORS.id, ORB.Const);
  816. IF int THEN parblksize := 12 ELSE parblksize := 4 END ;
  817. NEW(type); type.form := ORB.Proc; type.size := ORG.WordSize;
  818. proc.type := type; proc.val := -1; proc.lev := level;
  819. CheckExport(proc.expo);
  820. IF proc.expo THEN proc.exno := exno; INC(exno) END ;
  821. ORB.OpenScope; INC(level); type.base := ORB.noType;
  822. ProcedureType(type, parblksize); (*formal parameter list*)
  823. Check(ORS.semicolon, "no ;"); locblksize := parblksize;
  824. Declarations(locblksize);
  825. proc.val := ORG.Here() * 4; proc.type.dsc := ORB.topScope.next;
  826. IF sym = ORS.procedure THEN
  827. L := 0; ORG.FJump(L);
  828. REPEAT ProcedureDecl; Check(ORS.semicolon, "no ;") UNTIL sym # ORS.procedure;
  829. ORG.FixOne(L); proc.val := ORG.Here() * 4; proc.type.dsc := ORB.topScope.next
  830. END ;
  831. ORG.Enter(parblksize, locblksize, int);
  832. IF sym = ORS.begin THEN ORS.Get(sym); StatSequence END ;
  833. IF sym = ORS.return THEN
  834. ORS.Get(sym); expression(x);
  835. IF type.base = ORB.noType THEN ORS.Mark("this is not a function")
  836. ELSIF ~CompTypes(type.base, x.type, FALSE) THEN ORS.Mark("wrong result type")
  837. END
  838. ELSIF type.base.form # ORB.NoTyp THEN
  839. ORS.Mark("function without result"); type.base := ORB.noType
  840. END ;
  841. ORG.Return(type.base.form, x, locblksize, int);
  842. ORB.CloseScope; DEC(level); Check(ORS.end, "no END");
  843. IF sym = ORS.ident THEN
  844. IF ORS.id # procid THEN ORS.Mark("no match") END ;
  845. ORS.Get(sym)
  846. ELSE ORS.Mark("no proc id")
  847. END
  848. ELSE ORS.Mark("proc id expected")
  849. END
  850. END ProcedureDecl;
  851. PROCEDURE Import;
  852. VAR impid, impid1: ORS.Ident;
  853. BEGIN
  854. IF sym = ORS.ident THEN
  855. ORS.CopyId(impid); ORS.Get(sym);
  856. IF sym = ORS.becomes THEN
  857. ORS.Get(sym);
  858. IF sym = ORS.ident THEN ORS.CopyId(impid1); ORS.Get(sym)
  859. ELSE ORS.Mark("id expected"); impid1 := impid
  860. END
  861. ELSE impid1 := impid
  862. END ;
  863. ORB.Import(impid, impid1)
  864. ELSE ORS.Mark("id expected")
  865. END
  866. END Import;
  867. PROCEDURE Module;
  868. VAR key: LONGINT;
  869. BEGIN Texts.WriteString(W, " compiling "); ORS.Get(sym);
  870. IF sym = ORS.module THEN
  871. ORS.Get(sym);
  872. IF sym = ORS.times THEN version := 0; dc := 8; Texts.Write(W, "*"); ORS.Get(sym) ELSE dc := 0; version := 1 END ;
  873. ORB.Init; ORB.OpenScope;
  874. IF sym = ORS.ident THEN
  875. ORS.CopyId(modid); ORS.Get(sym);
  876. Texts.WriteString(W, modid); Texts.Append(Oberon.Log, W.buf)
  877. ELSE ORS.Mark("identifier expected")
  878. END ;
  879. Check(ORS.semicolon, "no ;"); level := 0; exno := 1; key := 0;
  880. IF sym = ORS.import THEN
  881. ORS.Get(sym); Import;
  882. WHILE sym = ORS.comma DO ORS.Get(sym); Import END ;
  883. Check(ORS.semicolon, "; missing")
  884. END ;
  885. ORG.Open(version); Declarations(dc); ORG.SetDataSize((dc + 3) DIV 4 * 4);
  886. WHILE sym = ORS.procedure DO ProcedureDecl; Check(ORS.semicolon, "no ;") END ;
  887. ORG.Header;
  888. IF sym = ORS.begin THEN ORS.Get(sym); StatSequence END ;
  889. Check(ORS.end, "no END");
  890. IF sym = ORS.ident THEN
  891. IF ORS.id # modid THEN ORS.Mark("no match") END ;
  892. ORS.Get(sym)
  893. ELSE ORS.Mark("identifier missing")
  894. END ;
  895. IF sym # ORS.period THEN ORS.Mark("period missing") END ;
  896. IF (ORS.errcnt = 0) & (version # 0) THEN
  897. ORB.Export(modid, newSF, key);
  898. IF newSF THEN Texts.WriteString(W, " new symbol file") END
  899. END ;
  900. IF ORS.errcnt = 0 THEN
  901. ORG.Close(modid, key, exno);
  902. Texts.WriteInt(W, ORG.pc, 6); Texts.WriteInt(W, dc, 6); Texts.WriteHex(W, key)
  903. ELSE Texts.WriteLn(W); Texts.WriteString(W, "compilation FAILED")
  904. END ;
  905. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  906. ORB.CloseScope; pbsList := NIL
  907. ELSE ORS.Mark("must start with MODULE")
  908. END
  909. END Module;
  910. PROCEDURE Option(VAR S: Texts.Scanner);
  911. BEGIN newSF := FALSE;
  912. IF S.nextCh = "/" THEN
  913. Texts.Scan(S); Texts.Scan(S);
  914. IF (S.class = Texts.Name) & (S.s[0] = "s") THEN newSF := TRUE END
  915. END
  916. END Option;
  917. PROCEDURE Compile*;
  918. VAR beg, end, time: LONGINT;
  919. T: Texts.Text;
  920. S: Texts.Scanner;
  921. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  922. IF S.class = Texts.Char THEN
  923. IF S.c = "@" THEN
  924. Option(S); Oberon.GetSelection(T, beg, end, time);
  925. IF time >= 0 THEN ORS.Init(T, beg); Module END
  926. ELSIF S.c = "^" THEN
  927. Option(S); Oberon.GetSelection(T, beg, end, time);
  928. IF time >= 0 THEN
  929. Texts.OpenScanner(S, T, beg); Texts.Scan(S);
  930. IF S.class = Texts.Name THEN
  931. Texts.WriteString(W, S.s); NEW(T); Texts.Open(T, S.s);
  932. IF T.len > 0 THEN ORS.Init(T, 0); Module END
  933. END
  934. END
  935. END
  936. ELSE
  937. WHILE S.class = Texts.Name DO
  938. NEW(T); Texts.Open(T, S.s);
  939. IF T.len > 0 THEN Option(S); ORS.Init(T, 0); Module
  940. ELSE Texts.WriteString(W, S.s); Texts.WriteString(W, " not found");
  941. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  942. END ;
  943. IF (T.len # 0) & (ORS.errcnt = 0) THEN Texts.Scan(S) ELSE S.class := 0 END
  944. END
  945. END ;
  946. Oberon.Collect(0)
  947. END Compile;
  948. BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "OR Compiler 8.2.2020");
  949. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  950. NEW(dummy); dummy.class := ORB.Var; dummy.type := ORB.intType;
  951. expression := expression0; Type := Type0; FormalType := FormalType0
  952. END ORP.