FoxPrintout.Mod 54 KB

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