O7ARMv7MP.Mod 45 KB

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