CompilerSymbols.mod 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. IMPLEMENTATION MODULE CompilerSymbols ;
  2. (* Symbol table and name scoping: storage, insertion, visibility-aware lookup,
  3. duplicate detection, and hiding a finished procedure's locals. The lexer's
  4. current word and lexical level live here because Search and NewSym are the
  5. only users that define their meaning. *)
  6. FROM CompilerShared IMPORT MaxName, Err, ECompOvf, EUnknown ;
  7. FROM CompilerSource IMPORT Upper ;
  8. FROM CompilerUtil IMPORT NameEq, CopyStr ;
  9. PROCEDURE CopyWord (name : ARRAY OF CHAR) ;
  10. (* stash current word into global wrd (uppercased) *)
  11. VAR i : CARDINAL ;
  12. BEGIN
  13. i := 0 ;
  14. LOOP
  15. IF i > HIGH (name) THEN
  16. wrd [i] := 0C ;
  17. RETURN
  18. END ;
  19. IF i > MaxName THEN
  20. wrd [MaxName] := 0C ;
  21. RETURN
  22. END ;
  23. IF name [i] = 0C THEN
  24. wrd [i] := 0C ;
  25. RETURN
  26. END ;
  27. wrd [i] := Upper (name [i]) ;
  28. INC (i)
  29. END
  30. END CopyWord ;
  31. PROCEDURE SaveWord (VAR dst : ARRAY OF CHAR) ;
  32. (* copy wrd into dst *)
  33. VAR i : CARDINAL ;
  34. BEGIN
  35. i := 0 ;
  36. LOOP
  37. IF i > HIGH (dst) THEN
  38. dst [HIGH (dst)] := 0C ;
  39. RETURN
  40. END ;
  41. IF i > MaxName THEN
  42. dst [MaxName] := 0C ;
  43. RETURN
  44. END ;
  45. dst [i] := wrd [i] ;
  46. IF wrd [i] = 0C THEN
  47. RETURN
  48. END ;
  49. INC (i)
  50. END
  51. END SaveWord ;
  52. PROCEDURE NewSym (name : ARRAY OF CHAR ; tag : CARDINAL ;
  53. cls, size, elem, off : CARDINAL ; v : LONGINT ;
  54. local : BOOLEAN) : CARDINAL ;
  55. VAR e : SymEntry ;
  56. BEGIN
  57. IF symTop >= MaxSym THEN
  58. Err (ECompOvf) ;
  59. RETURN 0
  60. END ;
  61. CopyWord (name) ;
  62. CopyStr (e.name, wrd) ;
  63. e.tag := tag ;
  64. e.cls := cls ;
  65. e.size := size ;
  66. e.elem := elem ;
  67. e.off := off ;
  68. e.lval := v ;
  69. e.lo := 0 ;
  70. e.hi := 0 ;
  71. e.fldFirst := 0 ;
  72. e.fldLast := 0 ;
  73. e.arrIdx := 0 ;
  74. e.parmFirst := 0 ;
  75. e.parmCount := 0 ;
  76. e.isKbd := FALSE ;
  77. e.isPort := FALSE ;
  78. e.isVar := FALSE ;
  79. e.level := lexnest ;
  80. e.local := local ;
  81. e.parent := 0 ;
  82. e.staticOff := 0 ;
  83. e.resvar := 0 ;
  84. e.goPos := 0 ;
  85. e.defnd := FALSE ;
  86. e.fwd := FALSE ;
  87. symtab [symTop] := e ;
  88. INC (symTop) ;
  89. RETURN symTop - 1
  90. END NewSym ;
  91. PROCEDURE Search (nm : ARRAY OF CHAR ; VAR idx : CARDINAL) : BOOLEAN ;
  92. (* find nm among symbols visible at the current lexical level *)
  93. VAR p : CARDINAL ;
  94. BEGIN
  95. CopyWord (nm) ;
  96. p := symTop ;
  97. WHILE p > 0 DO
  98. DEC (p) ;
  99. IF symtab [p].level <= lexnest THEN
  100. IF NameEq (symtab [p].name, wrd) THEN
  101. idx := p ;
  102. RETURN TRUE
  103. END
  104. END
  105. END ;
  106. RETURN FALSE
  107. END Search ;
  108. PROCEDURE DupTest (nm : ARRAY OF CHAR) ;
  109. (* A name may be declared twice only in the SAME scope. This used to reject
  110. any name Search could see, so a parameter could not shadow a global - legal
  111. ISO Pascal, and CALC.INC's `procedure IBMCh(var Ch: Char)' does exactly
  112. that (`Ch' is a global). Same-level duplicates stay errors: two parameters
  113. in one list, two locals, or two globals. *)
  114. VAR i : CARDINAL ;
  115. BEGIN
  116. IF Search (nm, i) THEN
  117. IF symtab [i].level = lexnest THEN
  118. Err (EUnknown)
  119. END
  120. END
  121. END DupTest ;
  122. PROCEDURE HideLocals (from : CARDINAL) ;
  123. (* Make every symbol from index `from' up invisible to everything outside the
  124. procedure that declared it.
  125. Search accepts a symbol when its level is <= lexnest, and every procedure
  126. body is compiled at the same depth (lexnest 1), so a finished procedure's
  127. parameters stayed visible to the NEXT procedure: a second `a : integer'
  128. was a duplicate (err 41) and an unqualified `a' inside procedure two read
  129. procedure one's argument. Level 0FFFFH fails `level <= lexnest' at every
  130. depth a later procedure can be at, and by the time this runs the body that
  131. could still legitimately see them is finished.
  132. The symbols are relabelled, not popped: symtab[old].resvar holds an INDEX,
  133. and a function's result variable is one of the entries being hidden. *)
  134. VAR p : CARDINAL ;
  135. BEGIN
  136. p := from ;
  137. WHILE p < symTop DO
  138. symtab [p].level := 0FFFFH ;
  139. INC (p)
  140. END
  141. END HideLocals ;
  142. END CompilerSymbols.