2
0

CPP.txt 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  1. MODULE Dev0CPP;
  2. (* THIS IS TEXT COPY OF CPP.odc *)
  3. (* DO NOT EDIT *)
  4. (**
  5. project = "BlackBox"
  6. organization = "www.oberon.ch"
  7. contributors = "Oberon microsystems"
  8. version = "System/Rsrc/AboutBB"
  9. copyright = "System/Rsrc/AboutBB"
  10. license = "Docu/BB-License"
  11. references = "ftp://ftp.inf.ethz.ch/pub/software/Oberon/OberonV4/Docu/OP2.Paper.ps"
  12. changes = ""
  13. issues = ""
  14. **)
  15. IMPORT
  16. DevCPM := Dev0CPM, DevCPT := Dev0CPT, DevCPB := Dev0CPB, DevCPS := Dev0CPS;
  17. CONST
  18. anchorVarPar = TRUE;
  19. (* numtyp values *)
  20. char = 1; integer = 2; real = 4; int64 = 5; real32 = 6; real64 = 7;
  21. (*symbol values*)
  22. null = 0; times = 1; slash = 2; div = 3; mod = 4;
  23. and = 5; plus = 6; minus = 7; or = 8; eql = 9;
  24. neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
  25. in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
  26. comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
  27. rbrace = 25; of = 26; then = 27; do = 28; to = 29;
  28. by = 30; not = 33;
  29. lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
  30. number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
  31. bar = 50; end = 51; else = 52; elsif = 53; until = 54;
  32. if = 55; case = 56; while = 57; repeat = 58; for = 59;
  33. loop = 60; with = 61; exit = 62; return = 63; array = 64;
  34. record = 65; pointer = 66; begin = 67; const = 68; type = 69;
  35. var = 70; out = 71; procedure = 72; close = 73; import = 74;
  36. module = 75; eof = 76;
  37. (* object modes *)
  38. Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7;
  39. SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13; Attr = 20;
  40. (* Structure forms *)
  41. Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6;
  42. Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12;
  43. Pointer = 13; ProcTyp = 14; Comp = 15;
  44. Char16 = 16; String16 = 17; Int64 = 18;
  45. intSet = {Int8..Int32, Int64}; charSet = {Char8, Char16};
  46. (* composite structure forms *)
  47. Basic = 1; Array = 2; DynArr = 3; Record = 4;
  48. (*function number*)
  49. haltfn = 0; newfn = 1; incfn = 13; sysnewfn = 30;
  50. (* nodes classes *)
  51. Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
  52. Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
  53. Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
  54. Nifelse = 20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
  55. Nreturn = 26; Nwith = 27; Ntrap = 28; Ncomp = 30;
  56. (* node subclasses *)
  57. super = 1;
  58. (* module visibility of objects *)
  59. internal = 0; external = 1; externalR = 2; inPar = 3; outPar = 4;
  60. (* procedure flags (conval.setval) *)
  61. hasBody = 1; isRedef = 2; slNeeded = 3; imVar = 4;
  62. (* attribute flags (attr.adr, struct.attribute, proc.conval.setval)*)
  63. newAttr = 16; absAttr = 17; limAttr = 18; empAttr = 19; extAttr = 20;
  64. (* case statement flags (conval.setval) *)
  65. useTable = 1; useTree = 2;
  66. (* sysflags *)
  67. nilBit = 1; inBit = 2; outBit = 4; newBit = 8; iidBit = 16; interface = 10; som = 20; jstr = -13;
  68. TYPE
  69. Elem = POINTER TO RECORD
  70. next: Elem;
  71. struct: DevCPT.Struct;
  72. obj, base: DevCPT.Object;
  73. pos: INTEGER;
  74. name: DevCPT.String
  75. END;
  76. VAR
  77. sym, level: BYTE;
  78. LoopLevel: SHORTINT;
  79. TDinit, lastTDinit: DevCPT.Node;
  80. userList: Elem;
  81. recList: Elem;
  82. hasReturn: BOOLEAN;
  83. numUsafeVarPar, numFuncVarPar: INTEGER;
  84. PROCEDURE^ Type(VAR typ: DevCPT.Struct; VAR name: DevCPT.String);
  85. PROCEDURE^ Expression(VAR x: DevCPT.Node);
  86. PROCEDURE^ Block(VAR procdec, statseq: DevCPT.Node);
  87. (* forward type handling *)
  88. PROCEDURE IncompleteType (typ: DevCPT.Struct): BOOLEAN;
  89. BEGIN
  90. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  91. RETURN (typ = DevCPT.undftyp) OR (typ.comp = Record) & (typ.BaseTyp = DevCPT.undftyp)
  92. END IncompleteType;
  93. PROCEDURE SetType (struct: DevCPT.Struct; obj: DevCPT.Object; typ: DevCPT.Struct; name: DevCPT.String);
  94. VAR u: Elem;
  95. BEGIN
  96. IF obj # NIL THEN obj.typ := typ ELSE struct.BaseTyp := typ END;
  97. IF name # NIL THEN
  98. NEW(u); u.struct := struct; u.obj := obj; u.pos := DevCPM.errpos; u.name := name;
  99. u.next := userList; userList := u
  100. END
  101. END SetType;
  102. PROCEDURE CheckAlloc (VAR typ: DevCPT.Struct; dynAllowed: BOOLEAN; pos: INTEGER);
  103. BEGIN
  104. typ.pvused := TRUE;
  105. IF typ.comp = DynArr THEN
  106. IF ~dynAllowed THEN DevCPM.Mark(88, pos); typ := DevCPT.undftyp END
  107. ELSIF typ.comp = Record THEN
  108. IF (typ.attribute = absAttr) OR (typ.attribute = limAttr) & (typ.mno # 0) THEN
  109. DevCPM.Mark(193, pos); typ := DevCPT.undftyp
  110. END
  111. END
  112. END CheckAlloc;
  113. PROCEDURE CheckRecursiveType (outer, inner: DevCPT.Struct; pos: INTEGER);
  114. VAR fld: DevCPT.Object;
  115. BEGIN
  116. IF outer = inner THEN DevCPM.Mark(58, pos)
  117. ELSIF inner.comp IN {Array, DynArr} THEN CheckRecursiveType(outer, inner.BaseTyp, pos)
  118. ELSIF inner.comp = Record THEN
  119. fld := inner.link;
  120. WHILE (fld # NIL) & (fld.mode = Fld) DO
  121. CheckRecursiveType(outer, fld.typ, pos);
  122. fld := fld.link
  123. END;
  124. IF inner.BaseTyp # NIL THEN CheckRecursiveType(outer, inner.BaseTyp, pos) END
  125. END
  126. END CheckRecursiveType;
  127. PROCEDURE FixType (struct: DevCPT.Struct; obj: DevCPT.Object; typ: DevCPT.Struct; pos: INTEGER);
  128. (* fix forward reference *)
  129. VAR t: DevCPT.Struct; f, bf: DevCPT.Object; i: SHORTINT;
  130. BEGIN
  131. IF obj # NIL THEN
  132. IF obj.mode = Var THEN (* variable type *)
  133. IF struct # NIL THEN (* receiver type *)
  134. IF (typ.form # Pointer) OR (typ.BaseTyp # struct) THEN DevCPM.Mark(180, pos) END;
  135. ELSE CheckAlloc(typ, obj.mnolev > level, pos) (* TRUE for parameters *)
  136. END
  137. ELSIF obj.mode = VarPar THEN (* varpar type *)
  138. IF struct # NIL THEN (* varpar receiver type *)
  139. IF typ # struct THEN DevCPM.Mark(180, pos) END
  140. END
  141. ELSIF obj.mode = Fld THEN (* field type *)
  142. CheckAlloc(typ, FALSE, pos);
  143. CheckRecursiveType(struct, typ, pos)
  144. ELSIF obj.mode = TProc THEN (* proc return type *)
  145. IF typ.form = Comp THEN typ := DevCPT.undftyp; DevCPM.Mark(54, pos) END
  146. ELSIF obj.mode = Typ THEN (* alias type *)
  147. IF typ.form IN {Byte..Set, Char16, Int64} THEN (* make alias structure *)
  148. t := DevCPT.NewStr(typ.form, Basic); i := t.ref;
  149. t^ := typ^; t.ref := i; t.strobj := obj; t.mno := 0;
  150. t.BaseTyp := typ; typ := t
  151. END;
  152. IF obj.vis # internal THEN
  153. IF typ.comp = Record THEN typ.exp := TRUE
  154. ELSIF typ.form = Pointer THEN typ.BaseTyp.exp := TRUE
  155. END
  156. END
  157. ELSE HALT(100)
  158. END;
  159. obj.typ := typ
  160. ELSE
  161. IF struct.form = Pointer THEN (* pointer base type *)
  162. IF typ.comp = Record THEN DevCPM.PropagateRecPtrSysFlag(typ.sysflag, struct.sysflag)
  163. ELSIF typ.comp IN {Array, DynArr} THEN DevCPM.PropagateArrPtrSysFlag(typ.sysflag, struct.sysflag)
  164. ELSE typ := DevCPT.undftyp; DevCPM.Mark(57, pos)
  165. END;
  166. struct.untagged := struct.sysflag > 0;
  167. IF (struct.strobj # NIL) & (struct.strobj.vis # internal) THEN typ.exp := TRUE END;
  168. ELSIF struct.comp = Array THEN (* array base type *)
  169. CheckAlloc(typ, FALSE, pos);
  170. CheckRecursiveType(struct, typ, pos)
  171. ELSIF struct.comp = DynArr THEN (* array base type *)
  172. CheckAlloc(typ, TRUE, pos);
  173. CheckRecursiveType(struct, typ, pos)
  174. ELSIF struct.comp = Record THEN (* record base type *)
  175. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  176. typ.pvused := TRUE; struct.extlev := SHORT(SHORT(typ.extlev + 1));
  177. DevCPM.PropagateRecordSysFlag(typ.sysflag, struct.sysflag);
  178. IF (typ.attribute = 0) OR (typ.attribute = limAttr) & (typ.mno # 0) THEN DevCPM.Mark(181, pos)
  179. ELSIF (struct.attribute = absAttr) & (typ.attribute # absAttr) THEN DevCPM.Mark(191, pos)
  180. ELSIF (typ.attribute = limAttr) & (struct.attribute # limAttr) THEN DevCPM.Mark(197, pos)
  181. END;
  182. f := struct.link;
  183. WHILE f # NIL DO (* check for field name conflicts *)
  184. DevCPT.FindField(f.name, typ, bf);
  185. IF bf # NIL THEN DevCPM.Mark(1, pos) END;
  186. f := f.link
  187. END;
  188. CheckRecursiveType(struct, typ, pos);
  189. struct.untagged := struct.sysflag > 0;
  190. ELSIF struct.form = ProcTyp THEN (* proc type return type *)
  191. IF typ.form = Comp THEN typ := DevCPT.undftyp; DevCPM.Mark(54, pos) END;
  192. ELSE HALT(100)
  193. END;
  194. struct.BaseTyp := typ
  195. END
  196. END FixType;
  197. PROCEDURE CheckForwardTypes;
  198. VAR u, next: Elem; progress: BOOLEAN;
  199. BEGIN
  200. u := userList; userList := NIL;
  201. WHILE u # NIL DO
  202. next := u.next; DevCPS.name := u.name^$; DevCPT.Find(DevCPS.name, u.base);
  203. IF u.base = NIL THEN DevCPM.Mark(0, u.pos)
  204. ELSIF u.base.mode # Typ THEN DevCPM.Mark(72, u.pos)
  205. ELSE u.next := userList; userList := u (* reinsert *)
  206. END;
  207. u := next
  208. END;
  209. REPEAT (* iteration for multy level alias *)
  210. u := userList; userList := NIL; progress := FALSE;
  211. WHILE u # NIL DO
  212. next := u.next;
  213. IF IncompleteType(u.base.typ) THEN
  214. u.next := userList; userList := u (* reinsert *)
  215. ELSE
  216. progress := TRUE;
  217. FixType(u.struct, u.obj, u.base.typ, u.pos)
  218. END;
  219. u := next
  220. END
  221. UNTIL (userList = NIL) OR ~progress;
  222. u := userList; (* remaining type relations are cyclic *)
  223. WHILE u # NIL DO
  224. IF (u.obj = NIL) OR (u.obj.mode = Typ) THEN DevCPM.Mark(58, u.pos) END;
  225. u := u.next
  226. END;
  227. END CheckForwardTypes;
  228. PROCEDURE CheckUnimpl (m: DevCPT.Object; typ: DevCPT.Struct; pos: INTEGER);
  229. VAR obj: DevCPT.Object;
  230. BEGIN
  231. IF m # NIL THEN
  232. IF (m.mode = TProc) & (absAttr IN m.conval.setval) THEN
  233. DevCPT.FindField(m.name^, typ, obj);
  234. IF (obj = NIL) OR (obj.mode # TProc) OR (absAttr IN obj.conval.setval) THEN
  235. DevCPM.Mark(192, pos);
  236. DevCPM.errorMes := DevCPM.errorMes + " " + m.name^ + " not implemented";
  237. IF typ.strobj # NIL THEN
  238. DevCPM.errorMes := DevCPM.errorMes+ " in " + typ.strobj.name^
  239. END
  240. END
  241. END;
  242. CheckUnimpl(m.left, typ, pos);
  243. CheckUnimpl(m.right, typ, pos)
  244. END
  245. END CheckUnimpl;
  246. PROCEDURE CheckRecords (rec: Elem);
  247. VAR b: DevCPT.Struct;
  248. BEGIN
  249. WHILE rec # NIL DO (* check for unimplemented methods in base type *)
  250. b := rec.struct.BaseTyp;
  251. WHILE (b # NIL) & (b # DevCPT.undftyp) DO
  252. CheckUnimpl(b.link, rec.struct, rec.pos);
  253. b := b.BaseTyp
  254. END;
  255. rec := rec.next
  256. END
  257. END CheckRecords;
  258. PROCEDURE err(n: SHORTINT);
  259. BEGIN DevCPM.err(n)
  260. END err;
  261. PROCEDURE CheckSym(s: SHORTINT);
  262. BEGIN
  263. IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
  264. END CheckSym;
  265. PROCEDURE qualident(VAR id: DevCPT.Object);
  266. VAR obj: DevCPT.Object; lev: BYTE;
  267. BEGIN (*sym = ident*)
  268. DevCPT.Find(DevCPS.name, obj); DevCPS.Get(sym);
  269. IF (sym = period) & (obj # NIL) & (obj.mode = Mod) THEN
  270. DevCPS.Get(sym);
  271. IF sym = ident THEN
  272. DevCPT.FindImport(DevCPS.name, obj, obj); DevCPS.Get(sym)
  273. ELSE err(ident); obj := NIL
  274. END
  275. END ;
  276. IF obj = NIL THEN err(0);
  277. obj := DevCPT.NewObj(); obj.mode := Var; obj.typ := DevCPT.undftyp; obj.adr := 0
  278. ELSE lev := obj.mnolev;
  279. IF (obj.mode IN {Var, VarPar}) & (lev # level) THEN
  280. obj.leaf := FALSE;
  281. IF lev > 0 THEN DevCPB.StaticLink(SHORT(SHORT(level-lev)), TRUE) END (* !!! *)
  282. END
  283. END ;
  284. id := obj
  285. END qualident;
  286. PROCEDURE ConstExpression(VAR x: DevCPT.Node);
  287. BEGIN Expression(x);
  288. IF x.class # Nconst THEN
  289. err(50); x := DevCPB.NewIntConst(1)
  290. END
  291. END ConstExpression;
  292. PROCEDURE CheckMark(obj: DevCPT.Object); (* !!! *)
  293. VAR n: INTEGER; mod: ARRAY 256 OF DevCPT.String;
  294. BEGIN DevCPS.Get(sym);
  295. IF (sym = times) OR (sym = minus) THEN
  296. IF (level > 0) OR ~(obj.mode IN {Var, Fld, TProc}) & (sym = minus) THEN err(41) END ;
  297. IF sym = times THEN obj.vis := external ELSE obj.vis := externalR END ;
  298. DevCPS.Get(sym)
  299. ELSE obj.vis := internal
  300. END;
  301. IF (obj.mode IN {TProc, LProc, XProc, CProc, Var, Typ, Con, Fld}) & (sym = lbrak) THEN
  302. DevCPS.Get(sym);
  303. IF (sym = number) & (DevCPS.numtyp = char) THEN
  304. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  305. END;
  306. IF sym = string THEN
  307. IF DevCPS.str^ # "" THEN obj.entry := DevCPS.str END;
  308. DevCPS.Get(sym); n := 0;
  309. IF (sym = comma) & (obj.mode IN {LProc, XProc, CProc, Var, Con}) THEN
  310. DevCPS.Get(sym);
  311. IF (sym = number) & (DevCPS.numtyp = char) THEN
  312. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  313. END;
  314. IF sym = string THEN
  315. obj.library := obj.entry; obj.entry := NIL;
  316. IF DevCPS.str^ # "" THEN obj.entry := DevCPS.str END;
  317. DevCPS.Get(sym);
  318. ELSE err(string)
  319. END
  320. END;
  321. WHILE sym = comma DO
  322. DevCPS.Get(sym);
  323. IF (sym = number) & (DevCPS.numtyp = char) THEN
  324. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  325. END;
  326. IF sym = string THEN
  327. IF n < LEN(mod) THEN mod[n] := DevCPS.str; INC(n)
  328. ELSE err(235)
  329. END;
  330. DevCPS.Get(sym)
  331. ELSE err(string)
  332. END
  333. END;
  334. IF n > 0 THEN
  335. NEW(obj.modifiers, n);
  336. WHILE n > 0 DO DEC(n); obj.modifiers[n] := mod[n] END
  337. END
  338. ELSE err(string)
  339. END;
  340. CheckSym(rbrak);
  341. IF DevCPM.options * {DevCPM.interface, DevCPM.java} = {} THEN err(225) END
  342. END
  343. END CheckMark;
  344. PROCEDURE CheckSysFlag (VAR sysflag: SHORTINT;
  345. GetSF: PROCEDURE(id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT));
  346. VAR x: DevCPT.Object; i: SHORTINT;
  347. BEGIN
  348. sysflag := 0;
  349. IF sym = lbrak THEN
  350. DevCPS.Get(sym);
  351. WHILE (sym = number) OR (sym = ident) OR (sym = string) DO
  352. IF sym = number THEN
  353. IF DevCPS.numtyp = integer THEN
  354. i := SHORT(DevCPS.intval); GetSF("", i, sysflag)
  355. ELSE err(225)
  356. END
  357. ELSIF sym = ident THEN
  358. DevCPT.Find(DevCPS.name, x);
  359. IF (x # NIL) & (x.mode = Con) & (x.typ.form IN {Int8, Int16, Int32}) THEN
  360. i := SHORT(x.conval.intval); GetSF("", i, sysflag)
  361. ELSE
  362. GetSF(DevCPS.name, 0, sysflag)
  363. END
  364. ELSE
  365. GetSF(DevCPS.str^, 0, sysflag)
  366. END;
  367. DevCPS.Get(sym);
  368. IF (sym = comma) OR (sym = plus) THEN DevCPS.Get(sym) END
  369. END;
  370. CheckSym(rbrak)
  371. END
  372. END CheckSysFlag;
  373. PROCEDURE Receiver(VAR mode, vis: BYTE; VAR name: DevCPT.Name; VAR typ, rec: DevCPT.Struct);
  374. VAR obj: DevCPT.Object; tname: DevCPT.String;
  375. BEGIN typ := DevCPT.undftyp; rec := NIL; vis := 0;
  376. IF sym = var THEN DevCPS.Get(sym); mode := VarPar;
  377. ELSIF sym = in THEN DevCPS.Get(sym); mode := VarPar; vis := inPar (* ??? *)
  378. ELSE mode := Var
  379. END ;
  380. name := DevCPS.name; CheckSym(ident); CheckSym(colon);
  381. IF sym # ident THEN err(ident) END;
  382. Type(typ, tname);
  383. IF tname = NIL THEN
  384. IF typ.form = Pointer THEN rec := typ.BaseTyp ELSE rec := typ END;
  385. IF ~((mode = Var) & (typ.form = Pointer) & (rec.comp = Record) OR
  386. (mode = VarPar) & (typ.comp = Record)) THEN err(70); rec := NIL END;
  387. IF (rec # NIL) & (rec.mno # level) THEN err(72); rec := NIL END
  388. ELSE err(0)
  389. END;
  390. CheckSym(rparen);
  391. IF rec = NIL THEN rec := DevCPT.NewStr(Comp, Record); rec.BaseTyp := NIL END
  392. END Receiver;
  393. PROCEDURE FormalParameters(
  394. VAR firstPar: DevCPT.Object; VAR resTyp: DevCPT.Struct; VAR name: DevCPT.String
  395. );
  396. VAR mode, vis: BYTE; sys: SHORTINT;
  397. par, first, last, res, newPar, iidPar: DevCPT.Object; typ: DevCPT.Struct;
  398. BEGIN
  399. first := NIL; last := firstPar;
  400. newPar := NIL; iidPar := NIL;
  401. IF (sym = ident) OR (sym = var) OR (sym = in) OR (sym = out) THEN
  402. LOOP
  403. sys := 0; vis := 0;
  404. IF sym = var THEN DevCPS.Get(sym); mode := VarPar
  405. ELSIF sym = in THEN DevCPS.Get(sym); mode := VarPar; vis := inPar
  406. ELSIF sym = out THEN DevCPS.Get(sym); mode := VarPar; vis := outPar
  407. ELSE mode := Var
  408. END ;
  409. IF mode = VarPar THEN CheckSysFlag(sys, DevCPM.GetVarParSysFlag) END;
  410. IF ODD(sys DIV inBit) THEN vis := inPar
  411. ELSIF ODD(sys DIV outBit) THEN vis := outPar
  412. END;
  413. IF ODD(sys DIV newBit) & (vis # outPar) THEN err(225)
  414. ELSIF ODD(sys DIV iidBit) & (vis # inPar) THEN err(225)
  415. END;
  416. LOOP
  417. IF sym = ident THEN
  418. DevCPT.Insert(DevCPS.name, par); DevCPS.Get(sym);
  419. par.mode := mode; par.link := NIL; par.vis := vis; par.sysflag := SHORT(sys);
  420. IF first = NIL THEN first := par END ;
  421. IF firstPar = NIL THEN firstPar := par ELSE last.link := par END ;
  422. last := par
  423. ELSE err(ident)
  424. END;
  425. IF sym = comma THEN DevCPS.Get(sym)
  426. ELSIF sym = ident THEN err(comma)
  427. ELSIF sym = var THEN err(comma); DevCPS.Get(sym)
  428. ELSE EXIT
  429. END
  430. END ;
  431. CheckSym(colon); Type(typ, name);
  432. IF mode # VarPar THEN CheckAlloc(typ, TRUE, DevCPM.errpos) END;
  433. IF (mode = VarPar) & (vis = inPar) & (typ.form # Undef) & (typ.form # Comp) & (typ.sysflag = 0) THEN err(177)
  434. END;
  435. (* typ.pbused is set when parameter type name is parsed *)
  436. WHILE first # NIL DO
  437. SetType (NIL, first, typ, name);
  438. IF DevCPM.com IN DevCPM.options THEN
  439. IF ODD(sys DIV newBit) THEN
  440. IF (newPar # NIL) OR (typ.form # Pointer) OR (typ.sysflag # interface) THEN err(168) END;
  441. newPar := first
  442. ELSIF ODD(sys DIV iidBit) THEN
  443. IF (iidPar # NIL) OR (typ # DevCPT.guidtyp) THEN err(168) END;
  444. iidPar := first
  445. END
  446. END;
  447. first := first.link
  448. END;
  449. IF sym = semicolon THEN DevCPS.Get(sym)
  450. ELSIF sym = ident THEN err(semicolon)
  451. ELSE EXIT
  452. END
  453. END
  454. END;
  455. CheckSym(rparen);
  456. IF (newPar = NIL) # (iidPar = NIL) THEN err(168) END;
  457. name := NIL;
  458. IF sym = colon THEN
  459. DevCPS.Get(sym);
  460. Type(resTyp, name);
  461. IF resTyp.form = Comp THEN resTyp := DevCPT.undftyp; err(54) END
  462. ELSE resTyp := DevCPT.notyp
  463. END
  464. END FormalParameters;
  465. PROCEDURE CheckOverwrite (proc, base: DevCPT.Object; rec: DevCPT.Struct);
  466. VAR o, bo: DevCPT.Object;
  467. BEGIN
  468. IF base # NIL THEN
  469. IF base.conval.setval * {absAttr, empAttr, extAttr} = {} THEN err(182) END;
  470. IF (proc.link.mode # base.link.mode) OR (proc.link.vis # base.link.vis)
  471. OR ~DevCPT.Extends(proc.link.typ, base.link.typ) THEN err(115) END;
  472. o := proc.link; bo := base.link;
  473. WHILE (o # NIL) & (bo # NIL) DO
  474. IF (bo.sysflag # 0) & (o.sysflag = 0) THEN (* propagate sysflags *)
  475. o.sysflag := bo.sysflag
  476. END;
  477. o := o.link; bo := bo.link
  478. END;
  479. DevCPB.CheckParameters(proc.link.link, base.link.link, FALSE);
  480. IF ~DevCPT.Extends(proc.typ, base.typ) THEN err(117) END;
  481. IF (base.vis # proc.vis) & ((proc.vis # internal) OR rec.exp) THEN err(183) END;
  482. INCL(proc.conval.setval, isRedef)
  483. END;
  484. END CheckOverwrite;
  485. PROCEDURE GetAttributes (proc, base: DevCPT.Object; owner: DevCPT.Struct); (* read method attributes *)
  486. VAR attr, battr: SET; o: DevCPT.Object;
  487. BEGIN
  488. attr := {};
  489. IF sym = comma THEN (* read attributes *)
  490. DevCPS.Get(sym);
  491. IF sym = ident THEN
  492. DevCPT.Find(DevCPS.name, o);
  493. IF (o # NIL) & (o.mode = SProc) & (o.adr = newfn) THEN
  494. IF ~(DevCPM.oberon IN DevCPM.options) THEN INCL(attr, newAttr) ELSE err(178) END;
  495. DevCPS.Get(sym);
  496. IF sym = comma THEN
  497. DevCPS.Get(sym);
  498. IF sym = ident THEN DevCPT.Find(DevCPS.name, o) ELSE o := NIL; err(ident) END
  499. ELSE o := NIL
  500. END
  501. END;
  502. IF o # NIL THEN
  503. IF (o.mode # Attr) OR (o.adr = limAttr) OR (DevCPM.oberon IN DevCPM.options) THEN err(178)
  504. ELSE INCL(attr, o.adr)
  505. END;
  506. DevCPS.Get(sym)
  507. END
  508. ELSE err(ident)
  509. END
  510. END;
  511. IF (base = NIL) & ~(newAttr IN attr) THEN err(185); INCL(attr, newAttr)
  512. ELSIF (base # NIL) & (newAttr IN attr) THEN err(186)
  513. END;
  514. IF absAttr IN attr THEN
  515. IF owner.attribute # absAttr THEN err(190) END;
  516. IF (proc.vis = internal) & owner.exp THEN err(179) END
  517. END;
  518. IF (owner.attribute = 0) OR (owner.attribute = limAttr) THEN
  519. IF (empAttr IN attr) & (newAttr IN attr) THEN err(187)
  520. (*
  521. ELSIF extAttr IN attr THEN err(188)
  522. *)
  523. END
  524. END;
  525. IF base # NIL THEN
  526. battr := base.conval.setval;
  527. IF empAttr IN battr THEN
  528. IF absAttr IN attr THEN err(189) END
  529. ELSIF ~(absAttr IN battr) THEN
  530. IF (absAttr IN attr) OR (empAttr IN attr) THEN err(189) END
  531. END
  532. END;
  533. IF empAttr IN attr THEN
  534. IF proc.typ # DevCPT.notyp THEN err(195)
  535. ELSE
  536. o := proc.link; WHILE (o # NIL) & (o.vis # outPar) DO o := o.link END;
  537. IF o # NIL THEN err(195) END
  538. END
  539. END;
  540. IF (owner.sysflag = interface) & ~(absAttr IN attr) THEN err(162) END;
  541. proc.conval.setval := attr
  542. END GetAttributes;
  543. PROCEDURE RecordType(VAR typ: DevCPT.Struct; attr: DevCPT.Object);
  544. VAR fld, first, last, base: DevCPT.Object; r: Elem; ftyp: DevCPT.Struct; name: DevCPT.String;
  545. BEGIN typ := DevCPT.NewStr(Comp, Record); typ.BaseTyp := NIL;
  546. CheckSysFlag(typ.sysflag, DevCPM.GetRecordSysFlag);
  547. IF attr # NIL THEN
  548. IF ~(DevCPM.oberon IN DevCPM.options) & (attr.adr # empAttr) THEN typ.attribute := SHORT(SHORT(attr.adr))
  549. ELSE err(178)
  550. END
  551. END;
  552. IF typ.sysflag = interface THEN
  553. IF (DevCPS.str # NIL) & (DevCPS.str[0] = "{") THEN typ.ext := DevCPS.str END;
  554. IF typ.attribute # absAttr THEN err(163) END;
  555. IF sym # lparen THEN err(160) END
  556. END;
  557. IF sym = lparen THEN
  558. DevCPS.Get(sym); (*record extension*)
  559. IF sym = ident THEN
  560. Type(ftyp, name);
  561. IF ftyp.form = Pointer THEN ftyp := ftyp.BaseTyp END;
  562. SetType(typ, NIL, ftyp, name);
  563. IF (ftyp.comp = Record) & (ftyp # DevCPT.anytyp) THEN
  564. ftyp.pvused := TRUE; typ.extlev := SHORT(SHORT(ftyp.extlev + 1));
  565. DevCPM.PropagateRecordSysFlag(ftyp.sysflag, typ.sysflag);
  566. IF (ftyp.attribute = 0) OR (ftyp.attribute = limAttr) & (ftyp.mno # 0) THEN err(181)
  567. ELSIF (typ.attribute = absAttr) & (ftyp.attribute # absAttr) & ~(DevCPM.java IN DevCPM.options) THEN err(191)
  568. ELSIF (ftyp.attribute = limAttr) & (typ.attribute # limAttr) THEN err(197)
  569. END
  570. ELSIF ftyp # DevCPT.undftyp THEN err(53)
  571. END
  572. ELSE err(ident)
  573. END ;
  574. IF typ.attribute # absAttr THEN (* save typ for unimplemented method check *)
  575. NEW(r); r.struct := typ; r.pos := DevCPM.errpos; r.next := recList; recList := r
  576. END;
  577. CheckSym(rparen)
  578. END;
  579. (*
  580. DevCPT.OpenScope(0, NIL);
  581. *)
  582. first := NIL; last := NIL;
  583. LOOP
  584. IF sym = ident THEN
  585. LOOP
  586. IF sym = ident THEN
  587. IF (typ.BaseTyp # NIL) & (typ.BaseTyp # DevCPT.undftyp) THEN
  588. DevCPT.FindBaseField(DevCPS.name, typ, fld);
  589. IF fld # NIL THEN err(1) END
  590. END ;
  591. DevCPT.InsertField(DevCPS.name, typ, fld);
  592. fld.mode := Fld; fld.link := NIL; fld.typ := DevCPT.undftyp;
  593. CheckMark(fld);
  594. IF first = NIL THEN first := fld END ;
  595. IF last = NIL THEN typ.link := fld ELSE last.link := fld END ;
  596. last := fld
  597. ELSE err(ident)
  598. END ;
  599. IF sym = comma THEN DevCPS.Get(sym)
  600. ELSIF sym = ident THEN err(comma)
  601. ELSE EXIT
  602. END
  603. END ;
  604. CheckSym(colon); Type(ftyp, name);
  605. CheckAlloc(ftyp, FALSE, DevCPM.errpos);
  606. WHILE first # NIL DO
  607. SetType(typ, first, ftyp, name); first := first.link
  608. END;
  609. IF typ.sysflag = interface THEN err(161) END
  610. END;
  611. IF sym = semicolon THEN DevCPS.Get(sym)
  612. ELSIF sym = ident THEN err(semicolon)
  613. ELSE EXIT
  614. END
  615. END;
  616. (*
  617. IF typ.link # NIL THEN ASSERT(typ.link = DevCPT.topScope.right) END;
  618. typ.link := DevCPT.topScope.right; DevCPT.CloseScope;
  619. *)
  620. typ.untagged := typ.sysflag > 0;
  621. DevCPB.Inittd(TDinit, lastTDinit, typ); CheckSym(end)
  622. END RecordType;
  623. PROCEDURE ArrayType(VAR typ: DevCPT.Struct);
  624. VAR x: DevCPT.Node; n: INTEGER; sysflag: SHORTINT; name: DevCPT.String;
  625. BEGIN CheckSysFlag(sysflag, DevCPM.GetArraySysFlag);
  626. IF sym = of THEN (*dynamic array*)
  627. typ := DevCPT.NewStr(Comp, DynArr); typ.mno := 0; typ.sysflag := sysflag;
  628. DevCPS.Get(sym); Type(typ.BaseTyp, name); SetType(typ, NIL, typ.BaseTyp, name);
  629. CheckAlloc(typ.BaseTyp, TRUE, DevCPM.errpos);
  630. IF typ.BaseTyp.comp = DynArr THEN typ.n := typ.BaseTyp.n + 1 ELSE typ.n := 0 END
  631. ELSE
  632. typ := DevCPT.NewStr(Comp, Array); typ.sysflag := sysflag; ConstExpression(x);
  633. IF x.typ.form IN {Int8, Int16, Int32} THEN n := x.conval.intval;
  634. IF (n <= 0) OR (n > DevCPM.MaxIndex) THEN err(63); n := 1 END
  635. ELSE err(42); n := 1
  636. END ;
  637. typ.n := n;
  638. IF sym = of THEN
  639. DevCPS.Get(sym); Type(typ.BaseTyp, name); SetType(typ, NIL, typ.BaseTyp, name);
  640. CheckAlloc(typ.BaseTyp, FALSE, DevCPM.errpos)
  641. ELSIF sym = comma THEN
  642. DevCPS.Get(sym);
  643. IF sym # of THEN ArrayType(typ.BaseTyp) END
  644. ELSE err(35)
  645. END
  646. END;
  647. typ.untagged := typ.sysflag > 0
  648. END ArrayType;
  649. PROCEDURE PointerType(VAR typ: DevCPT.Struct);
  650. VAR id: DevCPT.Object; name: DevCPT.String;
  651. BEGIN typ := DevCPT.NewStr(Pointer, Basic); CheckSysFlag(typ.sysflag, DevCPM.GetPointerSysFlag);
  652. CheckSym(to);
  653. Type(typ.BaseTyp, name);
  654. SetType(typ, NIL, typ.BaseTyp, name);
  655. IF (typ.BaseTyp # DevCPT.undftyp) & (typ.BaseTyp.comp = Basic) THEN
  656. typ.BaseTyp := DevCPT.undftyp; err(57)
  657. END;
  658. IF typ.BaseTyp.comp = Record THEN DevCPM.PropagateRecPtrSysFlag(typ.BaseTyp.sysflag, typ.sysflag)
  659. ELSIF typ.BaseTyp.comp IN {Array, DynArr} THEN DevCPM.PropagateArrPtrSysFlag(typ.BaseTyp.sysflag, typ.sysflag)
  660. END;
  661. typ.untagged := typ.sysflag > 0
  662. END PointerType;
  663. PROCEDURE Type (VAR typ: DevCPT.Struct; VAR name: DevCPT.String); (* name # NIL => forward reference *)
  664. VAR id: DevCPT.Object; tname: DevCPT.String;
  665. BEGIN
  666. typ := DevCPT.undftyp; name := NIL;
  667. IF sym < lparen THEN err(12);
  668. REPEAT DevCPS.Get(sym) UNTIL sym >= lparen
  669. END ;
  670. IF sym = ident THEN
  671. DevCPT.Find(DevCPS.name, id);
  672. IF (id = NIL) OR (id.mode = -1) OR (id.mode = Typ) & IncompleteType(id.typ) THEN (* forward type definition *)
  673. name := DevCPT.NewName(DevCPS.name); DevCPS.Get(sym);
  674. IF (id = NIL) & (sym = period) THEN (* missing module *)
  675. err(0); DevCPS.Get(sym); name := NIL;
  676. IF sym = ident THEN DevCPS.Get(sym) END
  677. ELSIF sym = record THEN (* wrong attribute *)
  678. err(178); DevCPS.Get(sym); name := NIL; RecordType(typ, NIL)
  679. END
  680. ELSE
  681. qualident(id);
  682. IF id.mode = Typ THEN
  683. IF ~(DevCPM.oberon IN DevCPM.options)
  684. & ((id.typ = DevCPT.lreal64typ) OR (id.typ = DevCPT.lint64typ) OR (id.typ = DevCPT.lchar16typ)) THEN
  685. err(198)
  686. END;
  687. typ := id.typ
  688. ELSIF id.mode = Attr THEN
  689. IF sym = record THEN
  690. DevCPS.Get(sym); RecordType(typ, id)
  691. ELSE err(12)
  692. END
  693. ELSE err(52)
  694. END
  695. END
  696. ELSIF sym = array THEN
  697. DevCPS.Get(sym); ArrayType(typ)
  698. ELSIF sym = record THEN
  699. DevCPS.Get(sym); RecordType(typ, NIL)
  700. ELSIF sym = pointer THEN
  701. DevCPS.Get(sym); PointerType(typ)
  702. ELSIF sym = procedure THEN
  703. DevCPS.Get(sym); typ := DevCPT.NewStr(ProcTyp, Basic);
  704. CheckSysFlag(typ.sysflag, DevCPM.GetProcTypSysFlag);
  705. typ.untagged := typ.sysflag > 0;
  706. IF sym = lparen THEN
  707. DevCPS.Get(sym); DevCPT.OpenScope(level, NIL);
  708. FormalParameters(typ.link, typ.BaseTyp, tname); SetType(typ, NIL, typ.BaseTyp, tname); DevCPT.CloseScope
  709. ELSE typ.BaseTyp := DevCPT.notyp; typ.link := NIL
  710. END
  711. ELSE err(12)
  712. END ;
  713. LOOP
  714. IF (sym >= semicolon) & (sym <= else) OR (sym = rparen) OR (sym = eof)
  715. OR (sym = number) OR (sym = comma) OR (sym = string) THEN EXIT END;
  716. err(15); IF sym = ident THEN EXIT END;
  717. DevCPS.Get(sym)
  718. END
  719. END Type;
  720. PROCEDURE ActualParameters(VAR aparlist: DevCPT.Node; fpar: DevCPT.Object; VAR pre, lastp: DevCPT.Node);
  721. VAR apar, last, newPar, iidPar, n: DevCPT.Node;
  722. BEGIN
  723. aparlist := NIL; last := NIL;
  724. IF sym # rparen THEN
  725. newPar := NIL; iidPar := NIL;
  726. LOOP Expression(apar);
  727. IF fpar # NIL THEN
  728. IF (apar.typ.form = Pointer) & (fpar.typ.form = Comp) THEN DevCPB.DeRef(apar) END;
  729. DevCPB.Param(apar, fpar);
  730. IF (fpar.mode = Var) OR (fpar.vis = inPar) THEN DevCPB.CheckBuffering(apar, NIL, fpar, pre, lastp) END;
  731. DevCPB.Link(aparlist, last, apar);
  732. IF ODD(fpar.sysflag DIV newBit) THEN newPar := apar
  733. ELSIF ODD(fpar.sysflag DIV iidBit) THEN iidPar := apar
  734. END;
  735. IF (newPar # NIL) & (iidPar # NIL) THEN DevCPB.CheckNewParamPair(newPar, iidPar) END;
  736. IF anchorVarPar & (fpar.mode = VarPar) & ~(DevCPM.java IN DevCPM.options)
  737. OR (DevCPM.allSysVal IN DevCPM.options) (* source output: avoid double evaluation *)
  738. & ((fpar.mode = VarPar) & (fpar.typ.comp = Record) & ~fpar.typ.untagged
  739. OR (fpar.typ.comp = DynArr) & ~fpar.typ.untagged) THEN
  740. n := apar;
  741. WHILE n.class IN {Nfield, Nindex, Nguard} DO n := n.left END;
  742. IF (n.class = Nderef) & (n.subcl = 0) THEN
  743. IF n.left.class = Nguard THEN n := n.left END;
  744. DevCPB.CheckVarParBuffering(n.left, pre, lastp)
  745. END
  746. END;
  747. fpar := fpar.link
  748. ELSE err(64)
  749. END;
  750. IF sym = comma THEN DevCPS.Get(sym)
  751. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  752. ELSE EXIT
  753. END
  754. END
  755. END;
  756. IF fpar # NIL THEN err(65) END
  757. END ActualParameters;
  758. PROCEDURE selector(VAR x: DevCPT.Node);
  759. VAR obj, proc, p, fpar: DevCPT.Object; y, apar, pre, lastp: DevCPT.Node; typ: DevCPT.Struct; name: DevCPT.Name;
  760. BEGIN
  761. LOOP
  762. IF sym = lbrak THEN DevCPS.Get(sym);
  763. LOOP
  764. IF (x.typ # NIL) & (x.typ.form = Pointer) THEN DevCPB.DeRef(x) END ;
  765. Expression(y); DevCPB.Index(x, y);
  766. IF sym = comma THEN DevCPS.Get(sym) ELSE EXIT END
  767. END ;
  768. CheckSym(rbrak)
  769. ELSIF sym = period THEN DevCPS.Get(sym);
  770. IF sym = ident THEN name := DevCPS.name; DevCPS.Get(sym);
  771. IF x.typ # NIL THEN
  772. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END ;
  773. IF x.typ.comp = Record THEN
  774. typ := x.typ; DevCPT.FindField(name, typ, obj); DevCPB.Field(x, obj);
  775. IF (obj # NIL) & (obj.mode = TProc) THEN
  776. IF sym = arrow THEN (* super call *) DevCPS.Get(sym);
  777. y := x.left;
  778. IF y.class = Nderef THEN y := y.left END ; (* y = record variable *)
  779. IF y.obj # NIL THEN
  780. proc := DevCPT.topScope; (* find innermost scope which owner is a TProc *)
  781. WHILE (proc.link # NIL) & (proc.link.mode # TProc) DO proc := proc.left END ;
  782. IF (proc.link = NIL) OR (proc.link.link # y.obj) (* OR (proc.link.name^ # name) *) THEN err(75)
  783. END ;
  784. typ := y.obj.typ;
  785. IF typ.form = Pointer THEN typ := typ.BaseTyp END ;
  786. DevCPT.FindBaseField(x.obj.name^, typ, p);
  787. IF p # NIL THEN
  788. x.subcl := super; x.typ := p.typ; (* correct result type *)
  789. IF p.conval.setval * {absAttr, empAttr} # {} THEN err(194) END;
  790. IF (p.vis = externalR) & (p.mnolev < 0) & (proc.link.name^ # name) THEN err(196) END;
  791. ELSE err(74)
  792. END
  793. ELSE err(75)
  794. END
  795. ELSE
  796. proc := obj;
  797. WHILE (proc.mnolev >= 0) & ~(newAttr IN proc.conval.setval) & (typ.BaseTyp # NIL) DO
  798. (* find base method *)
  799. typ := typ.BaseTyp; DevCPT.FindField(name, typ, proc);
  800. END;
  801. IF (proc.vis = externalR) & (proc.mnolev < 0) THEN err(196) END;
  802. END ;
  803. IF (obj.typ # DevCPT.notyp) & (sym # lparen) THEN err(lparen) END
  804. END
  805. ELSE err(53)
  806. END
  807. ELSE err(52)
  808. END
  809. ELSE err(ident)
  810. END
  811. ELSIF sym = arrow THEN DevCPS.Get(sym); DevCPB.DeRef(x)
  812. ELSIF sym = dollar THEN
  813. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END;
  814. DevCPS.Get(sym); DevCPB.StrDeref(x)
  815. ELSIF sym = lparen THEN
  816. IF (x.obj # NIL) & (x.obj.mode IN {XProc, LProc, CProc, TProc}) THEN typ := x.obj.typ
  817. ELSIF x.typ.form = ProcTyp THEN typ := x.typ.BaseTyp
  818. ELSIF x.class = Nproc THEN EXIT (* standard procedure *)
  819. ELSE typ := NIL
  820. END;
  821. IF typ # DevCPT.notyp THEN
  822. DevCPS.Get(sym);
  823. IF typ = NIL THEN (* type guard *)
  824. IF sym = ident THEN
  825. qualident(obj);
  826. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, TRUE)
  827. ELSE err(52)
  828. END
  829. ELSE err(ident)
  830. END
  831. ELSE (* function call *)
  832. pre := NIL; lastp := NIL;
  833. DevCPB.PrepCall(x, fpar);
  834. IF (x.obj # NIL) & (x.obj.mode = TProc) THEN DevCPB.CheckBuffering(x.left, NIL, x.obj.link, pre, lastp)
  835. END;
  836. ActualParameters(apar, fpar, pre, lastp);
  837. DevCPB.Call(x, apar, fpar);
  838. IF pre # NIL THEN DevCPB.Construct(Ncomp, pre, x); pre.typ := x.typ; x := pre END;
  839. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  840. END;
  841. CheckSym(rparen)
  842. ELSE EXIT
  843. END
  844. (*
  845. ELSIF (sym = lparen) & (x.class # Nproc) & (x.typ.form # ProcTyp) &
  846. ((x.obj = NIL) OR (x.obj.mode # TProc)) THEN
  847. DevCPS.Get(sym);
  848. IF sym = ident THEN
  849. qualident(obj);
  850. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, TRUE)
  851. ELSE err(52)
  852. END
  853. ELSE err(ident)
  854. END ;
  855. CheckSym(rparen)
  856. *)
  857. ELSE EXIT
  858. END
  859. END
  860. END selector;
  861. PROCEDURE StandProcCall(VAR x: DevCPT.Node);
  862. VAR y: DevCPT.Node; m: BYTE; n: SHORTINT;
  863. BEGIN m := SHORT(SHORT(x.obj.adr)); n := 0;
  864. IF sym = lparen THEN DevCPS.Get(sym);
  865. IF sym # rparen THEN
  866. LOOP
  867. IF n = 0 THEN Expression(x); DevCPB.StPar0(x, m); n := 1
  868. ELSIF n = 1 THEN Expression(y); DevCPB.StPar1(x, y, m); n := 2
  869. ELSE Expression(y); DevCPB.StParN(x, y, m, n); INC(n)
  870. END ;
  871. IF sym = comma THEN DevCPS.Get(sym)
  872. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  873. ELSE EXIT
  874. END
  875. END ;
  876. CheckSym(rparen)
  877. ELSE DevCPS.Get(sym)
  878. END ;
  879. DevCPB.StFct(x, m, n)
  880. ELSE err(lparen)
  881. END ;
  882. IF (level > 0) & ((m = newfn) OR (m = sysnewfn)) THEN DevCPT.topScope.link.leaf := FALSE END
  883. END StandProcCall;
  884. PROCEDURE Element(VAR x: DevCPT.Node);
  885. VAR y: DevCPT.Node;
  886. BEGIN Expression(x);
  887. IF sym = upto THEN
  888. DevCPS.Get(sym); Expression(y); DevCPB.SetRange(x, y)
  889. ELSE DevCPB.SetElem(x)
  890. END
  891. END Element;
  892. PROCEDURE Sets(VAR x: DevCPT.Node);
  893. VAR y: DevCPT.Node;
  894. BEGIN
  895. IF sym # rbrace THEN
  896. Element(x);
  897. LOOP
  898. IF sym = comma THEN DevCPS.Get(sym)
  899. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  900. ELSE EXIT
  901. END ;
  902. Element(y); DevCPB.Op(plus, x, y)
  903. END
  904. ELSE x := DevCPB.EmptySet()
  905. END ;
  906. CheckSym(rbrace)
  907. END Sets;
  908. PROCEDURE Factor(VAR x: DevCPT.Node);
  909. VAR fpar, id: DevCPT.Object; apar: DevCPT.Node;
  910. BEGIN
  911. IF sym < not THEN err(13);
  912. REPEAT DevCPS.Get(sym) UNTIL sym >= lparen
  913. END ;
  914. IF sym = ident THEN
  915. qualident(id); x := DevCPB.NewLeaf(id); selector(x);
  916. IF (x.class = Nproc) & (x.obj.mode = SProc) THEN StandProcCall(x) (* x may be NIL *)
  917. (*
  918. ELSIF sym = lparen THEN
  919. DevCPS.Get(sym); DevCPB.PrepCall(x, fpar);
  920. ActualParameters(apar, fpar);
  921. DevCPB.Call(x, apar, fpar);
  922. CheckSym(rparen);
  923. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  924. *)
  925. END
  926. ELSIF sym = number THEN
  927. CASE DevCPS.numtyp OF
  928. char:
  929. x := DevCPB.NewIntConst(DevCPS.intval); x.typ := DevCPT.char8typ;
  930. IF DevCPS.intval > 255 THEN x.typ := DevCPT.char16typ END
  931. | integer: x := DevCPB.NewIntConst(DevCPS.intval)
  932. | int64: x := DevCPB.NewLargeIntConst(DevCPS.intval, DevCPS.realval)
  933. | real: x := DevCPB.NewRealConst(DevCPS.realval, NIL)
  934. | real32: x := DevCPB.NewRealConst(DevCPS.realval, DevCPT.real32typ)
  935. | real64: x := DevCPB.NewRealConst(DevCPS.realval, DevCPT.real64typ)
  936. END ;
  937. DevCPS.Get(sym)
  938. ELSIF sym = string THEN
  939. x := DevCPB.NewString(DevCPS.str, DevCPS.lstr, DevCPS.intval);
  940. DevCPS.Get(sym)
  941. ELSIF sym = nil THEN
  942. x := DevCPB.Nil(); DevCPS.Get(sym)
  943. ELSIF sym = lparen THEN
  944. DevCPS.Get(sym); Expression(x); CheckSym(rparen)
  945. ELSIF sym = lbrak THEN
  946. DevCPS.Get(sym); err(lparen); Expression(x); CheckSym(rparen)
  947. ELSIF sym = lbrace THEN DevCPS.Get(sym); Sets(x)
  948. ELSIF sym = not THEN
  949. DevCPS.Get(sym); Factor(x); DevCPB.MOp(not, x)
  950. ELSE err(13); DevCPS.Get(sym); x := NIL
  951. END ;
  952. IF x = NIL THEN x := DevCPB.NewIntConst(1); x.typ := DevCPT.undftyp END
  953. END Factor;
  954. PROCEDURE Term(VAR x: DevCPT.Node);
  955. VAR y: DevCPT.Node; mulop: BYTE;
  956. BEGIN Factor(x);
  957. WHILE (times <= sym) & (sym <= and) DO
  958. mulop := sym; DevCPS.Get(sym);
  959. Factor(y); DevCPB.Op(mulop, x, y)
  960. END
  961. END Term;
  962. PROCEDURE SimpleExpression(VAR x: DevCPT.Node);
  963. VAR y: DevCPT.Node; addop: BYTE;
  964. BEGIN
  965. IF sym = minus THEN DevCPS.Get(sym); Term(x); DevCPB.MOp(minus, x)
  966. ELSIF sym = plus THEN DevCPS.Get(sym); Term(x); DevCPB.MOp(plus, x)
  967. ELSE Term(x)
  968. END ;
  969. WHILE (plus <= sym) & (sym <= or) DO
  970. addop := sym; DevCPS.Get(sym); Term(y);
  971. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END;
  972. IF (x.typ.comp IN {Array, DynArr}) & (x.typ.BaseTyp.form IN charSet) (* OR (x.typ.sysflag = jstr) *) THEN
  973. DevCPB.StrDeref(x)
  974. END;
  975. IF y.typ.form = Pointer THEN DevCPB.DeRef(y) END;
  976. IF (y.typ.comp IN {Array, DynArr}) & (y.typ.BaseTyp.form IN charSet) (* OR (y.typ.sysflag = jstr) *) THEN
  977. DevCPB.StrDeref(y)
  978. END;
  979. DevCPB.Op(addop, x, y)
  980. END
  981. END SimpleExpression;
  982. PROCEDURE Expression(VAR x: DevCPT.Node);
  983. VAR y, pre, last: DevCPT.Node; obj: DevCPT.Object; relation: BYTE;
  984. BEGIN SimpleExpression(x);
  985. IF (eql <= sym) & (sym <= geq) THEN
  986. relation := sym; DevCPS.Get(sym); SimpleExpression(y);
  987. pre := NIL; last := NIL;
  988. IF (x.typ.comp IN {Array, DynArr}) & (x.typ.BaseTyp.form IN charSet) THEN
  989. DevCPB.StrDeref(x)
  990. END;
  991. IF (y.typ.comp IN {Array, DynArr}) & (y.typ.BaseTyp.form IN charSet) THEN
  992. DevCPB.StrDeref(y)
  993. END;
  994. DevCPB.CheckBuffering(x, NIL, NIL, pre, last);
  995. DevCPB.CheckBuffering(y, NIL, NIL, pre, last);
  996. DevCPB.Op(relation, x, y);
  997. IF pre # NIL THEN DevCPB.Construct(Ncomp, pre, x); pre.typ := x.typ; x := pre END
  998. ELSIF sym = in THEN
  999. DevCPS.Get(sym); SimpleExpression(y); DevCPB.In(x, y)
  1000. ELSIF sym = is THEN
  1001. DevCPS.Get(sym);
  1002. IF sym = ident THEN
  1003. qualident(obj);
  1004. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, FALSE)
  1005. ELSE err(52)
  1006. END
  1007. ELSE err(ident)
  1008. END
  1009. END
  1010. END Expression;
  1011. PROCEDURE ProcedureDeclaration(VAR x: DevCPT.Node);
  1012. VAR proc, fwd: DevCPT.Object;
  1013. name: DevCPT.Name;
  1014. mode: BYTE;
  1015. forward: BOOLEAN;
  1016. sys: SHORTINT;
  1017. PROCEDURE GetCode;
  1018. VAR ext: DevCPT.ConstExt; i, n, c: INTEGER; s: ARRAY 256 OF SHORTCHAR;
  1019. BEGIN
  1020. n := 0;
  1021. IF sym = string THEN
  1022. NEW(ext, DevCPS.intval);
  1023. WHILE DevCPS.str[n] # 0X DO ext[n+1] := DevCPS.str[n]; INC(n) END ;
  1024. ext^[0] := SHORT(CHR(n)); DevCPS.Get(sym);
  1025. ELSE
  1026. LOOP
  1027. IF sym = number THEN c := DevCPS.intval; INC(n);
  1028. IF (c < 0) OR (c > 255) OR (n = 255) THEN
  1029. err(64); c := 1; n := 1
  1030. END ;
  1031. DevCPS.Get(sym); s[n] := SHORT(CHR(c))
  1032. END ;
  1033. IF sym = comma THEN DevCPS.Get(sym)
  1034. ELSIF sym = number THEN err(comma)
  1035. ELSE s[0] := SHORT(CHR(n)); EXIT
  1036. END
  1037. END;
  1038. NEW(ext, n + 1); i := 0;
  1039. WHILE i <= n DO ext[i] := s[i]; INC(i) END;
  1040. END;
  1041. proc.conval.ext := ext;
  1042. INCL(proc.conval.setval, hasBody)
  1043. END GetCode;
  1044. PROCEDURE GetParams;
  1045. VAR name: DevCPT.String;
  1046. BEGIN
  1047. proc.mode := mode; proc.typ := DevCPT.notyp;
  1048. proc.sysflag := SHORT(sys);
  1049. proc.conval.setval := {};
  1050. IF sym = lparen THEN
  1051. DevCPS.Get(sym); FormalParameters(proc.link, proc.typ, name);
  1052. IF name # NIL THEN err(0) END
  1053. END;
  1054. CheckForwardTypes; userList := NIL;
  1055. IF fwd # NIL THEN
  1056. DevCPB.CheckParameters(proc.link, fwd.link, TRUE);
  1057. IF ~DevCPT.EqualType(proc.typ, fwd.typ) THEN err(117) END ;
  1058. proc := fwd; DevCPT.topScope := proc.scope;
  1059. IF mode = IProc THEN proc.mode := IProc END
  1060. END
  1061. END GetParams;
  1062. PROCEDURE Body;
  1063. VAR procdec, statseq: DevCPT.Node; c: INTEGER;
  1064. BEGIN
  1065. c := DevCPM.errpos;
  1066. INCL(proc.conval.setval, hasBody);
  1067. CheckSym(semicolon); Block(procdec, statseq);
  1068. DevCPB.Enter(procdec, statseq, proc); x := procdec;
  1069. x.conval := DevCPT.NewConst(); x.conval.intval := c; x.conval.intval2 := DevCPM.startpos;
  1070. CheckSym(end);
  1071. IF sym = ident THEN
  1072. IF DevCPS.name # proc.name^ THEN err(4) END ;
  1073. DevCPS.Get(sym)
  1074. ELSE err(ident)
  1075. END
  1076. END Body;
  1077. PROCEDURE TProcDecl;
  1078. VAR baseProc, o, bo: DevCPT.Object;
  1079. objTyp, recTyp: DevCPT.Struct;
  1080. objMode, objVis: BYTE;
  1081. objName: DevCPT.Name;
  1082. pnode: DevCPT.Node;
  1083. fwdAttr: SET;
  1084. BEGIN
  1085. DevCPS.Get(sym); mode := TProc;
  1086. IF level > 0 THEN err(73) END;
  1087. Receiver(objMode, objVis, objName, objTyp, recTyp);
  1088. IF sym = ident THEN
  1089. name := DevCPS.name;
  1090. DevCPT.FindField(name, recTyp, fwd);
  1091. DevCPT.FindBaseField(name, recTyp, baseProc);
  1092. IF (baseProc # NIL) & (baseProc.mode # TProc) THEN baseProc := NIL; err(1) END ;
  1093. IF fwd = baseProc THEN fwd := NIL END ;
  1094. IF (fwd # NIL) & (fwd.mnolev # level) THEN fwd := NIL END ;
  1095. IF (fwd # NIL) & (fwd.mode = TProc) & (fwd.conval.setval * {hasBody, absAttr, empAttr} = {}) THEN
  1096. (* there exists a corresponding forward declaration *)
  1097. proc := DevCPT.NewObj(); proc.leaf := TRUE;
  1098. proc.mode := TProc; proc.conval := DevCPT.NewConst();
  1099. CheckMark(proc);
  1100. IF fwd.vis # proc.vis THEN err(118) END;
  1101. fwdAttr := fwd.conval.setval
  1102. ELSE
  1103. IF fwd # NIL THEN err(1); fwd := NIL END ;
  1104. DevCPT.InsertField(name, recTyp, proc);
  1105. proc.mode := TProc; proc.conval := DevCPT.NewConst();
  1106. CheckMark(proc);
  1107. IF recTyp.strobj # NIL THEN (* preserve declaration order *)
  1108. o := recTyp.strobj.link;
  1109. IF o = NIL THEN recTyp.strobj.link := proc
  1110. ELSE
  1111. WHILE o.nlink # NIL DO o := o.nlink END;
  1112. o.nlink := proc
  1113. END
  1114. END
  1115. END;
  1116. INC(level); DevCPT.OpenScope(level, proc);
  1117. DevCPT.Insert(objName, proc.link); proc.link.mode := objMode; proc.link.vis := objVis; proc.link.typ := objTyp;
  1118. ASSERT(DevCPT.topScope # NIL);
  1119. GetParams; (* may change proc := fwd !!! *)
  1120. ASSERT(DevCPT.topScope # NIL);
  1121. GetAttributes(proc, baseProc, recTyp);
  1122. IF (fwd # NIL) & (fwdAttr / proc.conval.setval * {absAttr, empAttr, extAttr} # {}) THEN err(184) END;
  1123. CheckOverwrite(proc, baseProc, recTyp);
  1124. IF ~forward THEN
  1125. IF empAttr IN proc.conval.setval THEN (* insert empty procedure *)
  1126. pnode := NIL; DevCPB.Enter(pnode, NIL, proc);
  1127. pnode.conval := DevCPT.NewConst();
  1128. pnode.conval.intval := DevCPM.errpos;
  1129. pnode.conval.intval2 := DevCPM.errpos;
  1130. x := pnode;
  1131. ELSIF DevCPM.noCode IN DevCPM.options THEN INCL(proc.conval.setval, hasBody)
  1132. ELSIF ~(absAttr IN proc.conval.setval) THEN Body
  1133. END;
  1134. proc.adr := 0
  1135. ELSE
  1136. proc.adr := DevCPM.errpos;
  1137. IF proc.conval.setval * {empAttr, absAttr} # {} THEN err(184) END
  1138. END;
  1139. DEC(level); DevCPT.CloseScope;
  1140. ELSE err(ident)
  1141. END;
  1142. END TProcDecl;
  1143. BEGIN proc := NIL; forward := FALSE; x := NIL; mode := LProc; sys := 0;
  1144. IF (sym # ident) & (sym # lparen) THEN
  1145. CheckSysFlag(sys, DevCPM.GetProcSysFlag);
  1146. IF sys # 0 THEN
  1147. IF ODD(sys DIV DevCPM.CProcFlag) THEN mode := CProc END
  1148. ELSE
  1149. IF sym = times THEN (* mode set later in DevCPB.CheckAssign *)
  1150. ELSIF sym = arrow THEN forward := TRUE
  1151. ELSE err(ident)
  1152. END;
  1153. DevCPS.Get(sym)
  1154. END
  1155. END ;
  1156. IF sym = lparen THEN TProcDecl
  1157. ELSIF sym = ident THEN DevCPT.Find(DevCPS.name, fwd);
  1158. name := DevCPS.name;
  1159. IF (fwd # NIL) & ((fwd.mnolev # level) OR (fwd.mode = SProc)) THEN fwd := NIL END ;
  1160. IF (fwd # NIL) & (fwd.mode IN {LProc, XProc}) & ~(hasBody IN fwd.conval.setval) THEN
  1161. (* there exists a corresponding forward declaration *)
  1162. proc := DevCPT.NewObj(); proc.leaf := TRUE;
  1163. proc.mode := mode; proc.conval := DevCPT.NewConst();
  1164. CheckMark(proc);
  1165. IF fwd.vis # proc.vis THEN err(118) END
  1166. ELSE
  1167. IF fwd # NIL THEN err(1); fwd := NIL END ;
  1168. DevCPT.Insert(name, proc);
  1169. proc.mode := mode; proc.conval := DevCPT.NewConst();
  1170. CheckMark(proc);
  1171. END ;
  1172. IF (proc.vis # internal) & (mode = LProc) THEN mode := XProc END ;
  1173. IF (mode # LProc) & (level > 0) THEN err(73) END ;
  1174. INC(level); DevCPT.OpenScope(level, proc);
  1175. proc.link := NIL; GetParams; (* may change proc := fwd !!! *)
  1176. IF mode = CProc THEN GetCode
  1177. ELSIF DevCPM.noCode IN DevCPM.options THEN INCL(proc.conval.setval, hasBody)
  1178. ELSIF ~forward THEN Body; proc.adr := 0
  1179. ELSE proc.adr := DevCPM.errpos
  1180. END ;
  1181. DEC(level); DevCPT.CloseScope
  1182. ELSE err(ident)
  1183. END
  1184. END ProcedureDeclaration;
  1185. PROCEDURE CaseLabelList(VAR lab, root: DevCPT.Node; LabelForm: SHORTINT; VAR min, max: INTEGER);
  1186. VAR x, y, lastlab: DevCPT.Node; i, f: SHORTINT; xval, yval: INTEGER;
  1187. PROCEDURE Insert(VAR n: DevCPT.Node); (* build binary tree of label ranges *) (* !!! *)
  1188. BEGIN
  1189. IF n = NIL THEN
  1190. IF x.hint # 1 THEN n := x END
  1191. ELSIF yval < n.conval.intval THEN Insert(n.left)
  1192. ELSIF xval > n.conval.intval2 THEN Insert(n.right)
  1193. ELSE err(63)
  1194. END
  1195. END Insert;
  1196. BEGIN lab := NIL; lastlab := NIL;
  1197. LOOP ConstExpression(x); f := x.typ.form;
  1198. IF f IN {Int8..Int32} + charSet THEN xval := x.conval.intval
  1199. ELSE err(61); xval := 1
  1200. END ;
  1201. IF (f IN {Int8..Int32}) # (LabelForm IN {Int8..Int32}) THEN err(60) END;
  1202. IF sym = upto THEN
  1203. DevCPS.Get(sym); ConstExpression(y); yval := y.conval.intval;
  1204. IF (y.typ.form IN {Int8..Int32}) # (LabelForm IN {Int8..Int32}) THEN err(60) END;
  1205. IF yval < xval THEN err(63); yval := xval END
  1206. ELSE yval := xval
  1207. END ;
  1208. x.conval.intval2 := yval;
  1209. IF xval < min THEN min := xval END;
  1210. IF yval > max THEN max := yval END;
  1211. IF lab = NIL THEN lab := x; Insert(root)
  1212. ELSIF yval < lab.conval.intval - 1 THEN x.link := lab; lab := x; Insert(root)
  1213. ELSIF yval = lab.conval.intval - 1 THEN x.hint := 1; Insert(root); lab.conval.intval := xval
  1214. ELSIF xval = lab.conval.intval2 + 1 THEN x.hint := 1; Insert(root); lab.conval.intval2 := yval
  1215. ELSE
  1216. y := lab;
  1217. WHILE (y.link # NIL) & (xval > y.link.conval.intval2 + 1) DO y := y.link END;
  1218. IF y.link = NIL THEN y.link := x; Insert(root)
  1219. ELSIF yval < y.link.conval.intval - 1 THEN x.link := y.link; y.link := x; Insert(root)
  1220. ELSIF yval = y.link.conval.intval - 1 THEN x.hint := 1; Insert(root); y.link.conval.intval := xval
  1221. ELSIF xval = y.link.conval.intval2 + 1 THEN x.hint := 1; Insert(root); y.link.conval.intval2 := yval
  1222. END
  1223. END;
  1224. IF sym = comma THEN DevCPS.Get(sym)
  1225. ELSIF (sym = number) OR (sym = ident) THEN err(comma)
  1226. ELSE EXIT
  1227. END
  1228. END
  1229. END CaseLabelList;
  1230. PROCEDURE StatSeq(VAR stat: DevCPT.Node);
  1231. VAR fpar, id, t, obj: DevCPT.Object; idtyp: DevCPT.Struct; e: BOOLEAN;
  1232. s, x, y, z, apar, last, lastif, pre, lastp: DevCPT.Node; pos, p: INTEGER; name: DevCPT.Name;
  1233. PROCEDURE CasePart(VAR x: DevCPT.Node);
  1234. VAR low, high: INTEGER; e: BOOLEAN; cases, lab, y, lastcase, root: DevCPT.Node;
  1235. BEGIN
  1236. Expression(x);
  1237. IF (x.class = Ntype) OR (x.class = Nproc) THEN err(126)
  1238. ELSIF x.typ.form = Int64 THEN err(260)
  1239. ELSIF ~(x.typ.form IN {Int8..Int32} + charSet) THEN err(125)
  1240. END ;
  1241. CheckSym(of); cases := NIL; lastcase := NIL; root := NIL;
  1242. low := MAX(INTEGER); high := MIN(INTEGER);
  1243. LOOP
  1244. IF sym < bar THEN
  1245. CaseLabelList(lab, root, x.typ.form, low, high);
  1246. CheckSym(colon); StatSeq(y);
  1247. DevCPB.Construct(Ncasedo, lab, y); DevCPB.Link(cases, lastcase, lab)
  1248. END ;
  1249. IF sym = bar THEN DevCPS.Get(sym) ELSE EXIT END
  1250. END;
  1251. e := sym = else;
  1252. IF e THEN DevCPS.Get(sym); StatSeq(y) ELSE y := NIL END ;
  1253. DevCPB.Construct(Ncaselse, cases, y); DevCPB.Construct(Ncase, x, cases);
  1254. cases.conval := DevCPT.NewConst();
  1255. cases.conval.intval := low; cases.conval.intval2 := high;
  1256. IF e THEN cases.conval.setval := {1} ELSE cases.conval.setval := {} END;
  1257. DevCPB.OptimizeCase(root); cases.link := root (* !!! *)
  1258. END CasePart;
  1259. PROCEDURE SetPos(x: DevCPT.Node);
  1260. BEGIN
  1261. x.conval := DevCPT.NewConst(); x.conval.intval := pos
  1262. END SetPos;
  1263. PROCEDURE CheckBool(VAR x: DevCPT.Node);
  1264. BEGIN
  1265. IF (x.class = Ntype) OR (x.class = Nproc) THEN err(126); x := DevCPB.NewBoolConst(FALSE)
  1266. ELSIF x.typ.form # Bool THEN err(120); x := DevCPB.NewBoolConst(FALSE)
  1267. END
  1268. END CheckBool;
  1269. BEGIN stat := NIL; last := NIL;
  1270. LOOP x := NIL;
  1271. IF sym < ident THEN err(14);
  1272. REPEAT DevCPS.Get(sym) UNTIL sym >= ident
  1273. END ;
  1274. pos := DevCPM.startpos;
  1275. IF sym = ident THEN
  1276. qualident(id); x := DevCPB.NewLeaf(id); selector(x);
  1277. IF sym = becomes THEN
  1278. DevCPS.Get(sym); Expression(y);
  1279. IF (y.typ.form = Pointer) & (x.typ.form = Comp) THEN DevCPB.DeRef(y) END;
  1280. pre := NIL; lastp := NIL;
  1281. DevCPB.CheckBuffering(y, x, NIL, pre, lastp);
  1282. DevCPB.Assign(x, y);
  1283. IF pre # NIL THEN SetPos(x); DevCPB.Construct(Ncomp, pre, x); x := pre END;
  1284. ELSIF sym = eql THEN
  1285. err(becomes); DevCPS.Get(sym); Expression(y); DevCPB.Assign(x, y)
  1286. ELSIF (x.class = Nproc) & (x.obj.mode = SProc) THEN
  1287. StandProcCall(x);
  1288. IF (x # NIL) & (x.typ # DevCPT.notyp) THEN err(55) END;
  1289. IF (x # NIL) & (x.class = Nifelse) THEN (* error pos for ASSERT *)
  1290. SetPos(x.left); SetPos(x.left.right)
  1291. END
  1292. ELSIF x.class = Ncall THEN err(55)
  1293. ELSE
  1294. pre := NIL; lastp := NIL;
  1295. DevCPB.PrepCall(x, fpar);
  1296. IF (x.obj # NIL) & (x.obj.mode = TProc) THEN DevCPB.CheckBuffering(x.left, NIL, x.obj.link, pre, lastp) END;
  1297. IF sym = lparen THEN
  1298. DevCPS.Get(sym); ActualParameters(apar, fpar, pre, lastp); CheckSym(rparen)
  1299. ELSE apar := NIL;
  1300. IF fpar # NIL THEN err(65) END
  1301. END ;
  1302. DevCPB.Call(x, apar, fpar);
  1303. IF x.typ # DevCPT.notyp THEN err(55) END;
  1304. IF pre # NIL THEN SetPos(x); DevCPB.Construct(Ncomp, pre, x); x := pre END;
  1305. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  1306. END
  1307. ELSIF sym = if THEN
  1308. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(x); CheckBool(x); CheckSym(then); StatSeq(y);
  1309. DevCPB.Construct(Nif, x, y); SetPos(x); lastif := x;
  1310. WHILE sym = elsif DO
  1311. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(y); CheckBool(y); CheckSym(then); StatSeq(z);
  1312. DevCPB.Construct(Nif, y, z); SetPos(y); DevCPB.Link(x, lastif, y)
  1313. END ;
  1314. pos := DevCPM.startpos;
  1315. IF sym = else THEN DevCPS.Get(sym); StatSeq(y) ELSE y := NIL END ;
  1316. DevCPB.Construct(Nifelse, x, y); CheckSym(end); DevCPB.OptIf(x);
  1317. ELSIF sym = case THEN
  1318. DevCPS.Get(sym); pos := DevCPM.startpos; CasePart(x); CheckSym(end)
  1319. ELSIF sym = while THEN
  1320. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(x); CheckBool(x); CheckSym(do); StatSeq(y);
  1321. DevCPB.Construct(Nwhile, x, y); CheckSym(end)
  1322. ELSIF sym = repeat THEN
  1323. DevCPS.Get(sym); StatSeq(x);
  1324. IF sym = until THEN DevCPS.Get(sym); pos := DevCPM.startpos; Expression(y); CheckBool(y)
  1325. ELSE err(43)
  1326. END ;
  1327. DevCPB.Construct(Nrepeat, x, y)
  1328. ELSIF sym = for THEN
  1329. DevCPS.Get(sym); pos := DevCPM.startpos;
  1330. IF sym = ident THEN qualident(id);
  1331. IF ~(id.typ.form IN intSet) THEN err(68) END ;
  1332. CheckSym(becomes); Expression(y);
  1333. x := DevCPB.NewLeaf(id); DevCPB.Assign(x, y); SetPos(x);
  1334. CheckSym(to); pos := DevCPM.startpos; Expression(y);
  1335. IF y.class # Nconst THEN
  1336. DevCPB.GetTempVar("@for", x.left.typ, t);
  1337. z := DevCPB.NewLeaf(t); DevCPB.Assign(z, y); SetPos(z); DevCPB.Link(stat, last, z);
  1338. y := DevCPB.NewLeaf(t)
  1339. ELSE
  1340. DevCPB.CheckAssign(x.left.typ, y)
  1341. END ;
  1342. DevCPB.Link(stat, last, x);
  1343. p := DevCPM.startpos;
  1344. IF sym = by THEN DevCPS.Get(sym); ConstExpression(z) ELSE z := DevCPB.NewIntConst(1) END ;
  1345. x := DevCPB.NewLeaf(id);
  1346. IF z.conval.intval > 0 THEN DevCPB.Op(leq, x, y)
  1347. ELSIF z.conval.intval < 0 THEN DevCPB.Op(geq, x, y)
  1348. ELSE err(63); DevCPB.Op(geq, x, y)
  1349. END ;
  1350. CheckSym(do); StatSeq(s);
  1351. y := DevCPB.NewLeaf(id); DevCPB.StPar1(y, z, incfn); pos := DevCPM.startpos; SetPos(y);
  1352. IF s = NIL THEN s := y
  1353. ELSE z := s;
  1354. WHILE z.link # NIL DO z := z.link END ;
  1355. z.link := y
  1356. END ;
  1357. CheckSym(end); DevCPB.Construct(Nwhile, x, s); pos := p
  1358. ELSE err(ident)
  1359. END
  1360. ELSIF sym = loop THEN
  1361. DevCPS.Get(sym); INC(LoopLevel); StatSeq(x); DEC(LoopLevel);
  1362. DevCPB.Construct(Nloop, x, NIL); CheckSym(end)
  1363. ELSIF sym = with THEN
  1364. DevCPS.Get(sym); idtyp := NIL; x := NIL;
  1365. LOOP
  1366. IF sym < bar THEN
  1367. pos := DevCPM.startpos;
  1368. IF sym = ident THEN
  1369. qualident(id); y := DevCPB.NewLeaf(id);
  1370. IF (id # NIL) & (id.typ.form = Pointer) & ((id.mode = VarPar) OR ~id.leaf) THEN
  1371. err(-302) (* warning 302 *)
  1372. END ;
  1373. CheckSym(colon);
  1374. IF sym = ident THEN qualident(t);
  1375. IF t.mode = Typ THEN
  1376. IF id # NIL THEN
  1377. idtyp := id.typ; DevCPB.TypTest(y, t, FALSE); id.typ := t.typ;
  1378. IF id.ptyp = NIL THEN id.ptyp := idtyp END
  1379. ELSE err(130)
  1380. END
  1381. ELSE err(52)
  1382. END
  1383. ELSE err(ident)
  1384. END
  1385. ELSE err(ident)
  1386. END ;
  1387. CheckSym(do); StatSeq(s); DevCPB.Construct(Nif, y, s); SetPos(y);
  1388. IF idtyp # NIL THEN
  1389. IF id.ptyp = idtyp THEN id.ptyp := NIL END;
  1390. id.typ := idtyp; idtyp := NIL
  1391. END ;
  1392. IF x = NIL THEN x := y; lastif := x ELSE DevCPB.Link(x, lastif, y) END
  1393. END;
  1394. IF sym = bar THEN DevCPS.Get(sym) ELSE EXIT END
  1395. END;
  1396. e := sym = else; pos := DevCPM.startpos;
  1397. IF e THEN DevCPS.Get(sym); StatSeq(s) ELSE s := NIL END ;
  1398. DevCPB.Construct(Nwith, x, s); CheckSym(end);
  1399. IF e THEN x.subcl := 1 END
  1400. ELSIF sym = exit THEN
  1401. DevCPS.Get(sym);
  1402. IF LoopLevel = 0 THEN err(46) END ;
  1403. DevCPB.Construct(Nexit, x, NIL)
  1404. ELSIF sym = return THEN DevCPS.Get(sym);
  1405. IF sym < semicolon THEN Expression(x) END ;
  1406. IF level > 0 THEN DevCPB.Return(x, DevCPT.topScope.link)
  1407. ELSE (* not standard Oberon *) DevCPB.Return(x, NIL)
  1408. END;
  1409. hasReturn := TRUE
  1410. END ;
  1411. IF x # NIL THEN SetPos(x); DevCPB.Link(stat, last, x) END ;
  1412. IF sym = semicolon THEN DevCPS.Get(sym)
  1413. ELSIF (sym <= ident) OR (if <= sym) & (sym <= return) THEN err(semicolon)
  1414. ELSE EXIT
  1415. END
  1416. END
  1417. END StatSeq;
  1418. PROCEDURE Block(VAR procdec, statseq: DevCPT.Node);
  1419. VAR typ: DevCPT.Struct;
  1420. obj, first, last, o: DevCPT.Object;
  1421. x, lastdec: DevCPT.Node;
  1422. i: SHORTINT;
  1423. rname: DevCPT.Name;
  1424. name: DevCPT.String;
  1425. rec: Elem;
  1426. BEGIN
  1427. IF ((sym < begin) OR (sym > var)) & (sym # procedure) & (sym # end) & (sym # close) THEN err(36) END;
  1428. first := NIL; last := NIL; userList := NIL; recList := NIL;
  1429. LOOP
  1430. IF sym = const THEN
  1431. DevCPS.Get(sym);
  1432. WHILE sym = ident DO
  1433. DevCPT.Insert(DevCPS.name, obj);
  1434. obj.mode := Con; CheckMark(obj);
  1435. obj.typ := DevCPT.int8typ; obj.mode := Var; (* Var to avoid recursive definition *)
  1436. IF sym = eql THEN
  1437. DevCPS.Get(sym); ConstExpression(x)
  1438. ELSIF sym = becomes THEN
  1439. err(eql); DevCPS.Get(sym); ConstExpression(x)
  1440. ELSE err(eql); x := DevCPB.NewIntConst(1)
  1441. END ;
  1442. obj.mode := Con; obj.typ := x.typ; obj.conval := x.conval; (* ConstDesc ist not copied *)
  1443. CheckSym(semicolon)
  1444. END
  1445. END ;
  1446. IF sym = type THEN
  1447. DevCPS.Get(sym);
  1448. WHILE sym = ident DO
  1449. DevCPT.Insert(DevCPS.name, obj); obj.mode := Typ; obj.typ := DevCPT.undftyp;
  1450. CheckMark(obj); obj.mode := -1;
  1451. IF sym # eql THEN err(eql) END;
  1452. IF (sym = eql) OR (sym = becomes) OR (sym = colon) THEN
  1453. DevCPS.Get(sym); Type(obj.typ, name); SetType(NIL, obj, obj.typ, name);
  1454. END;
  1455. obj.mode := Typ;
  1456. IF obj.typ.form IN {Byte..Set, Char16, Int64} THEN (* make alias structure *)
  1457. typ := DevCPT.NewStr(obj.typ.form, Basic); i := typ.ref;
  1458. typ^ := obj.typ^; typ.ref := i; typ.strobj := NIL; typ.mno := 0; typ.txtpos := DevCPM.errpos;
  1459. typ.BaseTyp := obj.typ; obj.typ := typ;
  1460. END;
  1461. IF obj.typ.strobj = NIL THEN obj.typ.strobj := obj END ;
  1462. IF obj.typ.form = Pointer THEN (* !!! *)
  1463. typ := obj.typ.BaseTyp;
  1464. IF (typ # NIL) & (typ.comp = Record) & (typ.strobj = NIL) THEN
  1465. (* pointer to unnamed record: name record as "pointerName^" *)
  1466. rname := obj.name^$; i := 0;
  1467. WHILE rname[i] # 0X DO INC(i) END;
  1468. rname[i] := "^"; rname[i+1] := 0X;
  1469. DevCPT.Insert(rname, o); o.mode := Typ; o.typ := typ; typ.strobj := o
  1470. END
  1471. END;
  1472. IF obj.vis # internal THEN
  1473. typ := obj.typ;
  1474. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  1475. IF typ.comp = Record THEN typ.exp := TRUE END
  1476. END;
  1477. CheckSym(semicolon)
  1478. END
  1479. END ;
  1480. IF sym = var THEN
  1481. DevCPS.Get(sym);
  1482. WHILE sym = ident DO
  1483. LOOP
  1484. IF sym = ident THEN
  1485. DevCPT.Insert(DevCPS.name, obj);
  1486. obj.mode := Var; obj.link := NIL; obj.leaf := obj.vis = internal; obj.typ := DevCPT.undftyp;
  1487. CheckMark(obj);
  1488. IF first = NIL THEN first := obj END ;
  1489. IF last = NIL THEN DevCPT.topScope.scope := obj ELSE last.link := obj END ;
  1490. last := obj
  1491. ELSE err(ident)
  1492. END ;
  1493. IF sym = comma THEN DevCPS.Get(sym)
  1494. ELSIF sym = ident THEN err(comma)
  1495. ELSE EXIT
  1496. END
  1497. END ;
  1498. CheckSym(colon); Type(typ, name);
  1499. CheckAlloc(typ, FALSE, DevCPM.errpos);
  1500. WHILE first # NIL DO SetType(NIL, first, typ, name); first := first.link END ;
  1501. CheckSym(semicolon)
  1502. END
  1503. END ;
  1504. IF (sym < const) OR (sym > var) THEN EXIT END ;
  1505. END ;
  1506. CheckForwardTypes;
  1507. userList := NIL; rec := recList; recList := NIL;
  1508. DevCPT.topScope.adr := DevCPM.errpos;
  1509. procdec := NIL; lastdec := NIL;
  1510. IF (sym # procedure) & (sym # begin) & (sym # end) & (sym # close) THEN err(37) END;
  1511. WHILE sym = procedure DO
  1512. DevCPS.Get(sym); ProcedureDeclaration(x);
  1513. IF x # NIL THEN
  1514. IF lastdec = NIL THEN procdec := x ELSE lastdec.link := x END ;
  1515. lastdec := x
  1516. END ;
  1517. CheckSym(semicolon)
  1518. END ;
  1519. IF DevCPM.noerr & ~(DevCPM.oberon IN DevCPM.options) THEN CheckRecords(rec) END;
  1520. hasReturn := FALSE;
  1521. IF (sym # begin) & (sym # end) & (sym # close) THEN err(38) END;
  1522. IF sym = begin THEN DevCPS.Get(sym); StatSeq(statseq)
  1523. ELSE statseq := NIL
  1524. END ;
  1525. IF (DevCPT.topScope.link # NIL) & (DevCPT.topScope.link.typ # DevCPT.notyp)
  1526. & ~hasReturn & (DevCPT.topScope.link.sysflag = 0) THEN err(133) END;
  1527. IF (level = 0) & (TDinit # NIL) THEN
  1528. lastTDinit.link := statseq; statseq := TDinit
  1529. END
  1530. END Block;
  1531. PROCEDURE Module*(VAR prog: DevCPT.Node);
  1532. VAR impName, aliasName: DevCPT.Name;
  1533. procdec, statseq: DevCPT.Node;
  1534. c, sf: INTEGER; done: BOOLEAN;
  1535. BEGIN
  1536. DevCPS.Init; LoopLevel := 0; level := 0; DevCPS.Get(sym);
  1537. IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END ;
  1538. IF sym = ident THEN
  1539. DevCPT.Open(DevCPS.name); DevCPS.Get(sym);
  1540. DevCPT.libName := "";
  1541. IF sym = lbrak THEN
  1542. INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
  1543. IF sym = eql THEN DevCPS.Get(sym)
  1544. ELSE INCL(DevCPM.options, DevCPM.noCode)
  1545. END;
  1546. IF sym = string THEN DevCPT.libName := DevCPS.str^$; DevCPS.Get(sym)
  1547. ELSE err(string)
  1548. END;
  1549. CheckSym(rbrak)
  1550. END;
  1551. CheckSym(semicolon);
  1552. IF sym = import THEN DevCPS.Get(sym);
  1553. LOOP
  1554. IF sym = ident THEN
  1555. aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
  1556. IF sym = becomes THEN DevCPS.Get(sym);
  1557. IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
  1558. END ;
  1559. DevCPT.Import(aliasName, impName, done)
  1560. ELSE err(ident)
  1561. END ;
  1562. IF sym = comma THEN DevCPS.Get(sym)
  1563. ELSIF sym = ident THEN err(comma)
  1564. ELSE EXIT
  1565. END
  1566. END ;
  1567. CheckSym(semicolon)
  1568. END ;
  1569. IF DevCPM.noerr THEN TDinit := NIL; lastTDinit := NIL; c := DevCPM.errpos;
  1570. Block(procdec, statseq); DevCPB.Enter(procdec, statseq, NIL); prog := procdec;
  1571. prog.conval := DevCPT.NewConst(); prog.conval.intval := c; prog.conval.intval2 := DevCPM.startpos;
  1572. IF sym = close THEN DevCPS.Get(sym); StatSeq(prog.link) END;
  1573. prog.conval.realval := DevCPM.startpos;
  1574. CheckSym(end);
  1575. IF sym = ident THEN
  1576. IF DevCPS.name # DevCPT.SelfName THEN err(4) END ;
  1577. DevCPS.Get(sym)
  1578. ELSE err(ident)
  1579. END;
  1580. IF sym # period THEN err(period) END
  1581. END
  1582. ELSE err(ident)
  1583. END ;
  1584. TDinit := NIL; lastTDinit := NIL;
  1585. DevCPS.str := NIL
  1586. END Module;
  1587. END Dev0CPP.