FoxPrintout.Mod 54 KB

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