ORP.Mod.txt 42 KB

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