ORP.Mod.txt 41 KB

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