COMPILER.MOD 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. (* Renamed for readability. Semantics unchanged. Original identifiers: see docs/compiler/ + src/compiler/RENAME-MAP.md. *)
  2. IMPLEMENTATION MODULE COMPILER;
  3. IMPORT SCANNER, Files, SYMTAB, ERRORS, Texts, Terminal, ComLine;
  4. FROM SYSTEM IMPORT ADR, BDOS, IORESULT; (* NOTE: ADDRESS/WORD/BYTE NOT imported here
  5. although used below — they come via the DEFINITION module's own SYSTEM
  6. import, which this compiler leaks into the implementation scope; listing
  7. them again is a hard error ("ADDRESS is declared twice", proven). *)
  8. FROM STORAGE IMPORT FREEMEM;
  9. (* $[+ remove procedure names *)
  10. VAR
  11. reserved27: RecordPtr;
  12. reserved28: RecordPtr;
  13. reserved29: RecordPtr;
  14. reserved30: RecordPtr;
  15. curScopeHead: RecordPtr;
  16. savedScopeHead: RecordPtr;
  17. baseScopeHead: RecordPtr;
  18. bitsetRangeDesc: RecordPtr;
  19. lastParamList: ArrayPtr;
  20. (* InitCompiler/OpenSourceAndOutput are DEF-declared (no FORWARD here:
  21. v1.00 rejects a FORWARD duplicating a DEF declaration). *)
  22. PROCEDURE InsertIdent(keyword: ARRAY OF CHAR; kind: CARDINAL):ADDRESS;
  23. VAR ptr : RecordPtr;
  24. BEGIN
  25. ptr := SCANNER.NewNode(kind);
  26. SCANNER.CopyStr(ptr^.word1, keyword);
  27. ptr^.word0 := curScopeHead;
  28. ptr^.word3 := BITSET{6}; (* was 64 *)
  29. curScopeHead := ptr;
  30. RETURN ptr
  31. END InsertIdent;
  32. PROCEDURE DeclConst(keyword: ARRAY OF CHAR; typeDesc: RecordPtr;
  33. constValue: WORD; kind:CARDINAL);
  34. VAR ptr: RecordPtr;
  35. BEGIN
  36. ptr := InsertIdent(keyword, kind);
  37. ptr^.word2 := typeDesc;
  38. ptr^.word5 := constValue;
  39. END DeclConst;
  40. PROCEDURE DeclStdProc(keyword: ARRAY OF CHAR; procNo,signature: WORD);
  41. VAR ptr: RecordPtr;
  42. BEGIN
  43. ptr := InsertIdent(keyword, 5);
  44. ptr^.word5 := procNo;
  45. ptr^.high := signature;
  46. END DeclStdProc;
  47. PROCEDURE DeclProc(keyword: ARRAY OF CHAR; procNo: CARDINAL);
  48. BEGIN
  49. DeclStdProc(keyword, procNo, 0);
  50. curScopeHead^.word3 := BITSET{6,7}; (* was 192 *)
  51. END DeclProc;
  52. PROCEDURE DeclFunc(keyword: ARRAY OF CHAR; funcNo: CARDINAL; returnType: RecordPtr);
  53. BEGIN
  54. DeclProc(keyword, funcNo);
  55. curScopeHead^.word2 := returnType;
  56. END DeclFunc;
  57. PROCEDURE NewTypeDesc(typeSize: BITSET; typeId: CARDINAL): RecordPtr;
  58. VAR ptr : RecordPtr;
  59. BEGIN
  60. ptr := SCANNER.NewSized(typeId);
  61. ptr^.word3 := typeSize;
  62. RETURN ptr
  63. END NewTypeDesc;
  64. PROCEDURE DeclType(keyword: ARRAY OF CHAR; tsize: BITSET; id: CARDINAL): ADDRESS;
  65. VAR ptr, ptr2 : RecordPtr;
  66. BEGIN
  67. ptr := InsertIdent(keyword, 3);
  68. ptr2:= NewTypeDesc(tsize, id);
  69. ptr^.word2 := ptr2;
  70. ptr2^.word0:= ptr;
  71. RETURN ptr2
  72. END DeclType;
  73. PROCEDURE InitOperatorTable;
  74. VAR opIndex: CARDINAL;
  75. PROCEDURE AddOperator(char1,char2: CHAR; opCode: CARDINAL);
  76. BEGIN
  77. ERRORS.opCharTable^[opIndex] := char1;
  78. ERRORS.opCharTable^[opIndex+1] := char2;
  79. ERRORS.opCharTable^[opIndex+2] := CHR(opCode);
  80. INC(opIndex,3);
  81. END AddOperator;
  82. BEGIN
  83. SCANNER.Allocate(ERRORS.opCharTable, 27);
  84. opIndex := 0;
  85. AddOperator(':','=',27);
  86. AddOperator('.','.', 4);
  87. AddOperator('<','=',56);
  88. AddOperator('>','=',57);
  89. AddOperator('<','>',53);
  90. AddOperator('(','.',44);
  91. AddOperator('.',')', 6);
  92. AddOperator('(',':',45);
  93. AddOperator(':',')', 7);
  94. END InitOperatorTable;
  95. PROCEDURE InitCharClasses;
  96. CONST DEL = 177C;
  97. VAR chCode: CARDINAL;
  98. glyphs: ARRAY [0..64] OF CHAR;
  99. code : CARDINAL;
  100. BEGIN
  101. SCANNER.Allocate(SCANNER.charClas, 128);
  102. chCode := ORD('A');
  103. REPEAT
  104. SCANNER.charClas^[chCode] := ORD(CHR(10));
  105. SCANNER.charClas^[chCode+32] := ORD(CHR(10));
  106. INC(chCode);
  107. UNTIL chCode > ORD('Z');
  108. chCode := ORD('0'); REPEAT SCANNER.charClas^[chCode] := ORD(CHR(11)); INC(chCode) UNTIL chCode > ORD('9');
  109. SCANNER.charClas^[ORD('!')] := ORD(CHR(8));
  110. SCANNER.charClas^[ORD('~')] := ORD(CHR(66));
  111. SCANNER.charClas^[ORD(DEL)] := ORD(CHR(4));
  112. SCANNER.charClas^[ORD('"')] := ORD(CHR(12));
  113. glyphs := " ,:. )]}|; ' ([{^ =#<> +-* /&";
  114. code := 0;
  115. REPEAT
  116. IF glyphs[code] <> ' ' THEN SCANNER.charClas^[ORD(glyphs[code])]:=ORD(CHR(code)) END;
  117. INC(code)
  118. UNTIL code > 64;
  119. END InitCharClasses;
  120. PROCEDURE InitKeywordTable;
  121. VAR p: POINTER TO ARRAY [0..29] OF CARDINAL;
  122. BEGIN
  123. SCANNER.Allocate(keywordTable, 30*2);
  124. p := keywordTable;
  125. p^[ 0] := 730;
  126. p^[ 1] := 731;
  127. p^[ 2] := 1245;
  128. p^[ 3] := 1206;
  129. p^[ 4] := 999;
  130. p^[ 5] := 1258;
  131. p^[ 6] := 1127;
  132. p^[ 7] := 708;
  133. p^[ 8] := 1312;
  134. p^[ 9] := 1234;
  135. p^[10] := 979;
  136. p^[11] := 990;
  137. p^[12] := 991;
  138. p^[13] := 747;
  139. p^[14] := 257;
  140. p^[15] := 1248;
  141. p^[16] := 993;
  142. p^[17] := 304;
  143. p^[18] := 49;
  144. p^[19] := 1229;
  145. p^[20] := 1230;
  146. p^[21] := 1231;
  147. p^[22] := 1236;
  148. p^[23] := 1024;
  149. p^[24] := 1281;
  150. p^[25] := 770;
  151. p^[26] := 772;
  152. p^[27] := 0;
  153. p^[28] := 195;
  154. p^[29] := 80;
  155. END InitKeywordTable;
  156. PROCEDURE DeclarePredefinedTypes;
  157. VAR p : RecordPtr;
  158. BEGIN
  159. curScopeHead := baseScopeHead;
  160. IntType := DeclType("INTEGER", BITSET{1}, 2);
  161. CharType := DeclType("CHAR", BITSET{0}, 0); CharType^.high := 255;
  162. BooleanType := DeclType("BOOLEAN", BITSET{0}, 0); BooleanType^.high := 1;
  163. CardType := DeclType("CARDINAL", BITSET{1}, 2);
  164. RealType := DeclType("REAL", BITSET{2}, 8);
  165. LongrealType := DeclType("LONGREAL", BITSET{3}, 8);
  166. BitsetType := DeclType("BITSET", BITSET{1}, 4);
  167. bitsetRangeDesc := NewTypeDesc(BITSET{0}, 1); bitsetRangeDesc^.word2 := CardType; bitsetRangeDesc^.high := 15;
  168. BitsetType^.word2 := bitsetRangeDesc;
  169. ProcType := DeclType("PROC", BITSET{2}, 9);
  170. LongintType := DeclType("LONGINT", BITSET{2}, 7);
  171. baseScopeHead := curScopeHead;
  172. curScopeHead := savedScopeHead;
  173. WordType := DeclType("WORD", BITSET{1}, 3);
  174. AddressType := DeclType("ADDRESS", BITSET{1}, 2);
  175. ByteType := DeclType("BYTE", BITSET{0}, 1); ByteType^.word2 := WordType;
  176. ByteType^.high := 255;
  177. p := InsertIdent("PROCESS",3);
  178. p^.word2 := AddressType;
  179. addressAlias := AddressType;
  180. savedScopeHead := curScopeHead;
  181. charArrayDesc := NewTypeDesc(BITSET{}, 11); charArrayDesc^.word5 := CharType;
  182. END DeclarePredefinedTypes;
  183. PROCEDURE MakeParamList(paramCount: CARDINAL; resultKind: CARDINAL; firstType: RecordPtr): ADDRESS;
  184. VAR p : ArrayPtr;
  185. BEGIN
  186. SCANNER.Allocate(p, (paramCount+2)*2);
  187. p^[0] := paramCount;
  188. p^[1] := resultKind;
  189. p^[2] := firstType;
  190. lastParamList := p;
  191. RETURN p
  192. END MakeParamList;
  193. PROCEDURE DeclareStandardNames;
  194. BEGIN
  195. curScopeHead := baseScopeHead;
  196. DeclConst("TRUE" ,BooleanType,1,1);
  197. DeclConst("FALSE",BooleanType,0,1);
  198. DeclConst("NIL" ,AddressType ,0,1);
  199. DeclProc("READ" , 0);
  200. DeclProc("READLN" , 1);
  201. DeclProc("WRITE" , 2);
  202. DeclProc("WRITELN" , 3);
  203. DeclProc("NEW" , 4);
  204. DeclProc("DISPOSE" , 5);
  205. DeclProc("INC" , 6);
  206. DeclProc("DEC" , 7);
  207. DeclProc("INCL" , 8);
  208. DeclProc("EXCL" , 9);
  209. DeclFunc("CARD" , 0, CardType);
  210. DeclFunc("INT" , 1, IntType);
  211. DeclFunc("LONG" , 2, LongintType);
  212. DeclFunc("FLOAT" , 3, RealType);
  213. DeclFunc("ABS" , 4, CardType);
  214. DeclFunc("DOUBLE" , 5, LongrealType);
  215. DeclFunc("ORD" , 6, CardType);
  216. DeclFunc("CHR" , 7, CharType);
  217. DeclFunc("ODD" , 8, BooleanType);
  218. DeclFunc("HIGH" , 9, CardType);
  219. DeclFunc("SIZE" ,11, CardType);
  220. DeclFunc("VAL" ,13, CardType);
  221. DeclFunc("MIN" ,14, CardType);
  222. DeclFunc("MAX" ,15, CardType);
  223. DeclStdProc("CAP" , 6, MakeParamList(1, 0, CharType));
  224. curScopeHead^.word2 := CharType;
  225. DeclStdProc("HALT" , 2, NIL);
  226. DeclStdProc("TRUNC" , 8, MakeParamList(1, 0, RealType));
  227. curScopeHead^.word2 := CardType;
  228. SCANNER.Allocate(stdScopeAnchor, 14);
  229. stdScopeAnchor^.word0 := NIL;
  230. stdScopeAnchor^.word1 := curScopeHead;
  231. END DeclareStandardNames;
  232. PROCEDURE DeclareSystemModule;
  233. VAR p: RecordPtr;
  234. BEGIN
  235. curScopeHead := savedScopeHead;
  236. DeclConst("IORESULT" , CardType, 0300H, 4); curScopeHead^.word3 := BITSET{8}; (* was 256 *)
  237. DeclConst("HLRESULT" , CardType, 0302H, 4); curScopeHead^.word3 := BITSET{8}; (* was 256 *)
  238. DeclConst("BADOVERLAY" , NIL , 1, 2);
  239. DeclConst("OUTOFMEMORY" , NIL , 5, 2);
  240. DeclConst("REALOVERFLOW" , NIL ,11, 2);
  241. DeclConst("OVERFLOW" , NIL ,12, 2);
  242. DeclProc("CODE" ,10);
  243. DeclFunc("ADR" ,10, AddressType);
  244. DeclFunc("TSIZE" ,12, CardType);
  245. DeclStdProc("BREAK" , 0, NIL);
  246. DeclStdProc("TRANSFER" ,15, MakeParamList(2, 3, addressAlias)); lastParamList^[3] := addressAlias;
  247. DeclStdProc("IOTRANSFER",16, MakeParamList(3, 6, AddressType));
  248. lastParamList^[3] := addressAlias;
  249. lastParamList^[4] := addressAlias;
  250. DeclStdProc("NEWPROCESS",17, MakeParamList(4, 1, addressAlias));
  251. lastParamList^[3] := CardType;
  252. lastParamList^[4] := AddressType;
  253. lastParamList^[5] := ProcType;
  254. p := MakeParamList(2, 0, WordType);
  255. lastParamList^[3] := WordType;
  256. DeclStdProc("BDOS" , 1, p);
  257. DeclStdProc("BIOS" ,18, p);
  258. DeclStdProc("MOVE" ,19, MakeParamList(3, 0, CardType));
  259. lastParamList^[3] := AddressType;
  260. lastParamList^[4] := AddressType;
  261. DeclStdProc("FILL" ,20, MakeParamList(3, 0, ByteType));
  262. lastParamList^[3] := CardType;
  263. lastParamList^[4] := AddressType;
  264. DeclStdProc("INP" ,21, MakeParamList(1, 0, WordType)); curScopeHead^.word2 := CardType;
  265. DeclStdProc("OUT" ,22, p);
  266. SCANNER.Allocate(systemScopeDesc, 14);
  267. systemScopeDesc^.word0 := stdScopeAnchor;
  268. systemScopeDesc^.word1 := curScopeHead;
  269. curScopeHead := NIL;
  270. DeclStdProc("SYSTEM" , 0, NIL);
  271. curScopeHead^.word4 := 6;
  272. curScopeHead^.word3 := BITSET{0,6,10}; (* was 1089 *)
  273. curScopeHead^.high := systemScopeDesc^.word1;
  274. systemModule := curScopeHead;
  275. END DeclareSystemModule;
  276. PROCEDURE DeclareStorageModule;
  277. VAR p: RecordPtr;
  278. BEGIN
  279. curScopeHead := NIL;
  280. allocateSignature := MakeParamList(2,2,CardType);
  281. lastParamList^[3] := AddressType;
  282. p := MakeParamList(1,1,AddressType);
  283. DeclStdProc("ALLOCATE" , 10, allocateSignature);
  284. DeclStdProc("DEALLOCATE", 11, allocateSignature);
  285. DeclStdProc("MARK" , 12, p);
  286. DeclStdProc("RELEASE" , 13, p);
  287. DeclStdProc("FREEMEM" , 14, NIL);
  288. curScopeHead^.word2 := CardType;
  289. SCANNER.Allocate(storageScopeDesc, 14);
  290. storageScopeDesc^.word0 := stdScopeAnchor;
  291. storageScopeDesc^.word1 := curScopeHead;
  292. curScopeHead := NIL;
  293. DeclStdProc("STORAGE" , 0, NIL);
  294. curScopeHead^.word4 := 6;
  295. curScopeHead^.word3 := BITSET{0,6,10}; (* was 1089 *)
  296. curScopeHead^.high := storageScopeDesc^.word1;
  297. storageModule := curScopeHead;
  298. END DeclareStorageModule;
  299. (* $[- retain procedure name because of exception handler *)
  300. PROCEDURE OpenSourceAndOutput;
  301. CONST DRVROVEC = 29;
  302. VAR cmdToken : ARRAY [0..2] OF CHAR;
  303. driveCh : CHAR;
  304. BEGIN
  305. SCANNER.srcFile := NIL;
  306. SCANNER.codeFile := NIL;
  307. Texts.ReadString(ComLine.commandLine, cmdToken);
  308. IF NOT Files.Open(SCANNER.srcFile, ComLine.inName) THEN
  309. Terminal.WriteString(ComLine.inName);
  310. Terminal.WriteString(" not found.");
  311. Terminal.WriteLn;
  312. ELSE
  313. ComLine.RedirectOutput;
  314. BDOS(DRVROVEC, 0);
  315. IF ORD(ComLine.inName[0])-ORD('A') IN BITSET(IORESULT) THEN Files.ResetSys() END;
  316. ComLine.outName := ComLine.inName;
  317. SCANNER.ChangeEx(ComLine.outName, "@@@", TRUE);
  318. Texts.ReadString(ComLine.commandLine, cmdToken);
  319. IF (cmdToken[1] = ':') AND (cmdToken[2] = 0C) THEN
  320. driveCh := CAP(cmdToken[0]);
  321. IF ORD(driveCh)-ORD('A') <= 15 THEN ComLine.outName[0] := driveCh END;
  322. END;
  323. Files.Create(SCANNER.codeFile, ComLine.outName);
  324. Files.NoTrailer(SCANNER.srcFile);
  325. Files.ReadByte(SCANNER.srcFile, driveCh);
  326. Files.SetPos(SCANNER.srcFile, LONG(0));
  327. END;
  328. EXCEPTION Files.UseError:
  329. Files.ResetSys();
  330. Files.Create(SCANNER.codeFile, ComLine.outName);
  331. END OpenSourceAndOutput;
  332. (* $[+ remove procedure names *)
  333. PROCEDURE InitCompiler;
  334. VAR cmdToken: ARRAY [0..2] OF CHAR;
  335. optCode : CARDINAL;
  336. compilerOptions[0348H] : BITSET;
  337. BEGIN
  338. nativeCodeRequested := FALSE;
  339. compilationActive := TRUE;
  340. baseScopeHead := NIL;
  341. savedScopeHead := NIL;
  342. InitOperatorTable;
  343. InitCharClasses;
  344. InitKeywordTable;
  345. DeclarePredefinedTypes;
  346. DeclareStandardNames;
  347. DeclareSystemModule;
  348. DeclareStorageModule;
  349. SCANNER.scanOpt := compilerOptions;
  350. rangeCheckEnabled := 2 IN SCANNER.scanOpt;
  351. Texts.ReadString(ComLine.commandLine, cmdToken);
  352. IF cmdToken[0] = '%' THEN
  353. optCode := ORD(CAP(cmdToken[1])) - ORD('L');
  354. IF optCode <= 15 THEN INCL(SCANNER.scanOpt, optCode) END;
  355. END;
  356. ERRORS.doSymtabRollback := FALSE;
  357. SCANNER.Allocate(SYMTAB.moduleTable, 170);
  358. SCANNER.Allocate(SYMTAB.modStage, 170);
  359. SCANNER.Allocate(SYMTAB.scopeChain, 34);
  360. SCANNER.InitScan;
  361. SCANNER.OpenScop(stdScopeAnchor, 0);
  362. IF 5 IN SCANNER.scanOpt THEN Texts.WriteCard(3, FREEMEM(), 5) END;
  363. END InitCompiler;
  364. END COMPILER.