2
0

O7ARMv7MP.Mod 38 KB

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