FoxPrintout.Mod 55 KB

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