FoxPrintout.Mod 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011
  1. MODULE FoxPrintout; (** AUTHOR "fof & fn"; PURPOSE "Oberon Compiler Module Output for SymbolFile, Pretty Printing and Testing"; *)
  2. (* (c) fof ETHZ 2009 *)
  3. IMPORT
  4. Scanner := FoxScanner, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal, Basic := FoxBasic, Streams, D:=Debugging, SYSTEM;
  5. CONST
  6. (* print modes *)
  7. Exported*=0; SymbolFile*=1; SourceCode*=2; All*=3;
  8. TYPE
  9. Printer*= OBJECT (SyntaxTree.Visitor)
  10. VAR
  11. w-: Basic.Writer; mode: LONGINT; singleStatement: BOOLEAN;
  12. currentScope: SyntaxTree.Scope; ws: Streams.StringWriter;
  13. info: BOOLEAN; case: LONGINT;
  14. useCase: BOOLEAN; (* TRUE to enable case conversion in "Identifier" *)
  15. alertCount, commentCount: LONGINT;
  16. PROCEDURE Small(CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
  17. VAR ch: CHAR; i: LONGINT;
  18. BEGIN
  19. i := 0;
  20. REPEAT
  21. ch := name[i];
  22. IF (ch >= 'A') & (ch <= 'Z') THEN
  23. ch := CHR(ORD(ch)-ORD('A')+ORD('a'));
  24. END;
  25. result[i] := ch; INC(i);
  26. UNTIL ch = 0X;
  27. END Small;
  28. PROCEDURE Big(CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
  29. VAR ch: CHAR; i: LONGINT;
  30. BEGIN
  31. i := 0;
  32. REPEAT
  33. ch := name[i];
  34. IF (ch >= 'a') & (ch <= 'z') THEN
  35. ch := CHR(ORD(ch)-ORD('a')+ORD('A'));
  36. END;
  37. result[i] := ch; INC(i);
  38. UNTIL ch = 0X;
  39. END Big;
  40. PROCEDURE Keyword(CONST a: ARRAY OF CHAR);
  41. VAR str: ARRAY 64 OF CHAR;
  42. BEGIN
  43. IF case= Scanner.Lowercase THEN Small(a,str) ELSE COPY(a,str) END;
  44. w.BeginKeyword;
  45. w.String(str);
  46. w.EndKeyword;
  47. END Keyword;
  48. PROCEDURE AlertString(CONST s: ARRAY OF CHAR);
  49. BEGIN
  50. w.BeginAlert; w.String(s); w.EndAlert;
  51. END AlertString;
  52. PROCEDURE Indent;
  53. BEGIN w.Ln;
  54. END Indent;
  55. PROCEDURE Identifier*(x: SyntaxTree.Identifier);
  56. VAR str: Scanner.IdentifierString;
  57. BEGIN
  58. Basic.GetString(x,str);
  59. IF useCase THEN
  60. IF case = Scanner.Lowercase THEN Small(str,str); ELSE Big(str,str); END;
  61. END;
  62. w.String(str);
  63. END Identifier;
  64. PROCEDURE QualifiedIdentifier*(x: SyntaxTree.QualifiedIdentifier);
  65. BEGIN
  66. IF x.prefix # SyntaxTree.invalidIdentifier THEN Identifier(x.prefix); w.String("."); END;
  67. Identifier(x.suffix);
  68. END QualifiedIdentifier;
  69. PROCEDURE Type*(x: SyntaxTree.Type);
  70. BEGIN
  71. IF x= NIL THEN
  72. AlertString("nil type");
  73. ELSE
  74. x.Accept(SELF);
  75. END;
  76. END Type;
  77. PROCEDURE VisitType(x: SyntaxTree.Type);
  78. BEGIN
  79. IF x = SyntaxTree.importType THEN w.String("importType")
  80. ELSIF x = SyntaxTree.typeDeclarationType THEN w.String("typeDeclarationType");
  81. ELSE
  82. AlertString("InvalidType");
  83. END;
  84. END VisitType;
  85. PROCEDURE VisitBasicType(x: SyntaxTree.BasicType);
  86. BEGIN
  87. IF x.typeDeclaration # NIL THEN
  88. Identifier(x.typeDeclaration.name);
  89. ELSE
  90. Identifier(x.name);
  91. END
  92. END VisitBasicType;
  93. PROCEDURE VisitBooleanType(x: SyntaxTree.BooleanType);
  94. BEGIN
  95. VisitBasicType(x);
  96. END VisitBooleanType;
  97. PROCEDURE VisitSetType(x: SyntaxTree.SetType);
  98. BEGIN
  99. VisitBasicType(x);
  100. END VisitSetType;
  101. PROCEDURE VisitSizeType(x: SyntaxTree.SizeType);
  102. BEGIN
  103. VisitBasicType(x);
  104. END VisitSizeType;
  105. PROCEDURE VisitCharacterType(x: SyntaxTree.CharacterType);
  106. BEGIN
  107. VisitBasicType(x);
  108. END VisitCharacterType;
  109. PROCEDURE VisitIntegerType(x: SyntaxTree.IntegerType);
  110. BEGIN
  111. VisitBasicType(x);
  112. END VisitIntegerType;
  113. PROCEDURE VisitFloatType(x: SyntaxTree.FloatType);
  114. BEGIN
  115. VisitBasicType(x);
  116. END VisitFloatType;
  117. PROCEDURE VisitComplexType(x: SyntaxTree.ComplexType);
  118. BEGIN
  119. VisitBasicType(x);
  120. END VisitComplexType;
  121. PROCEDURE VisitByteType(x: SyntaxTree.ByteType);
  122. BEGIN
  123. VisitBasicType(x);
  124. END VisitByteType;
  125. PROCEDURE VisitQualifiedType(x: SyntaxTree.QualifiedType);
  126. BEGIN
  127. IF x.resolved = SyntaxTree.invalidType THEN
  128. AlertString("(*unresolved*)");
  129. END;
  130. IF x.qualifiedIdentifier # NIL THEN
  131. (* Problem: how to distinguish betwteen type aliases, e.g. Status = LONGINT and actual use of LONGINT?
  132. This tries to use scope level: if the type is declared in the global scope, it should be a basic type use. *)
  133. IF x.resolved # NIL THEN
  134. useCase := (x.resolved IS SyntaxTree.BasicType) & (x.scope.Level() = 0);
  135. END;
  136. QualifiedIdentifier(x.qualifiedIdentifier);
  137. useCase := FALSE;
  138. ELSE
  139. AlertString("NIL (* missing qualified identifier *)");
  140. END;
  141. END VisitQualifiedType;
  142. PROCEDURE VisitStringType(x: SyntaxTree.StringType);
  143. BEGIN
  144. w.String("STRING"); w.String("(* len = "); w.Int(x.length,1); w.String(" *)");
  145. END VisitStringType;
  146. PROCEDURE VisitEnumerationType(x: SyntaxTree.EnumerationType);
  147. VAR e: SyntaxTree.Constant; first: BOOLEAN;
  148. BEGIN
  149. Keyword("ENUM ");
  150. IF x.enumerationBase # NIL THEN
  151. w.String("(");
  152. Type(x.enumerationBase);
  153. w.String(") ");
  154. END;
  155. e := x.enumerationScope.firstConstant; first := TRUE;
  156. WHILE (e # NIL) DO
  157. IF ~first THEN w.String(", ") ELSE first := FALSE END;
  158. VisitConstant(e);
  159. e := e.nextConstant;
  160. END;
  161. Keyword(" END");
  162. END VisitEnumerationType;
  163. PROCEDURE VisitRangeType(x: SyntaxTree.RangeType);
  164. BEGIN VisitBasicType(x);
  165. END VisitRangeType;
  166. PROCEDURE VisitArrayType(x: SyntaxTree.ArrayType);
  167. BEGIN
  168. Keyword("ARRAY " );
  169. IF x.length # NIL THEN Expression(x.length);
  170. w.String( " " ); END;
  171. Keyword("OF " );
  172. Type(x.arrayBase);
  173. END VisitArrayType;
  174. PROCEDURE VisitNilType(x: SyntaxTree.NilType);
  175. BEGIN
  176. w.String("NILTYPE");
  177. END VisitNilType;
  178. PROCEDURE VisitAddressType(x: SyntaxTree.AddressType);
  179. BEGIN
  180. w.String("ADDRESSTYPE");
  181. END VisitAddressType;
  182. PROCEDURE VisitObjectType(x: SyntaxTree.ObjectType);
  183. BEGIN
  184. VisitBasicType(x);
  185. END VisitObjectType;
  186. PROCEDURE VisitAnyType(x: SyntaxTree.AnyType);
  187. BEGIN
  188. VisitBasicType(x);
  189. END VisitAnyType;
  190. PROCEDURE VisitMathArrayType(x: SyntaxTree.MathArrayType);
  191. BEGIN
  192. Keyword("ARRAY " );
  193. IF x.form = SyntaxTree.Tensor THEN w.String("[?] ");
  194. ELSE
  195. w.String("[");
  196. IF x.length = NIL THEN
  197. w.String("*")
  198. ELSE
  199. Expression(x.length);
  200. END;
  201. WHILE(x.arrayBase # NIL) & (x.arrayBase IS SyntaxTree.MathArrayType) DO
  202. x := x.arrayBase(SyntaxTree.MathArrayType);
  203. w.String(", ");
  204. IF x.length = NIL THEN
  205. w.String("*")
  206. ELSE
  207. Expression(x.length);
  208. END;
  209. END;
  210. w.String("] ");
  211. END;
  212. IF x.arrayBase # NIL THEN
  213. Keyword("OF " );
  214. Type(x.arrayBase);
  215. END;
  216. END VisitMathArrayType;
  217. PROCEDURE PointerFlags(x: SyntaxTree.PointerType);
  218. VAR first: BOOLEAN;
  219. BEGIN
  220. first := TRUE;
  221. IF x.isUnsafe THEN Flag(Global.NameUnsafe,first) END;
  222. IF x.isRealtime THEN Flag(Global.NameRealtime,first) END;
  223. IF x.isDisposable THEN Flag(Global.NameDisposable,first) END;
  224. IF x.isPlain THEN Flag(Global.NamePlain,first) END;
  225. FlagEnd(first);
  226. END PointerFlags;
  227. PROCEDURE ObjectFlags ( rec: SyntaxTree.RecordType; x: SyntaxTree.PointerType);
  228. VAR first: BOOLEAN;
  229. BEGIN
  230. first := TRUE;
  231. IF x.isUnsafe THEN Flag(Global.NameUnsafe,first) END;
  232. IF x.isRealtime THEN Flag(Global.NameRealtime,first) END;
  233. IF x.isDisposable THEN Flag(Global.NameDisposable,first) END;
  234. IF x.isPlain THEN Flag(Global.NamePlain,first) END;
  235. IF rec.IsProtected() THEN Flag(Global.NameExclusive, first) END;
  236. FlagEnd(first);
  237. END ObjectFlags;
  238. PROCEDURE VisitPointerType(x: SyntaxTree.PointerType);
  239. VAR pointerBase: SyntaxTree.Type;
  240. BEGIN
  241. IF x.pointerBase = NIL THEN
  242. w.BeginAlert; Keyword("POINTER TO NIL"); w.EndAlert;
  243. ELSE
  244. pointerBase := x.pointerBase;
  245. IF x.isHidden THEN
  246. Type(x.pointerBase);
  247. ELSIF (pointerBase IS SyntaxTree.RecordType) & (pointerBase(SyntaxTree.RecordType).isObject) THEN
  248. VisitRecordType(pointerBase(SyntaxTree.RecordType))
  249. ELSE
  250. Keyword("POINTER "); PointerFlags(x); Keyword("TO " ); Type(x.pointerBase);
  251. END;
  252. END;
  253. END VisitPointerType;
  254. PROCEDURE VisitPortType(x: SyntaxTree.PortType);
  255. BEGIN
  256. Keyword("PORT");
  257. IF x.direction = SyntaxTree.OutPort THEN
  258. Keyword(" OUT")
  259. ELSE
  260. ASSERT(x.direction = SyntaxTree.InPort);
  261. Keyword(" IN");
  262. END;
  263. IF x.sizeExpression # NIL THEN
  264. w.String(" ("); Expression(x.sizeExpression); w.String(")");
  265. END;
  266. END VisitPortType;
  267. PROCEDURE VisitCellType(x: SyntaxTree.CellType);
  268. BEGIN
  269. IF x.isCellNet THEN
  270. Keyword("CELLNET ")
  271. ELSE
  272. Keyword("CELL ");
  273. END;
  274. Modifiers(x.modifiers);
  275. IF x.firstParameter # NIL THEN ParameterList(x.firstParameter) END;
  276. Scope(x.cellScope);
  277. IF (x.cellScope IS SyntaxTree.CellScope) & (x.cellScope(SyntaxTree.CellScope).bodyProcedure # NIL) THEN
  278. Body(x.cellScope(SyntaxTree.CellScope).bodyProcedure.procedureScope.body)
  279. END;
  280. Indent; Keyword("END ");
  281. IF (x.typeDeclaration # NIL) THEN
  282. Identifier(x.typeDeclaration.name);
  283. END;
  284. END VisitCellType;
  285. PROCEDURE VisitRecordType(x: SyntaxTree.RecordType);
  286. VAR prevScope: SyntaxTree.Scope;
  287. BEGIN
  288. IF x.isObject THEN
  289. Keyword("OBJECT ");
  290. IF x.pointerType # NIL THEN ObjectFlags(x, x.pointerType) END;
  291. IF info THEN
  292. BeginComment; w.String("ObjectType");
  293. IF x.HasArrayStructure() THEN
  294. w.String(" (array structure: ");
  295. VisitMathArrayType(x.arrayStructure);
  296. w.String(")");
  297. END;
  298. EndComment;
  299. END;
  300. IF (x.baseType # NIL) THEN
  301. w.String( "(" );
  302. IF (x.baseType IS SyntaxTree.RecordType) & (x.baseType(SyntaxTree.RecordType).pointerType # NIL) THEN
  303. Type(x.baseType(SyntaxTree.RecordType).pointerType)
  304. ELSE
  305. Type(x.baseType);
  306. END;
  307. w.String( ")" );
  308. END;
  309. Scope(x.recordScope);
  310. IF (x.recordScope.bodyProcedure # NIL) THEN
  311. Body(x.recordScope.bodyProcedure.procedureScope.body)
  312. END;
  313. Indent; Keyword("END ");
  314. IF (x.pointerType # NIL) & (x.pointerType.typeDeclaration # NIL) THEN
  315. Identifier(x.pointerType.typeDeclaration.name);
  316. END;
  317. ELSE
  318. Keyword("RECORD ");
  319. IF (x.baseType # NIL) THEN
  320. w.String( "(" );
  321. IF (x.baseType IS SyntaxTree.RecordType) & (x.baseType(SyntaxTree.RecordType).pointerType # NIL) THEN
  322. Type(x.baseType(SyntaxTree.RecordType).pointerType)
  323. ELSE
  324. Type(x.baseType);
  325. END;
  326. w.String( ")" );
  327. END;
  328. prevScope := currentScope;
  329. currentScope := x.recordScope;
  330. VariableList(x.recordScope.firstVariable);
  331. currentScope := prevScope;
  332. Indent; Keyword("END" );
  333. END;
  334. END VisitRecordType;
  335. PROCEDURE Flags((*flags: SET*));
  336. (*
  337. VAR first: BOOLEAN;
  338. PROCEDURE Flag(CONST name: ARRAY OF CHAR);
  339. BEGIN
  340. IF first THEN w.String("{"); first := FALSE; ELSE w.String(", ") END;
  341. w.String(name);
  342. END Flag;
  343. BEGIN
  344. first := TRUE;
  345. IF SyntaxTree.ActiveFlag IN flags THEN Flag("ACTIVE") END;
  346. IF SyntaxTree.ExclusiveFlag IN flags THEN Flag("EXCLUSIVE") END;
  347. IF SyntaxTree.SafeFlag IN flags THEN Flag("SAFE") END;
  348. IF SyntaxTree.RealtimeFlag IN flags THEN Flag("REALTIME") END;
  349. IF SyntaxTree.WinAPIFlag IN flags THEN Flag("WINAPI") END;
  350. IF SyntaxTree.CFlag IN flags THEN Flag("C") END;
  351. IF SyntaxTree.DelegateFlag IN flags THEN Flag("DELEGATE") END;
  352. IF SyntaxTree.UntracedFlag IN flags THEN Flag("UNTRACED") END;
  353. IF ~first THEN w.String("} ") END;
  354. IF info THEN
  355. BeginComment;
  356. IF SyntaxTree.AccessedFlag IN flags THEN Flag("ACCESSED") END;
  357. IF SyntaxTree.WrittenFlag IN flags THEN Flag("WRITTEN") END;
  358. IF SyntaxTree.UnreachableFlag IN flags THEN Flag("UNREACHABLE") END;
  359. IF ~first THEN w.String("}") END;
  360. EndComment;
  361. END;
  362. *)
  363. END Flags;
  364. PROCEDURE Flag(identifier: SyntaxTree.Identifier; VAR first: BOOLEAN);
  365. VAR name: SyntaxTree.IdentifierString;
  366. BEGIN
  367. IF first THEN w.String("{") ELSE w.String(", ") END;
  368. first := FALSE;
  369. Basic.GetString(identifier,name);
  370. w.String(name);
  371. END Flag;
  372. PROCEDURE FlagEnd(first: BOOLEAN);
  373. BEGIN
  374. IF ~first THEN w.String("} ") END;
  375. END FlagEnd;
  376. PROCEDURE Value(identifier: SyntaxTree.Identifier; value: LONGINT; VAR first: BOOLEAN);
  377. BEGIN
  378. Flag(identifier,first);
  379. w.String("("); w.Int(value,1); w.String(")");
  380. END Value;
  381. PROCEDURE VisitProcedureType(x: SyntaxTree.ProcedureType);
  382. VAR first: BOOLEAN;
  383. BEGIN
  384. Keyword("PROCEDURE " );
  385. first := TRUE;
  386. IF x.isDelegate THEN Flag(Global.NameDelegate,first) END;
  387. IF x.isInterrupt THEN Flag(Global.NameInterrupt,first) END;
  388. IF x.noPAF THEN Flag(Global.NameNoPAF,first) END;
  389. IF x.noReturn THEN Flag(Global.NameNoReturn,first) END;
  390. IF x.callingConvention = SyntaxTree.WinAPICallingConvention THEN
  391. Flag(Global.NameWinAPI,first)
  392. ELSIF x.callingConvention = SyntaxTree.CCallingConvention THEN
  393. Flag(Global.NameC,first)
  394. END;
  395. IF x.stackAlignment > 1 THEN Value(Global.NameStackAligned,x.stackAlignment,first) END;
  396. IF ~first THEN w.String("}") END;
  397. IF (x.modifiers # NIL) & info THEN
  398. BeginComment;
  399. Modifiers(x.modifiers);
  400. EndComment;
  401. END;
  402. (*
  403. CallingConvention(x.callingConvention);
  404. IF x.isDelegate THEN w.String("{DELEGATE}") END;
  405. *)
  406. IF (x.firstParameter # NIL) OR (x.returnType # NIL) THEN
  407. ParameterList(x.firstParameter)
  408. END;
  409. IF x.returnType # NIL THEN
  410. w.String( ":" );
  411. IF x.hasUntracedReturn THEN
  412. first := TRUE;
  413. Flag(Global.NameUntraced, first);
  414. FlagEnd(first);
  415. END;
  416. Type(x.returnType)
  417. END;
  418. IF info & (x.returnParameter # NIL) THEN
  419. BeginComment;
  420. VisitParameter(x.returnParameter);
  421. EndComment;
  422. END;
  423. END VisitProcedureType;
  424. (*** expressions ****)
  425. PROCEDURE ExpressionList(x: SyntaxTree.ExpressionList);
  426. VAR i: LONGINT; expression: SyntaxTree.Expression;
  427. BEGIN
  428. FOR i := 0 TO x.Length() - 1 DO
  429. expression := x.GetExpression( i ); Expression(expression);
  430. IF i < x.Length() - 1 THEN w.String( ", " ); END;
  431. END;
  432. END ExpressionList;
  433. PROCEDURE Expression*(x: SyntaxTree.Expression);
  434. BEGIN
  435. IF x = NIL THEN
  436. AlertString("nil expression");
  437. ELSE
  438. x.Accept(SELF);
  439. IF info & (x.resolved # NIL) & (x.resolved # x) THEN
  440. BeginComment; w.String("value = "); Expression(x.resolved); EndComment;
  441. END;
  442. END;
  443. w.Update;
  444. END Expression;
  445. PROCEDURE VisitExpression(x: SyntaxTree.Expression);
  446. BEGIN
  447. AlertString("InvalidExpression");
  448. END VisitExpression;
  449. PROCEDURE VisitSet(x: SyntaxTree.Set);
  450. BEGIN
  451. w.String( "{" ); ExpressionList(x.elements); w.String( "}" );
  452. END VisitSet;
  453. PROCEDURE VisitMathArrayExpression(x: SyntaxTree.MathArrayExpression);
  454. BEGIN
  455. w.String( "[" ); ExpressionList(x.elements); w.String( "]" );
  456. END VisitMathArrayExpression;
  457. PROCEDURE VisitUnaryExpression(x: SyntaxTree.UnaryExpression);
  458. VAR identifier: SyntaxTree.Identifier;
  459. BEGIN
  460. w.String(" ");
  461. IF x.operator = Scanner.Transpose THEN
  462. identifier := Global.GetIdentifier(x.operator,case);
  463. Expression(x.left);
  464. Identifier(identifier);
  465. ELSIF (x.operator = Scanner.Address) OR (x.operator = Scanner.Size) OR (x.operator = Scanner.Alias) THEN
  466. identifier := Global.GetIdentifier(x.operator,case);
  467. Identifier(identifier);
  468. Keyword(" OF ");
  469. Expression(x.left);
  470. ELSE
  471. identifier := Global.GetIdentifier(x.operator,case);
  472. Identifier(identifier);
  473. Expression(x.left);
  474. END;
  475. END VisitUnaryExpression;
  476. PROCEDURE VisitBinaryExpression(x: SyntaxTree.BinaryExpression);
  477. VAR identifier: SyntaxTree.Identifier;
  478. BEGIN
  479. w.String( "(" );
  480. Expression(x.left);
  481. identifier := Global.GetIdentifier(x.operator,case);
  482. w.String(" "); Identifier(identifier); w.String(" ");
  483. Expression(x.right);
  484. w.String(")");
  485. END VisitBinaryExpression;
  486. PROCEDURE VisitRangeExpression(x: SyntaxTree.RangeExpression);
  487. BEGIN
  488. IF x.missingFirst & x.missingLast & x.missingStep THEN
  489. (* open range expression *)
  490. (* the surrounding spaces prevent the asterisk from being next to a parenthesis,
  491. which could be confused with the beginning or end of a comment *)
  492. w.String(" * ")
  493. ELSE
  494. IF ~x.missingFirst THEN Expression(x.first) END;
  495. w.String(" .. ");
  496. IF ~x.missingLast THEN Expression(x.last) END;
  497. IF ~x.missingStep THEN
  498. Keyword(" BY ");
  499. Expression(x.step)
  500. END
  501. END;
  502. IF info THEN
  503. BeginComment;
  504. w.String("<RangeExpression:");
  505. ShortType(x.type);
  506. w.String(">");
  507. EndComment
  508. END
  509. END VisitRangeExpression;
  510. PROCEDURE VisitTensorRangeExpression(x: SyntaxTree.TensorRangeExpression);
  511. BEGIN
  512. w.String(" ? ");
  513. END VisitTensorRangeExpression;
  514. PROCEDURE VisitConversion(x: SyntaxTree.Conversion);
  515. BEGIN
  516. IF x.typeExpression # NIL THEN Expression(x.typeExpression); w.String("(");
  517. ELSIF info THEN BeginComment; ShortType(x.type); w.String("<-"); EndComment;
  518. END;
  519. Expression(x.expression);
  520. IF x.typeExpression # NIL THEN w.String(")") END;
  521. END VisitConversion;
  522. PROCEDURE VisitDesignator(x: SyntaxTree.Designator);
  523. BEGIN
  524. AlertString("InvalidDesignator");
  525. END VisitDesignator;
  526. PROCEDURE VisitIdentifierDesignator(x: SyntaxTree.IdentifierDesignator);
  527. BEGIN
  528. IF info THEN AlertString("(*<IdentifierDesignator>*)") END;
  529. Identifier(x.identifier)
  530. END VisitIdentifierDesignator;
  531. PROCEDURE VisitSelectorDesignator(x: SyntaxTree.SelectorDesignator);
  532. BEGIN
  533. Expression(x.left);
  534. w.String(".");
  535. IF info THEN AlertString("(*<SelectorDesignator>*)") END;
  536. Identifier(x.identifier);
  537. END VisitSelectorDesignator;
  538. PROCEDURE VisitBracketDesignator(x: SyntaxTree.BracketDesignator);
  539. BEGIN
  540. Expression(x.left);
  541. IF info THEN AlertString("(*<BracketDesignator>*)") END;
  542. w.String("["); ExpressionList(x.parameters); w.String("]");
  543. END VisitBracketDesignator;
  544. PROCEDURE VisitParameterDesignator(x: SyntaxTree.ParameterDesignator);
  545. BEGIN
  546. Expression(x.left);
  547. IF info THEN AlertString("(*<ParameterDesignator>*)") END;
  548. w.String("("); ExpressionList(x.parameters); w.String(")");
  549. END VisitParameterDesignator;
  550. PROCEDURE VisitIndexDesignator(x: SyntaxTree.IndexDesignator);
  551. BEGIN
  552. Expression(x.left);
  553. w.String("["); ExpressionList(x.parameters); w.String("]");
  554. IF info THEN
  555. BeginComment;
  556. w.String("<IndexDesignator:");
  557. ShortType(x.type);
  558. w.String(">");
  559. EndComment
  560. END;
  561. END VisitIndexDesignator;
  562. PROCEDURE VisitArrowDesignator(x: SyntaxTree.ArrowDesignator);
  563. BEGIN
  564. Expression(x.left);
  565. IF info THEN AlertString("(*<ArrowDesignator>*)") END;
  566. w.String( "^" );
  567. END VisitArrowDesignator;
  568. PROCEDURE ShortType(x: SyntaxTree.Type); (* for debug information, to prevent recursion *)
  569. BEGIN
  570. IF x = NIL THEN w.String("NIL TYPE")
  571. ELSIF x IS SyntaxTree.QualifiedType THEN Type(x)
  572. ELSIF x IS SyntaxTree.BasicType THEN Type(x)
  573. ELSIF x IS SyntaxTree.ProcedureType THEN w.String("ProcedureType:");ShortType(x(SyntaxTree.ProcedureType).returnType);
  574. ELSE w.String("(other)") END;
  575. END ShortType;
  576. PROCEDURE VisitSymbolDesignator(x: SyntaxTree.SymbolDesignator);
  577. BEGIN
  578. IF (x.left # NIL) & ~x.left.isHidden THEN
  579. Expression(x.left); w.String(".");
  580. END;
  581. IF x.symbol IS SyntaxTree.Operator THEN
  582. w.String('"'); Identifier(x.symbol.name); w.String('"');
  583. ELSE
  584. useCase :=
  585. (x.symbol IS SyntaxTree.Builtin)
  586. OR ((x.symbol IS SyntaxTree.TypeDeclaration) & (x.symbol(SyntaxTree.TypeDeclaration).declaredType IS SyntaxTree.BasicType))
  587. OR (x.symbol IS SyntaxTree.Module) & ((x.symbol.name = Global.systemName) OR (x.symbol.name = Global.SystemName));
  588. Identifier(x.symbol.name);
  589. useCase := FALSE;
  590. END;
  591. IF info THEN
  592. BeginComment;
  593. w.String("<SymbolDesignator:");
  594. ShortType(x.symbol.type);
  595. w.String(">");
  596. EndComment
  597. END;
  598. END VisitSymbolDesignator;
  599. PROCEDURE VisitSupercallDesignator(x: SyntaxTree.SupercallDesignator);
  600. BEGIN
  601. Expression(x.left);
  602. w.String( "^" );
  603. IF info THEN
  604. BeginComment;
  605. w.String("<SupercallDesignator:");
  606. ShortType(x.type);
  607. w.String(">");
  608. EndComment
  609. END;
  610. END VisitSupercallDesignator;
  611. PROCEDURE VisitSelfDesignator(x: SyntaxTree.SelfDesignator);
  612. BEGIN
  613. ASSERT(x.left = NIL);
  614. IF case = Scanner.Lowercase THEN w.String("self"); ELSE w.String("SELF"); END;
  615. IF info THEN
  616. BeginComment;
  617. w.String("<SelfDesignator:");
  618. ShortType(x.type);
  619. w.String(">");
  620. EndComment
  621. END;
  622. END VisitSelfDesignator;
  623. PROCEDURE VisitResultDesignator(x: SyntaxTree.ResultDesignator);
  624. BEGIN
  625. ASSERT(x.left = NIL);
  626. w.String("RESULT");
  627. IF info THEN
  628. BeginComment;
  629. w.String("<ResultDesignator:");
  630. ShortType(x.type);
  631. w.String(">");
  632. EndComment
  633. END;
  634. END VisitResultDesignator;
  635. PROCEDURE VisitDereferenceDesignator(x: SyntaxTree.DereferenceDesignator);
  636. BEGIN
  637. Expression(x.left);
  638. w.String( "^" );
  639. IF info THEN
  640. BeginComment;
  641. w.String("<DereferenceDesignator:");
  642. ShortType(x.type);
  643. w.String(">");
  644. EndComment
  645. END;
  646. END VisitDereferenceDesignator;
  647. PROCEDURE VisitTypeGuardDesignator(x: SyntaxTree.TypeGuardDesignator);
  648. BEGIN
  649. Expression(x.left);
  650. IF info THEN
  651. BeginComment;
  652. w.String("<TypeGuardDesignator:");
  653. ShortType(x.type);
  654. w.String(">");
  655. EndComment
  656. END;
  657. w.String("(");
  658. IF x.typeExpression # NIL THEN Expression(x.typeExpression) ELSE Type(x.type) END;
  659. w.String(")");
  660. END VisitTypeGuardDesignator;
  661. PROCEDURE VisitProcedureCallDesignator(x: SyntaxTree.ProcedureCallDesignator);
  662. BEGIN
  663. Expression(x.left);
  664. IF info THEN
  665. BeginComment;
  666. w.String("<ProcedureCallDesignator:");
  667. ShortType(x.type);
  668. w.String(">");
  669. EndComment
  670. END;
  671. w.String("("); ExpressionList(x.parameters); w.String(")");
  672. END VisitProcedureCallDesignator;
  673. PROCEDURE VisitStatementDesignator(x: SyntaxTree.StatementDesignator);
  674. BEGIN
  675. Indent; Keyword("STATEMENT-DESIGNATOR ");
  676. IF x.result # NIL THEN
  677. Keyword("RETURNS ");
  678. Expression(x.result)
  679. END;
  680. Indent; Statement(x.statement);
  681. END VisitStatementDesignator;
  682. PROCEDURE VisitBuiltinCallDesignator(x: SyntaxTree.BuiltinCallDesignator);
  683. BEGIN
  684. IF x.left # NIL THEN
  685. Expression(x.left);
  686. ELSE
  687. w.String("BUILTIN(");
  688. w.Int(x.id,1);
  689. w.String(")");
  690. END;
  691. IF info THEN
  692. BeginComment;
  693. w.String("<BuiltinCallDesignator:");
  694. ShortType(x.type);
  695. w.String(">");
  696. EndComment
  697. END;
  698. w.String("("); ExpressionList(x.parameters); w.String(")");
  699. END VisitBuiltinCallDesignator;
  700. PROCEDURE VisitValue(x: SyntaxTree.Value);
  701. BEGIN
  702. AlertString("InvalidValue");
  703. END VisitValue;
  704. PROCEDURE VisitBooleanValue(x: SyntaxTree.BooleanValue);
  705. BEGIN
  706. IF Scanner.Uppercase = case THEN
  707. IF x.value THEN w.String("TRUE" ) ELSE w.String( "FALSE" ) END
  708. ELSE
  709. IF x.value THEN w.String("true" ) ELSE w.String( "false" ) END
  710. END
  711. END VisitBooleanValue;
  712. PROCEDURE Hex(x: HUGEINT);
  713. VAR i: LONGINT; a: ARRAY 20 OF CHAR; y: HUGEINT;
  714. BEGIN
  715. i := 0;
  716. REPEAT
  717. y := x MOD 10H;
  718. IF y < 10 THEN a[i] := CHR(y+ORD('0'))
  719. ELSE a[i] := CHR(y-10+ORD('A'))
  720. END;
  721. x := x DIV 10H;
  722. INC(i);
  723. UNTIL (x=0) OR (i=16);
  724. IF y >=10 THEN w.Char("0") END;
  725. REPEAT DEC( i ); w.Char( a[i] ) UNTIL i = 0
  726. END Hex;
  727. PROCEDURE VisitIntegerValue(x: SyntaxTree.IntegerValue);
  728. PROCEDURE InBounds(val: HUGEINT; bits: LONGINT): BOOLEAN;
  729. VAR m: HUGEINT;
  730. BEGIN
  731. m := ASH(HUGEINT(1),bits-1);
  732. RETURN (val < m) & (-val <= m)
  733. END InBounds;
  734. BEGIN
  735. (*! use subtype for representation form ? *)
  736. IF x.hvalue = MIN(HUGEINT) THEN
  737. (* special case: display 8000000000000000H without leading minus sign
  738. to avoid double minus sign for unary expression -8000000000000000H
  739. *)
  740. w.Char("0"); w.Hex(x.hvalue,-16); w.Char("H");
  741. ELSIF InBounds(x.hvalue,32) THEN
  742. w.Int(SHORT(x.hvalue),1);
  743. ELSE
  744. Hex(x.hvalue); w.Char("H");
  745. END;
  746. END VisitIntegerValue;
  747. PROCEDURE VisitCharacterValue(x: SyntaxTree.CharacterValue);
  748. BEGIN
  749. Hex( ORD(x.value)); w.String( "X" );
  750. END VisitCharacterValue;
  751. PROCEDURE VisitSetValue(x: SyntaxTree.SetValue);
  752. VAR i: LONGINT;
  753. BEGIN
  754. w.String("{");
  755. i := 0;
  756. WHILE (i<MAX(SET)) & ~(i IN x.value) DO
  757. INC(i);
  758. END;
  759. IF i<MAX(SET) THEN
  760. w.Int(i,1);
  761. INC(i);
  762. WHILE i < MAX(SET) DO
  763. IF i IN x.value THEN w.String(","); w.Int(i,1); END;
  764. INC(i)
  765. END
  766. END;
  767. w.String("}");
  768. END VisitSetValue;
  769. PROCEDURE VisitMathArrayValue(x: SyntaxTree.MathArrayValue);
  770. BEGIN
  771. VisitMathArrayExpression(x.array);
  772. END VisitMathArrayValue;
  773. PROCEDURE FormatedFloat(value: LONGREAL; subtype: LONGINT);
  774. VAR string: ARRAY 128 OF CHAR; i: LONGINT;
  775. BEGIN
  776. IF subtype = Scanner.Real THEN
  777. ws.SetPos(0); ws.Float(value,11(*mantissa X.XXXXXXX *)+5(*exponent E+XXX *)); ws.Get(string);
  778. i := 0;
  779. WHILE(i<LEN(string)) & (string[i] # 0X) DO
  780. IF string[i] = "D" THEN string[i] := "E" END;
  781. INC(i);
  782. END;
  783. w.String(string);
  784. ELSIF subtype = Scanner.Longreal THEN
  785. ws.SetPos(0); ws.Float(value,20(*mantissa X.X..(16)..X *)+5(*exponent E+XXX *) ); ws.Get(string);
  786. i := 0;
  787. WHILE(i<LEN(string)) & (string[i] # 0X) DO
  788. IF string[i] = "E" THEN string[i] := "D" END;
  789. INC(i);
  790. END;
  791. w.String(string);
  792. ELSE
  793. w.Float(value,64)
  794. END;
  795. END FormatedFloat;
  796. PROCEDURE VisitRealValue(x: SyntaxTree.RealValue);
  797. BEGIN FormatedFloat(x.value, x.subtype)
  798. END VisitRealValue;
  799. PROCEDURE VisitComplexValue(x: SyntaxTree.ComplexValue);
  800. BEGIN
  801. IF (x.realValue = 0) & (x.imagValue = 1) THEN
  802. w.String("IMAG")
  803. ELSE
  804. w.String("(");
  805. FormatedFloat(x.realValue, x.subtype) ;
  806. w.String(" ");
  807. IF x.imagValue > 0 THEN w.String("+") END;
  808. FormatedFloat(x.imagValue, x.subtype);
  809. w.String("*IMAG)")
  810. END
  811. END VisitComplexValue;
  812. PROCEDURE VisitStringValue(x: SyntaxTree.StringValue);
  813. VAR i: LONGINT; ch: CHAR;
  814. BEGIN
  815. i := 0;
  816. w.Char('\');
  817. w.Char('"');
  818. WHILE (i < LEN( x.value )) & (x.value[i] # 0X) DO
  819. ch := x.value[i];
  820. IF ch = Scanner.CR THEN w.String("\n")
  821. ELSIF ch = Scanner.LF THEN (* ignore *)
  822. ELSIF ch = Scanner.TAB THEN w.String("\t")
  823. ELSIF ch = '\' THEN w.String("\\")
  824. ELSIF ch = '"' THEN w.String(\"""\); (* " *)
  825. ELSE w.Char(ch)
  826. END;
  827. INC( i );
  828. END;
  829. w.Char('"');
  830. w.Char('\');
  831. END VisitStringValue;
  832. PROCEDURE VisitNilValue(x: SyntaxTree.NilValue);
  833. BEGIN IF case = Scanner.Lowercase THEN w.String( "nil" ); ELSE w.String( "NIL" ); END; IF info THEN BeginComment; Type(x.type); EndComment; END;
  834. END VisitNilValue;
  835. PROCEDURE VisitEnumerationValue(x: SyntaxTree.EnumerationValue);
  836. BEGIN w.Int(x.value,1);
  837. END VisitEnumerationValue;
  838. (**** symbols ****)
  839. PROCEDURE Symbol*(x: SyntaxTree.Symbol);
  840. BEGIN
  841. IF x = NIL THEN
  842. AlertString("nil symbol");
  843. ELSE
  844. x.Accept(SELF);
  845. END
  846. END Symbol;
  847. PROCEDURE VisitSymbol(x: SyntaxTree.Symbol);
  848. BEGIN
  849. AlertString("InvalidSymbol");
  850. END VisitSymbol;
  851. PROCEDURE Visible(symbol: SyntaxTree.Symbol): BOOLEAN;
  852. BEGIN
  853. RETURN TRUE (* (SyntaxTree.Public * symbol.access # {}) OR (mode > SymbolFile) *)
  854. (* using only exported symbols does not work since there might be dependencies ... *)
  855. END Visible;
  856. PROCEDURE PrintSymbol(x: SyntaxTree.Symbol);
  857. VAR first: BOOLEAN;
  858. BEGIN
  859. IF x IS SyntaxTree.Operator THEN
  860. w.String('"');Identifier(x.name); w.String('"')
  861. ELSE
  862. Identifier(x.name)
  863. END;
  864. IF SyntaxTree.PublicWrite IN x.access THEN w.String( "*" )
  865. ELSIF SyntaxTree.PublicRead IN x.access THEN w.String( "-" )
  866. ELSIF x.access = {} THEN ASSERT(mode > SourceCode);
  867. IF info THEN BeginComment; w.String("<- hidden"); EndComment END;
  868. END;
  869. IF x.externalName # NIL THEN
  870. Keyword(" EXTERN " ); w.Char('"');
  871. w.String(x.externalName^); w.Char('"');
  872. END;
  873. IF info THEN
  874. BeginComment;
  875. w.String("access= {");
  876. Access(x.access);
  877. w.String("}");
  878. IF x.offsetInBits # MIN(LONGINT) THEN
  879. w.String("@"); w.Hex(x.offsetInBits,1);
  880. END;
  881. IF x.type # NIL THEN
  882. IF x.type.resolved.alignmentInBits >=0 THEN
  883. w.String("@@"); w.Hex(x.type.resolved.alignmentInBits,1);
  884. END;
  885. END;
  886. EndComment;
  887. END;
  888. END PrintSymbol;
  889. PROCEDURE VisitTypeDeclaration(x: SyntaxTree.TypeDeclaration);
  890. BEGIN
  891. IF Visible(x) THEN
  892. IF (x.access # SyntaxTree.Hidden) OR (mode > SourceCode) THEN
  893. Comments(x.comment,x,FALSE);
  894. PrintSymbol(x);
  895. w.String(" = ");
  896. IF x.access # SyntaxTree.Hidden THEN
  897. Type(x.declaredType);
  898. ELSE ShortType(x.declaredType)
  899. END;
  900. Comments(x.comment,x,TRUE);
  901. END;
  902. END;
  903. END VisitTypeDeclaration;
  904. PROCEDURE TypeDeclarationList(x: SyntaxTree.TypeDeclaration);
  905. BEGIN
  906. Indent;
  907. Keyword("TYPE " );
  908. w.IncIndent;
  909. WHILE(x # NIL) DO
  910. Indent;
  911. Symbol(x);
  912. w.String( "; " );
  913. x := x.nextTypeDeclaration;
  914. IF x # NIL THEN w.Ln END;
  915. END;
  916. w.DecIndent;
  917. END TypeDeclarationList;
  918. PROCEDURE VisitConstant(x: SyntaxTree.Constant);
  919. BEGIN
  920. IF Visible(x) THEN
  921. IF (mode > SourceCode) OR (x.access # SyntaxTree.Hidden) THEN
  922. Comments(x.comment,x,FALSE);
  923. PrintSymbol(x);
  924. IF x.value # NIL THEN
  925. w.String( " = " ); Expression(x.value);
  926. END;
  927. IF info THEN BeginComment; ShortType(x.type); EndComment; END;
  928. IF info & (x.value.resolved = NIL) THEN AlertString("(*NOT A CONSTANT*)") END;
  929. Comments(x.comment,x,TRUE);
  930. END;
  931. END;
  932. END VisitConstant;
  933. PROCEDURE ConstantList(x: SyntaxTree.Constant);
  934. BEGIN
  935. Indent; Keyword("CONST " );
  936. w.IncIndent;
  937. WHILE(x # NIL) DO
  938. IF (x.access # SyntaxTree.Hidden) OR (mode > SourceCode) THEN
  939. Indent;
  940. Symbol(x);
  941. w.String( "; " );
  942. END;
  943. x := x.nextConstant;
  944. END;
  945. w.DecIndent;
  946. END ConstantList;
  947. PROCEDURE VisitVariable(x: SyntaxTree.Variable);
  948. VAR first: BOOLEAN;
  949. BEGIN
  950. IF Visible(x) THEN
  951. IF (x.access # SyntaxTree.Hidden) THEN
  952. Comments(x.comment,x,FALSE);
  953. PrintSymbol(x);
  954. IF x.modifiers # NIL THEN w.String(" "); Modifiers(x.modifiers); END;
  955. IF x.initializer # NIL THEN
  956. w.String( " := " ); Expression (x.initializer);
  957. END;
  958. w.String( ": " );
  959. Type(x.type);
  960. Comments(x.comment,x,TRUE);
  961. ELSIF mode>SourceCode THEN
  962. Comments(x.comment,x,FALSE);
  963. PrintSymbol(x);
  964. IF x.initializer # NIL THEN
  965. w.String( " := " ); Expression (x.initializer);
  966. END;
  967. Comments(x.comment,x,TRUE);
  968. END
  969. END;
  970. END VisitVariable;
  971. PROCEDURE VariableList(x: SyntaxTree.Variable);
  972. VAR next: SyntaxTree.Variable;
  973. PROCEDURE Flags(x: SyntaxTree.Variable);
  974. VAR first: BOOLEAN;
  975. BEGIN
  976. first := TRUE;
  977. IF x.fixed THEN
  978. Value(Global.NameFixed,x.alignment,first)
  979. ELSIF x.alignment > 1 THEN
  980. Value(Global.NameAligned,x.alignment,first)
  981. ELSIF x.fictive THEN
  982. Value(Global.NameFictive, x.fictiveOffset, first);
  983. END;
  984. IF x.untraced THEN
  985. Flag(Global.NameUntraced,first)
  986. END;
  987. FlagEnd(first);
  988. END Flags;
  989. BEGIN
  990. w.IncIndent;
  991. WHILE(x # NIL) DO
  992. next := x.nextVariable;
  993. IF (x.access # SyntaxTree.Hidden) OR (mode > SourceCode) THEN
  994. Indent;
  995. Comments(x.comment, x, FALSE);
  996. PrintSymbol(x); Flags(x);
  997. WHILE(next # NIL) & (next.type = x.type) & ((next.access # SyntaxTree.Hidden) OR (mode > SourceCode)) DO
  998. w.String(", "); PrintSymbol(next); Flags(next);
  999. next := next.nextVariable;
  1000. END;
  1001. IF x.access # SyntaxTree.Hidden THEN
  1002. w.String(": ");
  1003. Type(x.type);
  1004. ELSE
  1005. w.String(": ");
  1006. ShortType(x.type);
  1007. END;
  1008. w.String("; ");
  1009. Comments(x.comment,x, TRUE);
  1010. END;
  1011. x := next;
  1012. END;
  1013. w.DecIndent
  1014. END VariableList;
  1015. PROCEDURE VisitParameter(x: SyntaxTree.Parameter);
  1016. BEGIN
  1017. IF (x.access # SyntaxTree.Hidden) THEN
  1018. Comments(x.comment,x,TRUE);
  1019. IF x.kind = SyntaxTree.VarParameter THEN Keyword("VAR " );
  1020. ELSIF x.kind = SyntaxTree.ConstParameter THEN Keyword("CONST " );
  1021. END;
  1022. PrintSymbol(x);
  1023. IF x.modifiers # NIL THEN w.String(" "); Modifiers(x.modifiers); END;
  1024. IF x.defaultValue # NIL THEN
  1025. w.String("= "); Expression(x.defaultValue);
  1026. END;
  1027. w.String( ": " );
  1028. Type(x.type);
  1029. Comments(x.comment,x,TRUE);
  1030. ELSIF (mode > SourceCode) THEN
  1031. Comments(x.comment,x,FALSE);
  1032. PrintSymbol(x);
  1033. Comments(x.comment,x,TRUE);
  1034. END;
  1035. END VisitParameter;
  1036. PROCEDURE ParameterList*(x: SyntaxTree.Parameter);
  1037. VAR next: SyntaxTree.Parameter; first: BOOLEAN;
  1038. PROCEDURE Flags(x: SyntaxTree.Parameter);
  1039. VAR first: BOOLEAN;
  1040. BEGIN
  1041. IF x.modifiers # NIL THEN
  1042. Modifiers(x.modifiers)
  1043. ELSE
  1044. first := TRUE;
  1045. IF x.untraced THEN
  1046. Flag(Global.NameUntraced,first)
  1047. END;
  1048. FlagEnd(first);
  1049. END;
  1050. END Flags;
  1051. BEGIN
  1052. first := TRUE;
  1053. w.String( "(" );
  1054. WHILE(x # NIL) DO
  1055. next := x.nextParameter;
  1056. IF (x.access # SyntaxTree.Hidden) OR (mode > SourceCode) THEN
  1057. IF ~first THEN w.String("; ") END;
  1058. first := FALSE;
  1059. IF x.kind = SyntaxTree.VarParameter THEN Keyword("VAR " );
  1060. ELSIF x.kind = SyntaxTree.ConstParameter THEN Keyword("CONST " );
  1061. END;
  1062. PrintSymbol(x); Flags(x);
  1063. IF x.defaultValue # NIL THEN
  1064. w.String("= "); Expression(x.defaultValue);
  1065. END;
  1066. WHILE (next # NIL) & (next.type = x.type) & (next.kind = x.kind) & ((next.access # SyntaxTree.Hidden) OR (mode > SourceCode)) DO
  1067. w.String(", ");
  1068. PrintSymbol(next); Flags(next);
  1069. IF next.defaultValue # NIL THEN
  1070. w.String("= "); Expression(next.defaultValue);
  1071. END;
  1072. next := next.nextParameter;
  1073. END;
  1074. IF x.access # SyntaxTree.Hidden THEN
  1075. w.String(": ");
  1076. Type(x.type);
  1077. ELSE
  1078. w.String(": ");
  1079. ShortType(x.type);
  1080. END;
  1081. END;
  1082. x := next;
  1083. END;
  1084. w.String( ")" );
  1085. END ParameterList;
  1086. PROCEDURE Access(access: SET);
  1087. BEGIN
  1088. IF SyntaxTree.PublicWrite IN access THEN w.String(" PublicWrite") END;
  1089. IF SyntaxTree.ProtectedWrite IN access THEN w.String(" ProtectedWrite") END;
  1090. IF SyntaxTree.InternalWrite IN access THEN w.String(" InternalWrite") END;
  1091. IF SyntaxTree.PublicRead IN access THEN w.String(" PublicRead") END;
  1092. IF SyntaxTree.ProtectedRead IN access THEN w.String(" ProtectedRead") END;
  1093. IF SyntaxTree.InternalRead IN access THEN w.String(" InternalRead") END;
  1094. END Access;
  1095. PROCEDURE VisitProcedure(x: SyntaxTree.Procedure);
  1096. VAR type: SyntaxTree.ProcedureType; flags: SET; first: BOOLEAN;
  1097. BEGIN
  1098. IF Visible(x) THEN
  1099. Indent;
  1100. Comments(x.comment,x,FALSE);
  1101. Keyword("PROCEDURE " );
  1102. IF (mode = SymbolFile) & ~x.isInline THEN
  1103. w.String("^ ");
  1104. END;
  1105. (*
  1106. CallingConvention(x.type(SyntaxTree.ProcedureType).callingConvention);
  1107. *)
  1108. type := x.type(SyntaxTree.ProcedureType);
  1109. (*
  1110. flags := type.flags;
  1111. *)
  1112. first := TRUE;
  1113. IF type.stackAlignment > 1 THEN Value(Global.NameStackAligned,type.stackAlignment,first) END;
  1114. IF (type.isRealtime) THEN Flag(Global.NameRealtime,first) END;
  1115. IF (type.noReturn) THEN Flag(Global.NameNoReturn,first) END;
  1116. IF (x.fixed) THEN Value(Global.NameFixed, x.alignment,first)
  1117. ELSIF (x.alignment >1) THEN Value(Global.NameAligned, x.alignment, first)
  1118. END;
  1119. FlagEnd(first);
  1120. IF x.isInline THEN w.String(" - ") END;
  1121. IF x.isConstructor THEN w.String(" & ") END;
  1122. IF x.isFinalizer THEN w.String(" ~ ") END;
  1123. IF info THEN
  1124. BeginComment;
  1125. Modifiers(x.type(SyntaxTree.ProcedureType).modifiers);
  1126. EndComment;
  1127. END;
  1128. PrintSymbol(x);
  1129. IF (type.firstParameter # NIL) OR (type.returnType # NIL ) THEN (* print parentheses only if not parameterless procedure *)
  1130. ParameterList(type.firstParameter);
  1131. END;
  1132. IF type.returnType # NIL THEN
  1133. w.String( ": " );
  1134. IF type.hasUntracedReturn THEN
  1135. first := TRUE;
  1136. Flag(Global.NameUntraced, first);
  1137. FlagEnd(first);
  1138. END;
  1139. Type(type.returnType);
  1140. END;
  1141. IF info & (type.returnParameter # NIL) THEN
  1142. BeginComment;
  1143. w.String("retPar = ");
  1144. Symbol(type.returnParameter);
  1145. EndComment;
  1146. END;
  1147. IF x.externalName = NIL THEN
  1148. IF (mode > SymbolFile) OR (mode = SymbolFile) & (x.isInline) THEN
  1149. w.String( ";" );
  1150. Comments(x.comment,x,TRUE);
  1151. IF mode >= SymbolFile THEN
  1152. ProcedureScope(x.procedureScope);
  1153. END;
  1154. Indent; Keyword("END " ); Identifier(x.name);
  1155. END;
  1156. END;
  1157. END;
  1158. END VisitProcedure;
  1159. PROCEDURE VisitOperator(x: SyntaxTree.Operator);
  1160. VAR type: SyntaxTree.ProcedureType;
  1161. recordType: SyntaxTree.RecordType;
  1162. i: LONGINT;
  1163. valid, first: BOOLEAN;
  1164. BEGIN
  1165. IF Visible(x) THEN
  1166. Indent;
  1167. Comments(x.comment,x,FALSE);
  1168. (* mark array access operators for array-structured object types *)
  1169. IF info THEN
  1170. IF (x.scope # NIL) & (x.scope IS SyntaxTree.RecordScope) THEN
  1171. recordType := x.scope(SyntaxTree.RecordScope).ownerRecord;
  1172. IF recordType.HasArrayStructure() THEN
  1173. BeginComment;
  1174. valid := FALSE;
  1175. IF x = recordType.arrayAccessOperators.len THEN w.String("the length operator: "); valid := TRUE;
  1176. ELSIF x = recordType.arrayAccessOperators.generalRead THEN w.String("the general read operator"); valid := TRUE;
  1177. ELSIF x = recordType.arrayAccessOperators.generalWrite THEN w.String("the general write operator"); valid := TRUE;
  1178. ELSE
  1179. FOR i := 0 TO LEN(recordType.arrayAccessOperators.read, 0) - 1 DO
  1180. IF x = recordType.arrayAccessOperators.read[i] THEN w.String("a read operator (hash="); w.Int(i, 1); w.String("):"); valid := TRUE;
  1181. ELSIF x = recordType.arrayAccessOperators.write[i] THEN w.String("a write operator (hash="); w.Int(i, 1); w.String("):"); valid := TRUE;
  1182. END
  1183. END
  1184. END;
  1185. IF ~valid THEN w.String("an invalid operator:") END;
  1186. EndComment;
  1187. w.String(" ");
  1188. END
  1189. END
  1190. END;
  1191. Keyword("OPERATOR ");
  1192. first := TRUE;
  1193. IF x.isInline THEN
  1194. ASSERT(~x.isDynamic);
  1195. w.String("-");
  1196. ELSE
  1197. IF mode = SymbolFile THEN w.String("^ ") END;
  1198. IF x.isDynamic THEN Flag(Global.NameDynamic, first) END;
  1199. IF ~first THEN w.String("}") END;
  1200. END;
  1201. type := x.type(SyntaxTree.ProcedureType);
  1202. PrintSymbol(x);
  1203. ParameterList(type.firstParameter);
  1204. IF type.returnType # NIL THEN
  1205. w.String( ": " );
  1206. IF type.hasUntracedReturn THEN
  1207. first := TRUE;
  1208. Flag(Global.NameUntraced, first);
  1209. FlagEnd(first);
  1210. END;
  1211. Type(type.returnType);
  1212. END;
  1213. IF info & (type.returnParameter # NIL) THEN
  1214. BeginComment;
  1215. (*w.String("retPar = ");*) (*! this is present in VisitProcedure - should it be present here as well??? *)
  1216. Symbol(type.returnParameter);
  1217. EndComment;
  1218. END;
  1219. IF x.externalName = NIL THEN
  1220. IF (mode > SymbolFile) OR (mode = SymbolFile) & (x.isInline) THEN
  1221. w.String( ";" );
  1222. Comments(x.comment,x,TRUE);
  1223. IF mode >= SymbolFile THEN
  1224. ProcedureScope(x.procedureScope);
  1225. END;
  1226. Indent; Keyword("END " ); w.String( '"' ); Identifier(x.name); w.String( '"' );
  1227. END;
  1228. END;
  1229. END
  1230. END VisitOperator;
  1231. PROCEDURE ProcedureList(x: SyntaxTree.Procedure);
  1232. BEGIN
  1233. w.IncIndent;
  1234. WHILE(x # NIL) DO
  1235. IF (x.access # SyntaxTree.Hidden) & ~(x.isBodyProcedure) OR (mode > SourceCode) THEN
  1236. Symbol(x);
  1237. w.String( "; " );
  1238. END;
  1239. x := x.nextProcedure;
  1240. IF (x# NIL) & (mode > SymbolFile) & ((x.access # SyntaxTree.Hidden) OR (mode > SourceCode)) THEN w.Ln END;
  1241. END;
  1242. w.DecIndent;
  1243. END ProcedureList;
  1244. PROCEDURE VisitImport(x: SyntaxTree.Import);
  1245. VAR context: SyntaxTree.Identifier;
  1246. BEGIN
  1247. IF x.moduleName # x.name THEN Identifier(x.name); w.String( " := " ); END;
  1248. IF (x.scope = NIL) OR (x.scope.ownerModule = NIL) THEN context := SyntaxTree.invalidIdentifier ELSE context := x.scope.ownerModule.context END;
  1249. Identifier(x.moduleName);
  1250. IF (x.context # SyntaxTree.invalidIdentifier) & (x.context#context) THEN
  1251. w.String(" IN ");
  1252. Identifier(x.context)
  1253. END;
  1254. END VisitImport;
  1255. PROCEDURE ImportList(x: SyntaxTree.Import);
  1256. VAR first: BOOLEAN;
  1257. BEGIN
  1258. first := TRUE;
  1259. WHILE(x # NIL) DO
  1260. IF x.direct & (x.module # NIL) OR (mode > SymbolFile) THEN
  1261. IF ~first THEN w.String(", ") ELSE Indent; Keyword("IMPORT "); first := FALSE END;
  1262. Symbol(x);
  1263. END;
  1264. x := x.nextImport;
  1265. END;
  1266. IF ~first THEN w.String( ";" ); END;
  1267. END ImportList;
  1268. PROCEDURE VisitBuiltin(x: SyntaxTree.Builtin);
  1269. BEGIN
  1270. Indent; Keyword("BUILTIN ");
  1271. Identifier(x.name);
  1272. END VisitBuiltin;
  1273. PROCEDURE BuiltinList(x: SyntaxTree.Builtin);
  1274. BEGIN
  1275. WHILE(x # NIL) DO
  1276. VisitBuiltin(x);
  1277. x := x.nextBuiltin;
  1278. END;
  1279. END BuiltinList;
  1280. PROCEDURE BeginComment;
  1281. BEGIN
  1282. w.BeginComment; w.String("(*");
  1283. END BeginComment;
  1284. PROCEDURE EndComment;
  1285. BEGIN
  1286. w.String("*)");w.EndComment
  1287. END EndComment;
  1288. PROCEDURE Comment(x: SyntaxTree.Comment);
  1289. VAR i: LONGINT; ch: CHAR;
  1290. BEGIN
  1291. BeginComment;
  1292. WHILE (i<LEN(x.source^)) & (x.source[i] # 0X) DO
  1293. ch := x.source[i];
  1294. IF ch = 0DX THEN w.Ln
  1295. ELSE w.Char(ch)
  1296. END;
  1297. INC(i);
  1298. END;
  1299. EndComment;
  1300. END Comment;
  1301. PROCEDURE Comments(c: SyntaxTree.Comment; x: ANY; sameLine: BOOLEAN);
  1302. BEGIN
  1303. IF mode >= SourceCode THEN
  1304. WHILE (c # NIL) & (c.item = x) DO
  1305. IF c.sameLine = sameLine THEN
  1306. Comment(c);
  1307. IF ~sameLine THEN
  1308. Indent;
  1309. END;
  1310. END;
  1311. c := c.nextComment;
  1312. END;
  1313. END;
  1314. END Comments;
  1315. PROCEDURE CommentList(x: SyntaxTree.Comment);
  1316. BEGIN
  1317. IF info THEN
  1318. WHILE (x#NIL) DO
  1319. Indent;
  1320. w.String("comment at position "); w.Int(x.position,1);
  1321. IF x.sameLine THEN w.String("(in line with item)") END;
  1322. IF x.item = NIL THEN w.String("(no item)"); END;
  1323. w.String(":");
  1324. Comment(x);
  1325. x := x.nextComment;
  1326. END;
  1327. END;
  1328. END CommentList;
  1329. (*** scopes ****)
  1330. PROCEDURE Scope*(x: SyntaxTree.Scope);
  1331. VAR prevScope: SyntaxTree.Scope;
  1332. BEGIN
  1333. prevScope := currentScope;
  1334. currentScope := x;
  1335. (* ASSERT(currentScope.outerScope = prevScope); (* sanity check *) *)
  1336. IF x.firstConstant # NIL THEN ConstantList(x.firstConstant); END;
  1337. IF x.firstTypeDeclaration # NIL THEN TypeDeclarationList(x.firstTypeDeclaration); END;
  1338. IF x.firstVariable # NIL THEN Indent; Keyword("VAR " ); VariableList(x.firstVariable); END;
  1339. IF x.firstProcedure # NIL THEN w.Ln; ProcedureList(x.firstProcedure) END;
  1340. currentScope := prevScope;
  1341. END Scope;
  1342. PROCEDURE ProcedureScope(x: SyntaxTree.ProcedureScope);
  1343. VAR prevScope: SyntaxTree.Scope;
  1344. BEGIN
  1345. prevScope := currentScope;
  1346. currentScope := x;
  1347. IF (mode >= SourceCode) OR (x.ownerProcedure.isInline) THEN Scope(x) END;
  1348. IF (mode >= SymbolFile) & (x.body # NIL) THEN Body(x.body)
  1349. END;
  1350. currentScope := prevScope;
  1351. END ProcedureScope;
  1352. PROCEDURE Statement*(x: SyntaxTree.Statement);
  1353. BEGIN
  1354. IF x = NIL THEN
  1355. AlertString("nil statement")
  1356. ELSE
  1357. Comments(x.comment, x, FALSE);
  1358. x.Accept(SELF);
  1359. Comments(x.comment,x,TRUE);
  1360. END
  1361. END Statement;
  1362. PROCEDURE StatementSequence*(x: SyntaxTree.StatementSequence);
  1363. VAR statement: SyntaxTree.Statement; i: LONGINT;
  1364. BEGIN
  1365. IF singleStatement THEN
  1366. w.String("...")
  1367. ELSE
  1368. FOR i := 0 TO x.Length() - 1 DO
  1369. statement := x.GetStatement( i );
  1370. Indent; Statement(statement);
  1371. IF i < x.Length() - 1 THEN w.String( "; " ); END;
  1372. END;
  1373. END;
  1374. END StatementSequence;
  1375. PROCEDURE VisitStatement(x: SyntaxTree.Statement);
  1376. BEGIN
  1377. AlertString("InvalidStatement");
  1378. END VisitStatement;
  1379. PROCEDURE VisitProcedureCallStatement(x: SyntaxTree.ProcedureCallStatement);
  1380. BEGIN Expression(x.call) END VisitProcedureCallStatement;
  1381. PROCEDURE VisitAssignment(x: SyntaxTree.Assignment);
  1382. BEGIN
  1383. Expression(x.left); w.String( " := " ); Expression(x.right);
  1384. END VisitAssignment;
  1385. PROCEDURE VisitCommunicationStatement(x: SyntaxTree.CommunicationStatement);
  1386. VAR identifier: SyntaxTree.Identifier;
  1387. BEGIN
  1388. Expression(x.left);
  1389. identifier := Global.GetIdentifier(x.op,case);
  1390. w.String(" "); Identifier(identifier); w.String(" ");
  1391. Expression(x.right);
  1392. END VisitCommunicationStatement;
  1393. PROCEDURE IfPart(x: SyntaxTree.IfPart);
  1394. BEGIN
  1395. Comments(x.comment, x, FALSE);
  1396. Keyword("IF " );
  1397. Expression(x.condition);
  1398. Keyword(" THEN " );
  1399. Comments(x.comment,x,TRUE);
  1400. w.IncIndent;
  1401. StatementSequence(x.statements);
  1402. w.DecIndent;
  1403. END IfPart;
  1404. PROCEDURE VisitIfStatement(x: SyntaxTree.IfStatement);
  1405. VAR i: LONGINT; elsif: SyntaxTree.IfPart;
  1406. BEGIN
  1407. IfPart(x.ifPart);
  1408. FOR i := 0 TO x.ElsifParts() - 1 DO
  1409. elsif := x.GetElsifPart( i );
  1410. Indent; Keyword("ELS");
  1411. IfPart(elsif);
  1412. END;
  1413. IF x.elsePart # NIL THEN
  1414. Indent; Keyword("ELSE" );
  1415. w.IncIndent;
  1416. StatementSequence(x.elsePart);
  1417. w.DecIndent;
  1418. END;
  1419. Indent; Keyword("END" );
  1420. END VisitIfStatement;
  1421. PROCEDURE WithPart(x: SyntaxTree.WithPart);
  1422. BEGIN
  1423. Comments(x.comment, x, FALSE);
  1424. Expression(x.variable);
  1425. w.String(" : ");
  1426. Type(x.type);
  1427. Keyword(" DO " );
  1428. Comments(x.comment,x, TRUE);
  1429. w.IncIndent; StatementSequence(x.statements); w.DecIndent;
  1430. END WithPart;
  1431. PROCEDURE VisitWithStatement(x: SyntaxTree.WithStatement);
  1432. VAR i: LONGINT;
  1433. BEGIN
  1434. Indent; Keyword("WITH " );
  1435. WithPart(x.GetWithPart(0));
  1436. FOR i := 1 TO x.WithParts()-1 DO
  1437. Indent; w.String("| ");
  1438. WithPart(x.GetWithPart(i));
  1439. END;
  1440. IF x.elsePart # NIL THEN
  1441. Indent; w.String("ELSE ");
  1442. w.IncIndent; StatementSequence(x.elsePart); w.DecIndent;
  1443. END;
  1444. Indent; Keyword("END" );
  1445. END VisitWithStatement;
  1446. PROCEDURE CasePart(x: SyntaxTree.CasePart);
  1447. VAR case: SyntaxTree.CaseConstant;
  1448. BEGIN
  1449. Comments(x.comment, x, FALSE);
  1450. ExpressionList(x.elements);
  1451. IF info THEN
  1452. w.BeginComment;
  1453. case := x.firstConstant;
  1454. WHILE(case # NIL) DO
  1455. IF case # x.firstConstant THEN w.String(",") END;
  1456. w.Int(case.min,1); w.String(".."); w.Int(case.max,1);
  1457. case := case.next;
  1458. END;
  1459. EndComment;
  1460. END;
  1461. w.String( ":" );
  1462. Comments(x.comment,x,TRUE);
  1463. w.IncIndent; StatementSequence(x.statements); w.DecIndent;
  1464. END CasePart;
  1465. PROCEDURE VisitCaseStatement(x: SyntaxTree.CaseStatement);
  1466. VAR i: LONGINT; case: SyntaxTree.CasePart;
  1467. BEGIN
  1468. Keyword("CASE " );
  1469. Expression(x.variable);
  1470. Keyword(" OF " );
  1471. FOR i := 0 TO x.CaseParts() - 1 DO
  1472. case := x.GetCasePart( i );
  1473. Indent;
  1474. w.String( "| " );
  1475. CasePart(case);
  1476. END;
  1477. IF x.elsePart # NIL THEN
  1478. Indent;
  1479. Keyword("ELSE" );
  1480. w.IncIndent;
  1481. StatementSequence(x.elsePart);
  1482. w.DecIndent;
  1483. END;
  1484. Indent;
  1485. Keyword("END" );
  1486. END VisitCaseStatement;
  1487. PROCEDURE VisitWhileStatement(x: SyntaxTree.WhileStatement);
  1488. BEGIN
  1489. Keyword("WHILE " );
  1490. Expression(x.condition);
  1491. Keyword(" DO " );
  1492. w.IncIndent;
  1493. StatementSequence(x.statements);
  1494. w.DecIndent;
  1495. Indent;
  1496. Keyword("END" );
  1497. END VisitWhileStatement;
  1498. PROCEDURE VisitRepeatStatement(x: SyntaxTree.RepeatStatement);
  1499. BEGIN
  1500. Keyword("REPEAT " );
  1501. w.IncIndent;
  1502. StatementSequence(x.statements);
  1503. w.DecIndent;
  1504. Indent; Keyword("UNTIL " );
  1505. Expression(x.condition);
  1506. END VisitRepeatStatement;
  1507. PROCEDURE VisitForStatement(x: SyntaxTree.ForStatement);
  1508. BEGIN
  1509. Keyword("FOR " );
  1510. Expression(x.variable);
  1511. w.String( " := " );
  1512. Expression(x.from);
  1513. Keyword(" TO " );
  1514. Expression(x.to);
  1515. IF x.by # NIL THEN
  1516. Keyword(" BY " );
  1517. Expression(x.by);
  1518. END;
  1519. Keyword(" DO " );
  1520. w.IncIndent;
  1521. StatementSequence(x.statements);
  1522. w.DecIndent;
  1523. Indent;
  1524. Keyword("END" );
  1525. END VisitForStatement;
  1526. PROCEDURE VisitLoopStatement(x: SyntaxTree.LoopStatement);
  1527. BEGIN
  1528. Keyword("LOOP " );
  1529. w.IncIndent; StatementSequence(x.statements); w.DecIndent;
  1530. Indent; Keyword("END" );
  1531. END VisitLoopStatement;
  1532. PROCEDURE VisitExitableBlock(x: SyntaxTree.ExitableBlock);
  1533. BEGIN
  1534. Keyword("EXITABLE " );
  1535. w.IncIndent; StatementSequence(x.statements); w.DecIndent;
  1536. Indent; Keyword("END " );
  1537. END VisitExitableBlock;
  1538. PROCEDURE VisitExitStatement(x: SyntaxTree.ExitStatement);
  1539. BEGIN Keyword("EXIT" ) END VisitExitStatement;
  1540. PROCEDURE VisitReturnStatement(x: SyntaxTree.ReturnStatement);
  1541. BEGIN
  1542. Keyword("RETURN " );
  1543. IF x.returnValue # NIL THEN Expression(x.returnValue) END
  1544. END VisitReturnStatement;
  1545. PROCEDURE VisitAwaitStatement(x: SyntaxTree.AwaitStatement);
  1546. BEGIN
  1547. Keyword("AWAIT (" ); Expression(x.condition); w.String( ")" );
  1548. END VisitAwaitStatement;
  1549. PROCEDURE Modifiers(x: SyntaxTree.Modifier);
  1550. VAR name: Scanner.IdentifierString; first: BOOLEAN;
  1551. BEGIN
  1552. first := TRUE;
  1553. WHILE x # NIL DO
  1554. IF first THEN w.String("{"); first := FALSE ELSE w.String(", ") END;
  1555. Basic.GetString(x.identifier,name);
  1556. w.String(name);
  1557. IF x.expression # NIL THEN
  1558. w.String("(");
  1559. Expression(x.expression);
  1560. w.String(")");
  1561. END;
  1562. x := x.nextModifier;
  1563. END;
  1564. IF ~first THEN w.String("} ") END;
  1565. END Modifiers;
  1566. (*
  1567. PROCEDURE BlockModifier(x: SyntaxTree.StatementBlock);
  1568. VAR first: BOOLEAN;
  1569. PROCEDURE Comma;
  1570. BEGIN
  1571. IF first THEN first := FALSE ELSE w.String(", "); END;
  1572. END Comma;
  1573. BEGIN
  1574. first := TRUE;
  1575. IF x.flags # {} THEN
  1576. w.String("{");
  1577. IF SyntaxTree.ActiveFlag IN x.flags THEN Comma; w.String("ACTIVE") END;
  1578. IF SyntaxTree.PriorityFlag IN x.flags THEN Comma; w.String("PRIORITY("); Expression(x(SyntaxTree.Body).priority); w.String(")"); first := FALSE; END;
  1579. IF SyntaxTree.SafeFlag IN x.flags THEN Comma; w.String("SAFE") END;
  1580. IF SyntaxTree.ExclusiveFlag IN x.flags THEN Comma; w.String("EXCLUSIVE") END;
  1581. w.String("}");
  1582. END;
  1583. END BlockModifier;
  1584. *)
  1585. PROCEDURE VisitStatementBlock(x: SyntaxTree.StatementBlock);
  1586. BEGIN
  1587. Keyword("BEGIN"); Modifiers(x.blockModifiers);
  1588. w.IncIndent;
  1589. IF x.statements # NIL THEN StatementSequence(x.statements); END;
  1590. w.DecIndent;
  1591. Indent; Keyword("END");
  1592. END VisitStatementBlock;
  1593. PROCEDURE Code(x: SyntaxTree.Code);
  1594. VAR i: LONGINT; ch: CHAR; cr: BOOLEAN; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1595. CONST CR=0DX;
  1596. BEGIN
  1597. IF (currentScope # NIL) & (currentScope IS SyntaxTree.ProcedureScope) THEN
  1598. procedure := currentScope(SyntaxTree.ProcedureScope).ownerProcedure;
  1599. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1600. END;
  1601. IF (mode >= SourceCode) OR (procedure = NIL) OR (procedure.access * SyntaxTree.Public # {}) & procedure.isInline THEN
  1602. (*
  1603. IF x.inlineCode # NIL THEN
  1604. unit := 8;
  1605. w.String(" D"); w.Int(unit,1);
  1606. i := 0; size := x.inlineCode.GetSize();
  1607. WHILE i < size DO
  1608. value := x.inlineCode.GetBits(i,unit);
  1609. w.String(" "); w.Int(value,1);
  1610. INC(i,unit);
  1611. END;
  1612. ELS*)
  1613. IF (x.sourceCode # NIL) THEN
  1614. i := 0;
  1615. ch := x.sourceCode[0];
  1616. WHILE (ch # 0X) DO
  1617. IF ch = CR THEN
  1618. cr := TRUE;
  1619. ELSE
  1620. IF cr THEN Indent; cr := FALSE END;
  1621. w.Char(ch);
  1622. END;
  1623. INC(i); ch := x.sourceCode[i];
  1624. END;
  1625. END;
  1626. (*
  1627. IF x.inlineCode # NIL THEN
  1628. w.String("; ");
  1629. size := x.inlineCode.GetSize() DIV 8;
  1630. FOR i := 0 TO size-1 DO
  1631. value := x.inlineCode.GetBits(i*8,8);
  1632. w.Hex(value,-2); w.String(" ");
  1633. END;
  1634. END;
  1635. *)
  1636. END;
  1637. END Code;
  1638. PROCEDURE VisitCode(x: SyntaxTree.Code);
  1639. VAR in, out: BOOLEAN;
  1640. BEGIN
  1641. Indent; Keyword("CODE");
  1642. Code(x);
  1643. in := x.inRules.Length()>0;
  1644. out := x.outRules.Length() >0;
  1645. IF in OR out THEN
  1646. Indent; Keyword("WITH ");
  1647. IF in THEN
  1648. Indent; Keyword("IN "); StatementSequence(x.inRules)
  1649. END;
  1650. IF out THEN
  1651. Indent; Keyword("OUT "); StatementSequence(x.outRules)
  1652. END;
  1653. END;
  1654. Indent; Keyword("END");
  1655. END VisitCode;
  1656. PROCEDURE Body(x: SyntaxTree.Body);
  1657. VAR
  1658. BEGIN
  1659. IF x.code # NIL THEN
  1660. Indent; Keyword("CODE");
  1661. Code(x.code);
  1662. ELSE
  1663. Indent; Keyword("BEGIN" ); Modifiers(x.blockModifiers);
  1664. IF mode >= SourceCode THEN
  1665. IF x.statements # NIL THEN
  1666. w.IncIndent;
  1667. StatementSequence(x.statements);
  1668. w.DecIndent;
  1669. END;
  1670. IF x.finally # NIL THEN
  1671. Indent; Keyword("FINALLY" );
  1672. w.IncIndent;
  1673. StatementSequence(x.finally);
  1674. w.DecIndent
  1675. END;
  1676. END;
  1677. END;
  1678. (* "END" written by caller *)
  1679. END Body;
  1680. PROCEDURE Module*(x: SyntaxTree.Module);
  1681. BEGIN
  1682. IF x = NIL THEN
  1683. AlertString("(* no module *)");
  1684. ELSE
  1685. case := x.case;
  1686. currentScope := x.moduleScope.outerScope;
  1687. Comments(x.comment,x,FALSE);
  1688. Keyword("MODULE ");
  1689. Identifier(x.name);
  1690. IF (x.context # SyntaxTree.invalidIdentifier) & (x.context#Global.A2Name) THEN
  1691. w.String(" IN ");
  1692. Identifier(x.context)
  1693. END;
  1694. IF (x.type IS SyntaxTree.CellType) & (x.type(SyntaxTree.CellType).firstParameter # NIL) THEN (* for actors *)
  1695. ParameterList(x.type(SyntaxTree.CellType).firstParameter);
  1696. END;
  1697. w.String(";");
  1698. Comments(x.comment,x,TRUE);
  1699. w.IncIndent;
  1700. IF x.moduleScope.firstImport # NIL THEN
  1701. ImportList(x.moduleScope.firstImport)
  1702. END;
  1703. w.DecIndent;
  1704. Scope(x.moduleScope);
  1705. IF x.moduleScope.firstBuiltin # NIL THEN
  1706. BuiltinList(x.moduleScope.firstBuiltin)
  1707. END;
  1708. IF (x.moduleScope.bodyProcedure # NIL) & (x.moduleScope.bodyProcedure.procedureScope.body # NIL) THEN
  1709. Body(x.moduleScope.bodyProcedure.procedureScope.body)
  1710. END;
  1711. Indent; Keyword("END "); Identifier(x.name); w.String( "." ); w.Ln; w.Update;
  1712. Comments(x.closingComment,x, FALSE);
  1713. IF (mode > SourceCode) & (x.moduleScope.firstComment # NIL) THEN w.Ln; CommentList(x.moduleScope.firstComment) END;
  1714. END
  1715. END Module;
  1716. PROCEDURE SingleStatement*(b: BOOLEAN);
  1717. BEGIN singleStatement := b
  1718. END SingleStatement;
  1719. PROCEDURE &Init*(w: Streams.Writer; mode: LONGINT; info: BOOLEAN);
  1720. BEGIN
  1721. SELF.w := Basic.GetWriter(w);
  1722. SELF.mode := mode; NEW(ws,128); SELF.info := info; case := Scanner.Uppercase;
  1723. commentCount := 0; alertCount := 0; singleStatement := FALSE;
  1724. END Init;
  1725. END Printer;
  1726. (* debugging helper *)
  1727. VAR
  1728. debug: Printer;
  1729. PROCEDURE NewPrinter*(w: Streams.Writer; mode: LONGINT; info: BOOLEAN): Printer;
  1730. VAR p: Printer;
  1731. BEGIN
  1732. NEW(p,w,mode,info); RETURN p
  1733. END NewPrinter;
  1734. PROCEDURE Info*(CONST info: ARRAY OF CHAR; a: ANY);
  1735. VAR symbol: SyntaxTree.Symbol; scope: SyntaxTree.Scope;
  1736. BEGIN
  1737. debug.w := Basic.GetWriter(D.Log);
  1738. D.Ln;
  1739. D.Str(" --------> ");
  1740. D.Str(info);
  1741. D.Str(" ");
  1742. D.Hex(SYSTEM.VAL(LONGINT,a),8);
  1743. D.Str(" : ");
  1744. IF a = NIL THEN
  1745. D.Str("NIL");
  1746. ELSIF a IS SyntaxTree.Expression THEN
  1747. debug.Expression(a(SyntaxTree.Expression));
  1748. Info("with type",a(SyntaxTree.Expression).type);
  1749. ELSIF a IS SyntaxTree.Type THEN
  1750. IF a IS SyntaxTree.QualifiedType THEN
  1751. D.Str("[QualifiedType] ");
  1752. END;
  1753. debug.Type(a(SyntaxTree.Type))
  1754. ELSIF a IS SyntaxTree.Symbol THEN
  1755. debug.Symbol(a(SyntaxTree.Symbol))
  1756. ELSIF a IS SyntaxTree.Statement THEN
  1757. debug.Statement(a(SyntaxTree.Statement))
  1758. ELSIF a IS SyntaxTree.StatementSequence THEN
  1759. debug.StatementSequence(a(SyntaxTree.StatementSequence));
  1760. ELSIF a IS SyntaxTree.Scope THEN
  1761. scope := a(SyntaxTree.Scope);
  1762. WHILE(scope # NIL) DO
  1763. D.Ln; D.Str(" ");
  1764. IF scope IS SyntaxTree.ModuleScope THEN D.Str("ModuleScope: ")
  1765. ELSIF scope IS SyntaxTree.ProcedureScope THEN D.Str("ProcedureScope: ");
  1766. ELSIF scope IS SyntaxTree.RecordScope THEN D.Str("RecordScope: ");
  1767. ELSE D.Str("Scope: ");
  1768. END;
  1769. symbol := scope.firstSymbol;
  1770. WHILE(symbol # NIL) DO
  1771. debug.Identifier(symbol.name); D.Str(" ");
  1772. symbol := symbol.nextSymbol;
  1773. END;
  1774. scope := scope.outerScope;
  1775. END;
  1776. (*
  1777. ELSIF a IS SyntaxTree.Identifier THEN
  1778. debug.Identifier(a(SyntaxTree.Identifier));
  1779. *)
  1780. ELSIF a IS SyntaxTree.QualifiedIdentifier THEN
  1781. debug.QualifiedIdentifier(a(SyntaxTree.QualifiedIdentifier));
  1782. ELSIF a IS SyntaxTree.Module THEN
  1783. debug.Module(a(SyntaxTree.Module))
  1784. ELSE
  1785. debug.w.String("unknown");
  1786. END;
  1787. D.Update();
  1788. END Info;
  1789. PROCEDURE IsIntegerValue(x: SyntaxTree.Expression; VAR value: LONGINT): BOOLEAN;
  1790. VAR result: BOOLEAN;
  1791. BEGIN
  1792. IF (x.resolved # NIL) & (x.resolved IS SyntaxTree.IntegerValue) THEN
  1793. value := x.resolved(SyntaxTree.IntegerValue).value;
  1794. result := TRUE
  1795. ELSE
  1796. result := FALSE
  1797. END;
  1798. RETURN result
  1799. END IsIntegerValue;
  1800. PROCEDURE Init;
  1801. BEGIN
  1802. NEW(debug,D.Log,All,TRUE);
  1803. debug.case := Scanner.Uppercase;
  1804. END Init;
  1805. BEGIN
  1806. Init;
  1807. END FoxPrintout.