ORP.Mod.txt 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. MODULE ORP; (*N. Wirth 1.7.97 / 18.4.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: 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) & (p0.rdo = p1.rdo) &
  155. ((p0.type = p1.type) OR
  156. (p0.type.form = ORB.Array) & (p1.type.form = ORB.Array) & (p0.type.len = p1.type.len) & (p0.type.base = p1.type.base) OR
  157. (p0.type.form = ORB.Proc) & (p1.type.form = ORB.Proc) & EqualSignatures(p0.type, p1.type))
  158. THEN p0 := p0.next; p1 := p1.next
  159. ELSE p0 := NIL; com := FALSE
  160. END
  161. END
  162. ELSE com := FALSE
  163. END ;
  164. RETURN com
  165. END EqualSignatures;
  166. BEGIN (*check for assignment compatibility*)
  167. RETURN (t0 = t1)
  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. ORG.OpenArrayParam(x)
  189. ELSIF (x.type.form = ORB.String) & varpar & par.rdo & (par.type.form = ORB.Array) &
  190. (par.type.base.form = ORB.Char) & (par.type.len < 0) THEN ORG.StringParam(x)
  191. ELSIF ~varpar & (par.type.form = ORB.Int) & (x.type.form = ORB.Int) THEN ORG.ValueParam(x) (*BYTE*)
  192. ELSIF (x.type.form = ORB.String) & (x.b = 2) & (par.class = ORB.Var) & (par.type.form = ORB.Char) THEN
  193. ORG.StrToChar(x); ORG.ValueParam(x)
  194. ELSIF (par.type.form = ORB.Array) & (par.type.base = ORB.byteType) &
  195. (par.type.len > 0) & (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 x.type = y.type THEN
  360. IF (xf IN {ORB.Char, ORB.Int}) THEN ORG.IntRelation(rel, x, y)
  361. ELSIF xf = ORB.Real THEN ORG.RealRelation(rel, x, y)
  362. ELSIF (xf IN {ORB.Set, ORB.Pointer, ORB.Proc, ORB.NilTyp, ORB.Bool}) THEN
  363. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  364. ELSIF (xf = ORB.Array) & (x.type.base.form = ORB.Char) OR (xf = ORB.String) THEN
  365. ORG.StringRelation(rel, x, y)
  366. ELSE ORS.Mark("illegal comparison")
  367. END
  368. ELSIF (xf IN {ORB.Pointer, ORB.Proc}) & (yf = ORB.NilTyp)
  369. OR (yf IN {ORB.Pointer, ORB.Proc}) & (xf = ORB.NilTyp) THEN
  370. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  371. ELSIF (xf = ORB.Pointer) & (yf = ORB.Pointer) &
  372. (IsExtension(x.type.base, y.type.base) OR IsExtension(y.type.base, x.type.base)) THEN
  373. IF rel <= ORS.neq THEN ORG.IntRelation(rel, x, y) ELSE ORS.Mark("only = or #") END
  374. ELSIF (xf = ORB.Array) & (x.type.base.form = ORB.Char) &
  375. ((yf = ORB.String) OR (yf = ORB.Array) & (y.type.base.form = ORB.Char))
  376. OR (yf = ORB.Array) & (y.type.base.form = ORB.Char) & (xf = ORB.String) THEN
  377. ORG.StringRelation(rel, x, y)
  378. ELSIF (xf = ORB.Char) & (yf = ORB.String) & (y.b = 2) THEN
  379. ORG.StrToChar(y); ORG.IntRelation(rel, x, y)
  380. ELSIF (yf = ORB.Char) & (xf = ORB.String) & (x.b = 2) THEN
  381. ORG.StrToChar(x); ORG.IntRelation(rel, x, y)
  382. ELSIF (xf = ORB.Int) & (yf = ORB.Int) THEN ORG.IntRelation(rel, x, y) (*BYTE*)
  383. ELSE ORS.Mark("illegal comparison")
  384. END ;
  385. x.type := ORB.boolType
  386. ELSIF sym = ORS.in THEN
  387. ORS.Get(sym); CheckInt(x); SimpleExpression(y); CheckSet(y); ORG.In(x, y) ;
  388. x.type := ORB.boolType
  389. ELSIF sym = ORS.is THEN
  390. ORS.Get(sym); qualident(obj); TypeTest(x, obj.type, FALSE) ;
  391. x.type := ORB.boolType
  392. END
  393. END expression0;
  394. (* statements *)
  395. PROCEDURE StandProc(pno: LONGINT);
  396. VAR nap, npar: LONGINT; (*nof actual/formal parameters*)
  397. x, y, z: ORG.Item;
  398. BEGIN Check(ORS.lparen, "no (");
  399. npar := pno MOD 10; pno := pno DIV 10; expression(x); nap := 1;
  400. IF sym = ORS.comma THEN
  401. ORS.Get(sym); expression(y); nap := 2; z.type := ORB.noType;
  402. WHILE sym = ORS.comma DO ORS.Get(sym); expression(z); INC(nap) END
  403. ELSE y.type := ORB.noType
  404. END ;
  405. Check(ORS.rparen, "no )");
  406. IF (npar = nap) OR (pno IN {0, 1}) THEN
  407. IF pno IN {0, 1} THEN (*INC, DEC*)
  408. CheckInt(x); CheckReadOnly(x);
  409. IF y.type # ORB.noType THEN CheckInt(y) END ;
  410. ORG.Increment(pno, x, y)
  411. ELSIF pno IN {2, 3} THEN (*INCL, EXCL*)
  412. CheckSet(x); CheckReadOnly(x); CheckInt(y); ORG.Include(pno-2, x, y)
  413. ELSIF pno = 4 THEN CheckBool(x); ORG.Assert(x)
  414. ELSIF pno = 5 THEN(*NEW*) CheckReadOnly(x);
  415. IF (x.type.form = ORB.Pointer) & (x.type.base.form = ORB.Record) THEN ORG.New(x)
  416. ELSE ORS.Mark("not a pointer to record")
  417. END
  418. ELSIF pno = 6 THEN CheckReal(x); CheckInt(y); CheckReadOnly(x); ORG.Pack(x, y)
  419. ELSIF pno = 7 THEN CheckReal(x); CheckInt(y); CheckReadOnly(x); ORG.Unpk(x, y)
  420. ELSIF pno = 8 THEN
  421. IF x.type.form <= ORB.Set THEN ORG.Led(x) ELSE ORS.Mark("bad type") END
  422. ELSIF pno = 10 THEN CheckInt(x); ORG.Get(x, y)
  423. ELSIF pno = 11 THEN CheckInt(x); ORG.Put(x, y)
  424. ELSIF pno = 12 THEN CheckInt(x); CheckInt(y); CheckInt(z); ORG.Copy(x, y, z)
  425. ELSIF pno = 13 THEN CheckConst(x); CheckInt(x); ORG.LDPSR(x)
  426. ELSIF pno = 14 THEN CheckInt(x); ORG.LDREG(x, y)
  427. END
  428. ELSE ORS.Mark("wrong nof parameters")
  429. END
  430. END StandProc;
  431. PROCEDURE StatSequence;
  432. VAR obj: ORB.Object;
  433. orgtype: ORB.Type; (*original type of case var*)
  434. x, y, z, w: ORG.Item;
  435. L0, L1, rx: LONGINT;
  436. PROCEDURE TypeCase(obj: ORB.Object; VAR x: ORG.Item);
  437. VAR typobj: ORB.Object;
  438. BEGIN
  439. IF sym = ORS.ident THEN
  440. qualident(typobj); ORG.MakeItem(x, obj, level);
  441. IF typobj.class # ORB.Typ THEN ORS.Mark("not a type") END ;
  442. TypeTest(x, typobj.type, FALSE); obj.type := typobj.type;
  443. ORG.CFJump(x); Check(ORS.colon, ": expected"); StatSequence
  444. ELSE ORG.CFJump(x); ORS.Mark("type id expected")
  445. END
  446. END TypeCase;
  447. PROCEDURE SkipCase;
  448. BEGIN
  449. WHILE sym # ORS.colon DO ORS.Get(sym) END ;
  450. ORS.Get(sym); StatSequence
  451. END SkipCase;
  452. BEGIN (* StatSequence *)
  453. REPEAT (*sync*) obj := NIL;
  454. IF ~((sym = ORS.ident) OR (sym >= ORS.if) & (sym <= ORS.for) OR (sym >= ORS.semicolon)) THEN
  455. ORS.Mark("statement expected");
  456. REPEAT ORS.Get(sym) UNTIL (sym = ORS.ident) OR (sym >= ORS.if)
  457. END ;
  458. IF sym = ORS.ident THEN
  459. qualident(obj); ORG.MakeItem(x, obj, level);
  460. IF x.mode = ORB.SProc THEN StandProc(obj.val)
  461. ELSE selector(x);
  462. IF sym = ORS.becomes THEN (*assignment*)
  463. ORS.Get(sym); CheckReadOnly(x); expression(y);
  464. IF CompTypes(x.type, y.type, FALSE) THEN
  465. IF (x.type.form <= ORB.Pointer) OR (x.type.form = ORB.Proc) THEN ORG.Store(x, y)
  466. ELSE ORG.StoreStruct(x, y)
  467. END
  468. ELSIF (x.type.form = ORB.Array) & (y.type.form = ORB.Array) & (x.type.base = y.type.base) & (y.type.len < 0) THEN
  469. ORG.StoreStruct(x, y)
  470. ELSIF (x.type.form = ORB.Array) & (x.type.base.form = ORB.Char) & (y.type.form = ORB.String) THEN
  471. ORG.CopyString(x, y)
  472. ELSIF (x.type.form = ORB.Int) & (y.type.form = ORB.Int) THEN ORG.Store(x, y) (*BYTE*)
  473. ELSIF (x.type.form = ORB.Char) & (y.type.form = ORB.String) & (y.b = 2) THEN
  474. ORG.StrToChar(y); ORG.Store(x, y)
  475. ELSE ORS.Mark("illegal assignment")
  476. END
  477. ELSIF sym = ORS.eql THEN ORS.Mark("should be :="); ORS.Get(sym); expression(y)
  478. ELSIF sym = ORS.lparen THEN (*procedure call*)
  479. ORS.Get(sym);
  480. IF (x.type.form = ORB.Proc) & (x.type.base.form = ORB.NoTyp) THEN
  481. ORG.PrepCall(x, rx); ParamList(x); ORG.Call(x, rx)
  482. ELSE ORS.Mark("not a procedure"); ParamList(x)
  483. END
  484. ELSIF x.type.form = ORB.Proc THEN (*procedure call without parameters*)
  485. IF x.type.nofpar > 0 THEN ORS.Mark("missing parameters") END ;
  486. IF x.type.base.form = ORB.NoTyp THEN ORG.PrepCall(x, rx); ORG.Call(x, rx) ELSE ORS.Mark("not a procedure") END
  487. ELSIF x.mode = ORB.Typ THEN ORS.Mark("illegal assignment")
  488. ELSE ORS.Mark("not a procedure")
  489. END
  490. END
  491. ELSIF sym = ORS.if THEN
  492. ORS.Get(sym); expression(x); CheckBool(x); ORG.CFJump(x);
  493. Check(ORS.then, "no THEN");
  494. StatSequence; L0 := 0;
  495. WHILE sym = ORS.elsif DO
  496. ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); expression(x); CheckBool(x);
  497. ORG.CFJump(x); Check(ORS.then, "no THEN"); StatSequence
  498. END ;
  499. IF sym = ORS.else THEN ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); StatSequence
  500. ELSE ORG.Fixup(x)
  501. END ;
  502. ORG.FixLink(L0); Check(ORS.end, "no END")
  503. ELSIF sym = ORS.while THEN
  504. ORS.Get(sym); L0 := ORG.Here(); expression(x); CheckBool(x); ORG.CFJump(x);
  505. Check(ORS.do, "no DO"); StatSequence; ORG.BJump(L0);
  506. WHILE sym = ORS.elsif DO
  507. ORS.Get(sym); ORG.Fixup(x); expression(x); CheckBool(x); ORG.CFJump(x);
  508. Check(ORS.do, "no DO"); StatSequence; ORG.BJump(L0)
  509. END ;
  510. ORG.Fixup(x); Check(ORS.end, "no END")
  511. ELSIF sym = ORS.repeat THEN
  512. ORS.Get(sym); L0 := ORG.Here(); StatSequence;
  513. IF sym = ORS.until THEN
  514. ORS.Get(sym); expression(x); CheckBool(x); ORG.CBJump(x, L0)
  515. ELSE ORS.Mark("missing UNTIL")
  516. END
  517. ELSIF sym = ORS.for THEN
  518. ORS.Get(sym);
  519. IF sym = ORS.ident THEN
  520. qualident(obj); ORG.MakeItem(x, obj, level); CheckInt(x); CheckReadOnly(x);
  521. IF sym = ORS.becomes THEN
  522. ORS.Get(sym); expression(y); CheckInt(y); ORG.For0(x, y); L0 := ORG.Here();
  523. Check(ORS.to, "no TO"); expression(z); CheckInt(z); obj.rdo := TRUE;
  524. IF sym = ORS.by THEN ORS.Get(sym); expression(w); CheckConst(w); CheckInt(w)
  525. ELSE ORG.MakeConstItem(w, ORB.intType, 1)
  526. END ;
  527. Check(ORS.do, "no DO"); ORG.For1(x, y, z, w, L1);
  528. StatSequence; Check(ORS.end, "no END");
  529. ORG.For2(x, y, w); ORG.BJump(L0); ORG.FixLink(L1); obj.rdo := FALSE
  530. ELSE ORS.Mark(":= expected")
  531. END
  532. ELSE ORS.Mark("identifier expected")
  533. END
  534. ELSIF sym = ORS.case THEN
  535. ORS.Get(sym);
  536. IF sym = ORS.ident THEN
  537. qualident(obj); orgtype := obj.type;
  538. IF (orgtype.form = ORB.Pointer) OR (orgtype.form = ORB.Record) & (obj.class = ORB.Par) THEN
  539. Check(ORS.of, "OF expected"); TypeCase(obj, x); L0 := 0;
  540. WHILE sym = ORS.bar DO
  541. ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); obj.type := orgtype; TypeCase(obj, x)
  542. END ;
  543. ORG.Fixup(x); ORG.FixLink(L0); obj.type := orgtype
  544. ELSE ORS.Mark("numeric case not implemented");
  545. Check(ORS.of, "OF expected"); SkipCase;
  546. WHILE sym = ORS.bar DO SkipCase END
  547. END
  548. ELSE ORS.Mark("ident expected")
  549. END ;
  550. Check(ORS.end, "no END")
  551. END ;
  552. ORG.CheckRegs;
  553. IF sym = ORS.semicolon THEN ORS.Get(sym)
  554. ELSIF sym < ORS.semicolon THEN ORS.Mark("missing semicolon?")
  555. END
  556. UNTIL sym > ORS.semicolon
  557. END StatSequence;
  558. (* Types and declarations *)
  559. PROCEDURE IdentList(class: INTEGER; VAR first: ORB.Object);
  560. VAR obj: ORB.Object;
  561. BEGIN
  562. IF sym = ORS.ident THEN
  563. ORB.NewObj(first, ORS.id, class); ORS.Get(sym); CheckExport(first.expo);
  564. WHILE sym = ORS.comma DO
  565. ORS.Get(sym);
  566. IF sym = ORS.ident THEN ORB.NewObj(obj, ORS.id, class); ORS.Get(sym); CheckExport(obj.expo)
  567. ELSE ORS.Mark("ident?")
  568. END
  569. END;
  570. IF sym = ORS.colon THEN ORS.Get(sym) ELSE ORS.Mark(":?") END
  571. ELSE first := NIL
  572. END
  573. END IdentList;
  574. PROCEDURE ArrayType(VAR type: ORB.Type);
  575. VAR x: ORG.Item; typ: ORB.Type; len: LONGINT;
  576. BEGIN NEW(typ); typ.form := ORB.NoTyp;
  577. expression(x);
  578. IF (x.mode = ORB.Const) & (x.type.form = ORB.Int) & (x.a >= 0) THEN len := x.a
  579. ELSE len := 1; ORS.Mark("not a valid length")
  580. END ;
  581. IF sym = ORS.of THEN ORS.Get(sym); Type(typ.base);
  582. IF (typ.base.form = ORB.Array) & (typ.base.len < 0) THEN ORS.Mark("dyn array not allowed") END
  583. ELSIF sym = ORS.comma THEN ORS.Get(sym); ArrayType(typ.base)
  584. ELSE ORS.Mark("missing OF"); typ.base := ORB.intType
  585. END ;
  586. typ.size := (len * typ.base.size + 3) DIV 4 * 4;
  587. typ.form := ORB.Array; typ.len := len; type := typ
  588. END ArrayType;
  589. PROCEDURE RecordType(VAR type: ORB.Type);
  590. VAR obj, obj0, new, bot, base: ORB.Object;
  591. typ, tp: ORB.Type;
  592. offset, off, n: LONGINT;
  593. BEGIN NEW(typ); typ.form := ORB.NoTyp; typ.base := NIL; typ.mno := -level; typ.nofpar := 0; offset := 0; bot := NIL;
  594. IF sym = ORS.lparen THEN
  595. ORS.Get(sym); (*record extension*)
  596. IF level # 0 THEN ORS.Mark("extension of local types not implemented") END ;
  597. IF sym = ORS.ident THEN
  598. qualident(base);
  599. IF base.class = ORB.Typ THEN
  600. IF base.type.form = ORB.Record THEN typ.base := base.type
  601. ELSE typ.base := ORB.intType; ORS.Mark("invalid extension")
  602. END ;
  603. typ.nofpar := typ.base.nofpar + 1; (*"nofpar" here abused for extension level*)
  604. bot := typ.base.dsc; offset := typ.base.size
  605. ELSE ORS.Mark("type expected")
  606. END
  607. ELSE ORS.Mark("ident expected")
  608. END ;
  609. Check(ORS.rparen, "no )")
  610. END ;
  611. WHILE sym = ORS.ident DO (*fields*)
  612. n := 0; obj := bot;
  613. WHILE sym = ORS.ident DO
  614. obj0 := obj;
  615. WHILE (obj0 # NIL) & (obj0.name # ORS.id) DO obj0 := obj0.next END ;
  616. IF obj0 # NIL THEN ORS.Mark("mult def") END ;
  617. NEW(new); ORS.CopyId(new.name); new.class := ORB.Fld; new.next := obj; obj := new; INC(n);
  618. ORS.Get(sym); CheckExport(new.expo);
  619. IF (sym # ORS.comma) & (sym # ORS.colon) THEN ORS.Mark("comma expected")
  620. ELSIF sym = ORS.comma THEN ORS.Get(sym)
  621. END
  622. END ;
  623. Check(ORS.colon, "colon expected"); Type(tp);
  624. IF (tp.form = ORB.Array) & (tp.len < 0) THEN ORS.Mark("dyn array not allowed") END ;
  625. IF tp.size > 1 THEN offset := (offset+3) DIV 4 * 4 END ;
  626. offset := offset + n * tp.size; off := offset; obj0 := obj;
  627. WHILE obj0 # bot DO obj0.type := tp; obj0.lev := 0; off := off - tp.size; obj0.val := off; obj0 := obj0.next END ;
  628. bot := obj;
  629. IF sym = ORS.semicolon THEN ORS.Get(sym) ELSIF sym # ORS.end THEN ORS.Mark(" ; or END") END
  630. END ;
  631. typ.form := ORB.Record; typ.dsc := bot; typ.size := (offset + 3) DIV 4 * 4; type := typ
  632. END RecordType;
  633. PROCEDURE FPSection(VAR adr: LONGINT; VAR nofpar: INTEGER);
  634. VAR obj, first: ORB.Object; tp: ORB.Type;
  635. parsize: LONGINT; cl: INTEGER; rdo: BOOLEAN;
  636. BEGIN
  637. IF sym = ORS.var THEN ORS.Get(sym); cl := ORB.Par ELSE cl := ORB.Var END ;
  638. IdentList(cl, first); FormalType(tp, 0); rdo := FALSE;
  639. IF (cl = ORB.Var) & (tp.form >= ORB.Array) THEN cl := ORB.Par; rdo := TRUE END ;
  640. IF (tp.form = ORB.Array) & (tp.len < 0) OR (tp.form = ORB.Record) THEN
  641. parsize := 2*ORG.WordSize (*open array or record, needs second word for length or type tag*)
  642. ELSE parsize := ORG.WordSize
  643. END ;
  644. obj := first;
  645. WHILE obj # NIL DO
  646. INC(nofpar); obj.class := cl; obj.type := tp; obj.rdo := rdo; obj.lev := level; obj.val := adr;
  647. adr := adr + parsize; obj := obj.next
  648. END ;
  649. IF adr >= 52 THEN ORS.Mark("too many parameters") END
  650. END FPSection;
  651. PROCEDURE ProcedureType(ptype: ORB.Type; VAR parblksize: LONGINT);
  652. VAR obj: ORB.Object; size: LONGINT; nofpar: INTEGER;
  653. BEGIN ptype.base := ORB.noType; size := parblksize; nofpar := 0; ptype.dsc := NIL;
  654. IF sym = ORS.lparen THEN
  655. ORS.Get(sym);
  656. IF sym = ORS.rparen THEN ORS.Get(sym)
  657. ELSE FPSection(size, nofpar);
  658. WHILE sym = ORS.semicolon DO ORS.Get(sym); FPSection(size, nofpar) END ;
  659. Check(ORS.rparen, "no )")
  660. END ;
  661. ptype.nofpar := nofpar; parblksize := size;
  662. IF sym = ORS.colon THEN (*function*)
  663. ORS.Get(sym);
  664. IF sym = ORS.ident THEN
  665. qualident(obj); ptype.base := obj.type;
  666. IF ~((obj.class = ORB.Typ) & (obj.type.form IN {ORB.Byte .. ORB.Pointer, ORB.Proc})) THEN
  667. ORS.Mark("illegal function type")
  668. END
  669. ELSE ORS.Mark("type identifier expected")
  670. END
  671. END
  672. END
  673. END ProcedureType;
  674. PROCEDURE FormalType0(VAR typ: ORB.Type; dim: INTEGER);
  675. VAR obj: ORB.Object; dmy: LONGINT;
  676. BEGIN
  677. IF sym = ORS.ident THEN
  678. qualident(obj);
  679. IF obj.class = ORB.Typ THEN typ := obj.type ELSE ORS.Mark("not a type"); typ := ORB.intType END
  680. ELSIF sym = ORS.array THEN
  681. ORS.Get(sym); Check(ORS.of, "OF ?");
  682. IF dim >= 1 THEN ORS.Mark("multi-dimensional open arrays not implemented") END ;
  683. NEW(typ); typ.form := ORB.Array; typ.len := -1; typ.size := 2*ORG.WordSize;
  684. FormalType(typ.base, dim+1)
  685. ELSIF sym = ORS.procedure THEN
  686. ORS.Get(sym); ORB.OpenScope;
  687. NEW(typ); typ.form := ORB.Proc; typ.size := ORG.WordSize; dmy := 0; ProcedureType(typ, dmy);
  688. typ.dsc := ORB.topScope.next; ORB.CloseScope
  689. ELSE ORS.Mark("identifier expected"); typ := ORB.noType
  690. END
  691. END FormalType0;
  692. PROCEDURE CheckRecLevel(lev: INTEGER);
  693. BEGIN
  694. IF lev # 0 THEN ORS.Mark("ptr base must be global") END
  695. END CheckRecLevel;
  696. PROCEDURE Type0(VAR type: ORB.Type);
  697. VAR dmy: LONGINT; obj: ORB.Object; ptbase: PtrBase;
  698. BEGIN type := ORB.intType; (*sync*)
  699. IF (sym # ORS.ident) & (sym < ORS.array) THEN ORS.Mark("not a type");
  700. REPEAT ORS.Get(sym) UNTIL (sym = ORS.ident) OR (sym >= ORS.array)
  701. END ;
  702. IF sym = ORS.ident THEN
  703. qualident(obj);
  704. IF obj.class = ORB.Typ THEN
  705. IF (obj.type # NIL) & (obj.type.form # ORB.NoTyp) THEN type := obj.type END
  706. ELSE ORS.Mark("not a type or undefined")
  707. END
  708. ELSIF sym = ORS.array THEN ORS.Get(sym); ArrayType(type)
  709. ELSIF sym = ORS.record THEN
  710. ORS.Get(sym); RecordType(type); Check(ORS.end, "no END")
  711. ELSIF sym = ORS.pointer THEN
  712. ORS.Get(sym); Check(ORS.to, "no TO");
  713. NEW(type); type.form := ORB.Pointer; type.size := ORG.WordSize; type.base := ORB.intType;
  714. IF sym = ORS.ident THEN
  715. obj := ORB.thisObj();
  716. IF obj # NIL THEN
  717. IF (obj.class = ORB.Typ) & (obj.type.form IN {ORB.Record, ORB.NoTyp}) THEN
  718. CheckRecLevel(obj.lev); type.base := obj.type
  719. ELSIF obj.class = ORB.Mod THEN ORS.Mark("external base type not implemented")
  720. ELSE ORS.Mark("no valid base type")
  721. END
  722. ELSE CheckRecLevel(level); (*enter into list of forward references to be fixed in Declarations*)
  723. NEW(ptbase); ORS.CopyId(ptbase.name); ptbase.type := type; ptbase.next := pbsList; pbsList := ptbase
  724. END ;
  725. ORS.Get(sym)
  726. ELSE Type(type.base);
  727. IF type.base.form # ORB.Record THEN ORS.Mark("must point to record") END ;
  728. CheckRecLevel(level)
  729. END
  730. ELSIF sym = ORS.procedure THEN
  731. ORS.Get(sym); ORB.OpenScope;
  732. NEW(type); type.form := ORB.Proc; type.size := ORG.WordSize; dmy := 0;
  733. ProcedureType(type, dmy); type.dsc := ORB.topScope.next; ORB.CloseScope
  734. ELSE ORS.Mark("illegal type")
  735. END
  736. END Type0;
  737. PROCEDURE Declarations(VAR varsize: LONGINT);
  738. VAR obj, first: ORB.Object;
  739. x: ORG.Item; tp: ORB.Type; ptbase: PtrBase;
  740. expo: BOOLEAN; id: ORS.Ident;
  741. BEGIN (*sync*) pbsList := NIL;
  742. IF (sym < ORS.const) & (sym # ORS.end) THEN ORS.Mark("declaration?");
  743. REPEAT ORS.Get(sym) UNTIL (sym >= ORS.const) OR (sym = ORS.end)
  744. END ;
  745. IF sym = ORS.const THEN
  746. ORS.Get(sym);
  747. WHILE sym = ORS.ident DO
  748. ORS.CopyId(id); ORS.Get(sym); CheckExport(expo);
  749. IF sym = ORS.eql THEN ORS.Get(sym) ELSE ORS.Mark("= ?") END;
  750. expression(x);
  751. IF (x.type.form = ORB.String) & (x.b = 2) THEN ORG.StrToChar(x) END ;
  752. ORB.NewObj(obj, id, ORB.Const); obj.expo := expo;
  753. IF x.mode = ORB.Const THEN obj.val := x.a; obj.lev := x.b; obj.type := x.type
  754. ELSE ORS.Mark("expression not constant"); obj.type := ORB.intType
  755. END;
  756. Check(ORS.semicolon, "; missing")
  757. END
  758. END ;
  759. IF sym = ORS.type THEN
  760. ORS.Get(sym);
  761. WHILE sym = ORS.ident DO
  762. ORS.CopyId(id); ORS.Get(sym); CheckExport(expo);
  763. IF sym = ORS.eql THEN ORS.Get(sym) ELSE ORS.Mark("=?") END ;
  764. Type(tp);
  765. ORB.NewObj(obj, id, ORB.Typ); obj.type := tp; obj.expo := expo; obj.lev := level;
  766. IF tp.typobj = NIL THEN tp.typobj := obj END ;
  767. IF expo & (obj.type.form = ORB.Record) THEN obj.exno := exno; INC(exno) ELSE obj.exno := 0 END ;
  768. IF tp.form = ORB.Record THEN
  769. ptbase := pbsList; (*check whether this is base of a pointer type; search and fixup*)
  770. WHILE ptbase # NIL DO
  771. IF obj.name = ptbase.name THEN ptbase.type.base := obj.type END ;
  772. ptbase := ptbase.next
  773. END ;
  774. IF level = 0 THEN ORG.BuildTD(tp, dc) END (*type descriptor; len used as its address*)
  775. END ;
  776. Check(ORS.semicolon, "; missing")
  777. END
  778. END ;
  779. IF sym = ORS.var THEN
  780. ORS.Get(sym);
  781. WHILE sym = ORS.ident DO
  782. IdentList(ORB.Var, first); Type(tp);
  783. obj := first;
  784. WHILE obj # NIL DO
  785. obj.type := tp; obj.lev := level;
  786. IF tp.size > 1 THEN varsize := (varsize + 3) DIV 4 * 4 (*align*) END ;
  787. obj.val := varsize; varsize := varsize + obj.type.size;
  788. IF obj.expo THEN obj.exno := exno; INC(exno) END ;
  789. obj := obj.next
  790. END ;
  791. Check(ORS.semicolon, "; missing")
  792. END
  793. END ;
  794. varsize := (varsize + 3) DIV 4 * 4;
  795. ptbase := pbsList;
  796. WHILE ptbase # NIL DO
  797. IF ptbase.type.base.form = ORB.Int THEN ORS.Mark("undefined pointer base of") END ;
  798. ptbase := ptbase.next
  799. END ;
  800. IF (sym >= ORS.const) & (sym <= ORS.var) THEN ORS.Mark("declaration in bad order") END
  801. END Declarations;
  802. PROCEDURE ProcedureDecl;
  803. VAR proc: ORB.Object;
  804. type: ORB.Type;
  805. procid: ORS.Ident;
  806. x: ORG.Item;
  807. locblksize, parblksize, L: LONGINT;
  808. int: BOOLEAN;
  809. BEGIN (* ProcedureDecl *) int := FALSE; ORS.Get(sym);
  810. IF sym = ORS.times THEN ORS.Get(sym); int := TRUE END ;
  811. IF sym = ORS.ident THEN
  812. ORS.CopyId(procid); ORS.Get(sym);
  813. ORB.NewObj(proc, ORS.id, ORB.Const); parblksize := 4;
  814. NEW(type); type.form := ORB.Proc; type.size := ORG.WordSize; proc.type := type;
  815. CheckExport(proc.expo);
  816. IF proc.expo THEN proc.exno := exno; INC(exno) END ;
  817. ORB.OpenScope; INC(level); proc.val := -1; type.base := ORB.noType;
  818. ProcedureType(type, parblksize); (*formal parameter list*)
  819. Check(ORS.semicolon, "no ;"); locblksize := parblksize;
  820. Declarations(locblksize);
  821. proc.val := ORG.Here() * 4; proc.type.dsc := ORB.topScope.next;
  822. IF sym = ORS.procedure THEN
  823. L := 0; ORG.FJump(L);
  824. REPEAT ProcedureDecl; Check(ORS.semicolon, "no ;") UNTIL sym # ORS.procedure;
  825. ORG.FixLink(L); proc.val := ORG.Here() * 4; proc.type.dsc := ORB.topScope.next
  826. END ;
  827. ORG.Enter(parblksize, locblksize, int);
  828. IF sym = ORS.begin THEN ORS.Get(sym); StatSequence END ;
  829. IF sym = ORS.return THEN
  830. ORS.Get(sym); expression(x);
  831. IF type.base = ORB.noType THEN ORS.Mark("this is not a function")
  832. ELSIF ~CompTypes(type.base, x.type, FALSE) THEN ORS.Mark("wrong result type")
  833. END
  834. ELSIF type.base.form # ORB.NoTyp THEN
  835. ORS.Mark("function without result"); type.base := ORB.noType
  836. END ;
  837. ORG.Return(type.base.form, x, locblksize, int);
  838. ORB.CloseScope; DEC(level); Check(ORS.end, "no END");
  839. IF sym = ORS.ident THEN
  840. IF ORS.id # procid THEN ORS.Mark("no match") END ;
  841. ORS.Get(sym)
  842. ELSE ORS.Mark("no proc id")
  843. END
  844. END ;
  845. int := FALSE
  846. END ProcedureDecl;
  847. PROCEDURE Module;
  848. VAR key: LONGINT;
  849. obj: ORB.Object;
  850. impid, impid1: ORS.Ident;
  851. BEGIN Texts.WriteString(W, " compiling "); ORS.Get(sym);
  852. IF sym = ORS.module THEN
  853. ORS.Get(sym);
  854. IF sym = ORS.times THEN version := 0; Texts.Write(W, "*"); ORS.Get(sym) ELSE version := 1 END ;
  855. ORB.Init; ORB.OpenScope;
  856. IF sym = ORS.ident THEN
  857. ORS.CopyId(modid); ORS.Get(sym);
  858. Texts.WriteString(W, modid); Texts.Append(Oberon.Log, W.buf)
  859. ELSE ORS.Mark("identifier expected")
  860. END ;
  861. Check(ORS.semicolon, "no ;"); level := 0; dc := 0; exno := 1; key := 0;
  862. IF sym = ORS.import THEN
  863. ORS.Get(sym);
  864. WHILE sym = ORS.ident DO
  865. ORS.CopyId(impid); ORS.Get(sym);
  866. IF sym = ORS.becomes THEN
  867. ORS.Get(sym);
  868. IF sym = ORS.ident THEN ORS.CopyId(impid1); ORS.Get(sym)
  869. ELSE ORS.Mark("id expected")
  870. END
  871. ELSE impid1 := impid
  872. END ;
  873. ORB.Import(impid, impid1);
  874. IF sym = ORS.comma THEN ORS.Get(sym)
  875. ELSIF sym = ORS.ident THEN ORS.Mark("comma missing")
  876. END
  877. END ;
  878. Check(ORS.semicolon, "no ;")
  879. END ;
  880. obj := ORB.topScope.next;
  881. ORG.Open(version); Declarations(dc); ORG.SetDataSize((dc + 3) DIV 4 * 4);
  882. WHILE sym = ORS.procedure DO ProcedureDecl; Check(ORS.semicolon, "no ;") END ;
  883. ORG.Header;
  884. IF sym = ORS.begin THEN ORS.Get(sym); StatSequence END ;
  885. Check(ORS.end, "no END");
  886. IF sym = ORS.ident THEN
  887. IF ORS.id # modid THEN ORS.Mark("no match") END ;
  888. ORS.Get(sym)
  889. ELSE ORS.Mark("identifier missing")
  890. END ;
  891. IF sym # ORS.period THEN ORS.Mark("period missing") END ;
  892. IF (ORS.errcnt = 0) & (version # 0) THEN
  893. ORB.Export(modid, newSF, key);
  894. IF newSF THEN Texts.WriteString(W, " new symbol file") END
  895. END ;
  896. IF ORS.errcnt = 0 THEN
  897. ORG.Close(modid, key, exno);
  898. Texts.WriteInt(W, ORG.pc, 6); Texts.WriteInt(W, dc, 6); Texts.WriteHex(W, key)
  899. ELSE Texts.WriteLn(W); Texts.WriteString(W, "compilation FAILED")
  900. END ;
  901. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  902. ORB.CloseScope; pbsList := NIL
  903. ELSE ORS.Mark("must start with MODULE")
  904. END
  905. END Module;
  906. PROCEDURE Option(VAR S: Texts.Scanner);
  907. BEGIN newSF := FALSE;
  908. IF S.nextCh = "/" THEN
  909. Texts.Scan(S); Texts.Scan(S);
  910. IF (S.class = Texts.Name) & (S.s[0] = "s") THEN newSF := TRUE END
  911. END
  912. END Option;
  913. PROCEDURE Compile*;
  914. VAR beg, end, time: LONGINT;
  915. T: Texts.Text;
  916. S: Texts.Scanner;
  917. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  918. IF S.class = Texts.Char THEN
  919. IF S.c = "@" THEN
  920. Option(S); Oberon.GetSelection(T, beg, end, time);
  921. IF time >= 0 THEN ORS.Init(T, beg); Module END
  922. ELSIF S.c = "^" THEN
  923. Option(S); Oberon.GetSelection(T, beg, end, time);
  924. IF time >= 0 THEN
  925. Texts.OpenScanner(S, T, beg); Texts.Scan(S);
  926. IF S.class = Texts.Name THEN
  927. Texts.WriteString(W, S.s); NEW(T); Texts.Open(T, S.s);
  928. IF T.len > 0 THEN ORS.Init(T, 0); Module END
  929. END
  930. END
  931. END
  932. ELSE
  933. WHILE S.class = Texts.Name DO
  934. NEW(T); Texts.Open(T, S.s);
  935. IF T.len > 0 THEN Option(S); ORS.Init(T, 0); Module
  936. ELSE Texts.WriteString(W, S.s); Texts.WriteString(W, " not found");
  937. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  938. END ;
  939. IF (T.len # 0) & (ORS.errcnt = 0) THEN Texts.Scan(S) ELSE S.class := 0 END
  940. END
  941. END ;
  942. Oberon.Collect(0)
  943. END Compile;
  944. BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "OR Compiler 18.4.2016");
  945. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  946. NEW(dummy); dummy.class := ORB.Var; dummy.type := ORB.intType;
  947. expression := expression0; Type := Type0; FormalType := FormalType0
  948. END ORP.