M3TL.MOD 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. IMPLEMENTATION MODULE M3TL; (*NW 7.4.83 / 30.1.86*)
  2. FROM M3DL IMPORT
  3. WordSize, nilval, ObjPtr, Object, ObjClass, StrPtr, Structure, StrForm,
  4. ParPtr, Parameter, PDesc, PDPtr,
  5. KeyPtr, Key, mainmod, sysmod,
  6. undftyp, cardtyp, inttyp, booltyp, chartyp, bitstyp, realtyp,
  7. dbltyp, proctyp, notyp, stringtyp, addrtyp, wordtyp,
  8. ALLOCATE, ResetHeap;
  9. FROM M2S IMPORT id, Diff, Enter, Mark;
  10. VAR obj: ObjPtr;
  11. universe: ObjPtr;
  12. BBtyp: StrPtr;
  13. expo: BOOLEAN;
  14. PROCEDURE FindInScope(id: CARDINAL; root: ObjPtr): ObjPtr;
  15. VAR obj: ObjPtr; d: INTEGER;
  16. BEGIN obj := root;
  17. LOOP IF obj = NIL THEN EXIT END ;
  18. d := Diff(id, obj^.name);
  19. IF d < 0 THEN obj := obj^.left
  20. ELSIF d > 0 THEN obj := obj^.right
  21. ELSE EXIT
  22. END
  23. END ;
  24. RETURN obj
  25. END FindInScope;
  26. PROCEDURE Find(id: CARDINAL): ObjPtr;
  27. VAR obj: ObjPtr;
  28. BEGIN Scope := topScope;
  29. LOOP obj := FindInScope(id, Scope^.right);
  30. IF obj # NIL THEN EXIT END ;
  31. IF Scope^.kind = Module THEN
  32. obj := FindInScope(id, universe^.right); EXIT
  33. END ;
  34. Scope := Scope^.left
  35. END ;
  36. RETURN obj
  37. END Find;
  38. PROCEDURE FindImport(id: CARDINAL): ObjPtr;
  39. VAR obj: ObjPtr;
  40. BEGIN Scope := topScope^.left;
  41. LOOP obj := FindInScope(id, Scope^.right);
  42. IF obj # NIL THEN EXIT END ;
  43. IF Scope^.kind = Module THEN
  44. obj := FindInScope(id, universe^.right); EXIT
  45. END ;
  46. Scope := Scope^.left
  47. END ;
  48. RETURN obj
  49. END FindImport;
  50. PROCEDURE NewObj(id: CARDINAL; cl: ObjClass): ObjPtr;
  51. VAR ob0, ob1: ObjPtr; d: INTEGER;
  52. BEGIN ob0 := topScope; ob1 := ob0^.right; d := 1;
  53. LOOP
  54. IF ob1 # NIL THEN
  55. d := Diff(id, ob1^.name);
  56. IF d < 0 THEN ob0 := ob1; ob1 := ob0^.left
  57. ELSIF d > 0 THEN ob0 := ob1; ob1 := ob0^.right
  58. ELSIF ob1^.class = Temp THEN (*export*)
  59. (*change variant*) ob1^.exported := TRUE;
  60. topScope^.last^.next := ob1; topScope^.last := ob1; EXIT
  61. ELSE (*double def*)
  62. Mark(100); ob0 := ob1; ob1 := ob0^.right
  63. END
  64. ELSE (*insert new object*) ALLOCATE(ob1, SIZE(Object));
  65. IF d < 0 THEN ob0^.left := ob1 ELSE ob0^.right := ob1 END ;
  66. ob1^.left := NIL; ob1^.right := NIL; ob1^.next := NIL;
  67. IF cl # Temp THEN
  68. topScope^.last^.next := ob1; topScope^.last := ob1
  69. END ;
  70. ob1^.exported := FALSE; EXIT
  71. END
  72. END ;
  73. WITH ob1^ DO
  74. name := id; typ := undftyp; class := cl;
  75. CASE cl OF
  76. Header, Const, Typ, Var, Field, Temp: |
  77. Proc: firstParam := NIL; firstLocal := NIL;
  78. ALLOCATE(pd, SIZE(PDesc)) |
  79. Code: firstArg := NIL; cd := NIL |
  80. Module: firstObj := NIL; root := NIL; key := NIL; typ := notyp
  81. END
  82. END ;
  83. RETURN ob1
  84. END NewObj;
  85. PROCEDURE NewStr(frm: StrForm): StrPtr;
  86. VAR str: StrPtr;
  87. BEGIN ALLOCATE(str, SIZE(Structure));
  88. WITH str^ DO
  89. strobj := NIL; size := 0; ref := 0; form := frm;
  90. CASE frm OF
  91. Undef .. Enum, Opaque: |
  92. Range: RBaseTyp := undftyp; min := 0; max := 0 |
  93. Pointer: PBaseTyp := undftyp |
  94. Set: SBaseTyp := undftyp |
  95. Array: ElemTyp := undftyp; IndexTyp := undftyp |
  96. Record: firstFld := NIL |
  97. ProcTyp: firstPar := NIL; resTyp := NIL
  98. END
  99. END ;
  100. RETURN str
  101. END NewStr;
  102. PROCEDURE NewImp(scope, obj: ObjPtr);
  103. VAR ob0, ob1, ob1L, ob1R: ObjPtr; d: INTEGER;
  104. BEGIN ob0 := scope; ob1 := ob0^.right; d := 1;
  105. LOOP
  106. IF ob1 # NIL THEN
  107. d := Diff(obj^.name, ob1^.name);
  108. IF d < 0 THEN ob0 := ob1; ob1 := ob1^.left
  109. ELSIF d > 0 THEN ob0 := ob1; ob1 := ob1^.right
  110. ELSIF ob1^.class = Temp THEN (*export*)
  111. ob1L := ob1^.left; ob1R := ob1^.right;
  112. ob1^ := obj^; ob1^.exported := TRUE;
  113. ob1^.left := ob1L; ob1^.right := ob1R; EXIT
  114. ELSE Mark(100); EXIT
  115. END
  116. ELSE (*insert copy of imported object*)
  117. ALLOCATE(ob1, SIZE(Object)); ob1^ := obj^;
  118. IF d < 0 THEN ob0^.left := ob1 ELSE ob0^.right := ob1 END ;
  119. ob1^.left := NIL; ob1^.right := NIL; ob1^.exported := FALSE;
  120. IF (obj^.class = Typ) & (obj^.typ^.form = Enum) THEN
  121. (*import enumeration constants too*)
  122. ob0 := obj^.typ^.ConstLink;
  123. WHILE ob0 # NIL DO
  124. NewImp(scope, ob0); ob0 := ob0^.conval.prev
  125. END
  126. END ;
  127. EXIT
  128. END
  129. END
  130. END NewImp;
  131. PROCEDURE NewPar(ident: CARDINAL; isvar: BOOLEAN; last: ParPtr): ParPtr;
  132. VAR par: ParPtr;
  133. BEGIN ALLOCATE(par, SIZE(Parameter));
  134. par^.name := ident; par^.varpar := isvar; par^.next := last;
  135. RETURN par
  136. END NewPar;
  137. PROCEDURE NewScope(cl: ObjClass);
  138. VAR hd: ObjPtr;
  139. BEGIN ALLOCATE(hd, SIZE(Object));
  140. WITH hd^ DO
  141. name := 0; typ := NIL; class := Header;
  142. left := topScope; right := NIL; last := hd; next := NIL; kind := cl
  143. END ;
  144. topScope := hd
  145. END NewScope;
  146. PROCEDURE CloseScope;
  147. BEGIN topScope := topScope^.left
  148. END CloseScope;
  149. PROCEDURE CheckUDP(obj, node: ObjPtr);
  150. (*obj is newly defined type; check for undefined forward references
  151. pointing to this new type by traversing the tree*)
  152. BEGIN
  153. IF node # NIL THEN
  154. IF (node^.class = Typ) & (node^.typ^.form = Pointer) &
  155. (node^.typ^.PBaseTyp = undftyp) &
  156. (Diff(node^.typ^.BaseId, obj^.name) = 0) THEN
  157. node^.typ^.PBaseTyp := obj^.typ
  158. END ;
  159. CheckUDP(obj, node^.left); CheckUDP(obj, node^.right)
  160. END
  161. END CheckUDP;
  162. PROCEDURE MarkHeap;
  163. BEGIN ALLOCATE(topScope^.heap, 0); topScope^.name := id
  164. END MarkHeap;
  165. PROCEDURE ReleaseHeap;
  166. BEGIN ResetHeap(topScope^.heap); id := topScope^.name
  167. END ReleaseHeap;
  168. PROCEDURE InitTableHandler;
  169. BEGIN topScope := universe; mainmod^.firstObj := NIL; ReleaseHeap
  170. END InitTableHandler;
  171. PROCEDURE EnterTyp(VAR str: StrPtr; name: ARRAY OF CHAR;
  172. frm: StrForm; sz: CARDINAL);
  173. BEGIN obj := NewObj(Enter(name), Typ); str := NewStr(frm);
  174. obj^.typ := str; str^.strobj := obj; str^.size := sz;
  175. obj^.exported := expo
  176. END EnterTyp;
  177. PROCEDURE EnterProc(name: ARRAY OF CHAR; num: CARDINAL);
  178. BEGIN obj := NewObj(Enter(name), Code);
  179. obj^.typ := notyp; obj^.cnum := num; obj^.exported := expo
  180. END EnterProc;
  181. BEGIN topScope := NIL; Scope := NIL;
  182. NewScope(Module); universe := topScope;
  183. undftyp := NewStr(Undef); undftyp^.size := 1;
  184. notyp := NewStr(Undef); notyp^.size := 0;
  185. stringtyp := NewStr(String); stringtyp^.size := 1;
  186. BBtyp := NewStr(Range); (*Bitset Basetyp*)
  187. ALLOCATE(mainmod, SIZE(Object));
  188. WITH mainmod^ DO
  189. class := Module; modno := 0; typ := notyp; next := NIL; exported := FALSE;
  190. ALLOCATE(key, SIZE(Key))
  191. END ;
  192. (*initialization of module SYSTEM*) expo := TRUE;
  193. EnterTyp(wordtyp, "WORD", Undef, 1);
  194. EnterTyp(addrtyp, "ADDRESS", Card, 1);
  195. EnterProc("TSIZE", 8);
  196. EnterProc("ADR", 10);
  197. EnterProc("LONG", 20);
  198. ALLOCATE(sysmod, SIZE(Object));
  199. WITH sysmod^ DO
  200. name := Enter("SYSTEM"); class := Module; modno := 0; exported := FALSE;
  201. left := NIL; right := NIL; next := NIL;
  202. firstObj := topScope^.next; root := topScope^.right;
  203. ALLOCATE(key, SIZE(Key))
  204. END ;
  205. (*reset header*)
  206. WITH topScope^ DO
  207. next := NIL; right := NIL; last := topScope
  208. END ;
  209. expo := FALSE;
  210. (*initialization of Universe*)
  211. EnterTyp(realtyp, "REAL", Real, 2);
  212. obj := NewObj(Enter("NIL"), Const);
  213. obj^.typ := addrtyp; obj^.conval.C := nilval;
  214. EnterTyp(chartyp, "CHAR", Char, 1);
  215. EnterTyp(booltyp, "BOOLEAN", Bool, 1);
  216. obj := NewObj(Enter("FALSE"), Const);
  217. obj^.typ := booltyp; obj^.conval.B := FALSE;
  218. obj := NewObj(Enter("TRUE"), Const);
  219. obj^.typ := booltyp; obj^.conval.B := TRUE;
  220. EnterTyp(inttyp, "INTEGER", Int, 1);
  221. EnterTyp(cardtyp, "CARDINAL", Card, 1);
  222. EnterTyp(bitstyp, "BITSET", Set, 1); bitstyp^.SBaseTyp := BBtyp;
  223. WITH BBtyp^ DO
  224. RBaseTyp := cardtyp; min := 0; max := WordSize-1; size := 1
  225. END ;
  226. EnterTyp(dbltyp, "LONGINT", Double, 2);
  227. EnterProc("INC", 15);
  228. EnterProc("DEC", 16);
  229. EnterProc("CAP", 3);
  230. EnterProc("ABS", 2);
  231. EnterProc("CHR", 14);
  232. EnterProc("MIN", 11);
  233. EnterProc("MAX", 12);
  234. EnterProc("ODD", 5);
  235. EnterProc("ORD", 6);
  236. EnterProc("INCL", 17);
  237. EnterProc("HALT", 1);
  238. EnterProc("EXCL", 18);
  239. EnterProc("HIGH", 13);
  240. EnterProc("SIZE", 8);
  241. EnterProc("VAL", 19);
  242. EnterProc("FLOAT", 4);
  243. EnterProc("TRUNC", 7);
  244. EnterTyp(proctyp, "PROC", ProcTyp, 1);
  245. proctyp^.firstPar := NIL; proctyp^.resTyp := notyp;
  246. MarkHeap
  247. END M3TL.