// ResistSym.bcpl -- symbol table management // Last modified November 6, 1979 3:05 PM external [ // outgoing procedures CreateSymbolTable; EnumerateSymbolTable; MustLookupSymbol LookupSymbol; DefineSymbol; InsertSymbol; LookupOrDefineSymbol SymbolsObject; SymbolsString; SymbolsType ObjectsSymbol; ObjectsString; ObjectsLength; ObjectsType // incoming procedures Allocate; Zero; MoveBlock; CallSwat ] // --------------------------------------------------------------------------- structure String: [ length byte; char^1,1 byte ] // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- structure ST: // Symbol Table // --------------------------------------------------------------------------- [ lenHT word zone word numSymbols word hashTable^0,0 word ] // --------------------------------------------------------------------------- structure ObjHdr: // --------------------------------------------------------------------------- [ length bit 6 // length of object objOffset bit 5 // offset of object relative to symbol type bit 5 // type of object ] // --------------------------------------------------------------------------- structure Symbol: // --------------------------------------------------------------------------- [ next word string @String objHdr @ObjHdr // object ] manifest objOffset1 = (offset Symbol.string + size ObjHdr)/16 +1 // --------------------------------------------------------------------------- let CreateSymbolTable(lenHT, zone) = valof // --------------------------------------------------------------------------- // Creates symbol table with hash table length lenHT, allocating it from zone, // and returns a pointer to it. All symbols subsequently inserted into // the table will also be allocated from zone. [ let lenST = (offset ST.hashTable^lenHT)/16 let st = Allocate(zone, lenST) Zero(st, lenST) st>>ST.lenHT = lenHT st>>ST.zone = zone resultis st ] // --------------------------------------------------------------------------- and EnumerateSymbolTable(st, type, Proc, arg) be // --------------------------------------------------------------------------- // Calls Proc(object, arg) for each symbol of type type in st. [ for hash = 0 to st>>ST.lenHT-1 do [ let symbol = st>>ST.hashTable^hash while symbol ne 0 do [ let object = SymbolsObject(symbol) if type eq (object-1)>>ObjHdr.type then Proc(object, arg) symbol = symbol>>Symbol.next ] ] ] // --------------------------------------------------------------------------- and LookupOrDefineSymbol(st, string, type, object, lenObject; numargs na) = valof // --------------------------------------------------------------------------- // Looks up string in st and defines a symbol for it if not already present. [ let symbol = LookupSymbol(st, string) if symbol ne 0 resultis symbol resultis InsertSymbol(st, string, type, object, (na ge 5? lenObject, 0)) ] // --------------------------------------------------------------------------- and MustLookupSymbol(st, string) = valof // --------------------------------------------------------------------------- // Looks up string in st and returns pointer to symbol. // Calls Swat if not found. [ let symbol = LookupSymbol(st, string) if symbol eq 0 then CallSwat("Symbol not found: ", string) resultis symbol ] // --------------------------------------------------------------------------- and LookupSymbol(st, string) = valof // --------------------------------------------------------------------------- // Looks up string in st and returns pointer to symbol. // Returns zero if not found. [ let symbol = st>>ST.hashTable^(Hash(st, string)) while symbol ne 0 do [ if valof [ if string>>String.length ne symbol>>Symbol.string.length resultis false for i = 1 to string>>String.length do if string>>String.char^i ne symbol>>Symbol.string.char^i then resultis false resultis true ] resultis symbol symbol = symbol>>Symbol.next ] resultis 0 ] // --------------------------------------------------------------------------- and DefineSymbol(st, string, type, object, lenObject; numargs na) = valof // --------------------------------------------------------------------------- // Inserts string into st as a symbol of type type, // along with a copy of object whose length // is lenObject, and returns a pointer to the symbol. // Calls Swat if the symbol is already defined. [ if LookupSymbol(st, string) ne 0 then CallSwat("Symbol already defined: ", string) resultis InsertSymbol(st, string, type, object, (na ge 5? lenObject, 0)) ] // --------------------------------------------------------------------------- and InsertSymbol(st, string, type, object, lenObject; numargs na) = valof // --------------------------------------------------------------------------- // Inserts string into st as a symbol of type type, // along with a copy of object whose length // is lenObject, and returns a pointer to the symbol. // Makes no check for duplicate definitions. [ if na ls 5 then lenObject = 0 let objOffset = objOffset1 + string>>String.length rshift 1 let symbol = Allocate(st>>ST.zone, objOffset + lenObject) let hash = Hash(st, string) symbol>>Symbol.next = st>>ST.hashTable^hash st>>ST.hashTable^hash = symbol MoveBlock(lv symbol>>Symbol.string, string, string>>String.length rshift 1 +1) let objHdr = symbol+objOffset-1 objHdr>>ObjHdr.length = lenObject objHdr>>ObjHdr.objOffset = objOffset objHdr>>ObjHdr.type = type MoveBlock(symbol+objOffset, object, lenObject) st>>ST.numSymbols = st>>ST.numSymbols+1 resultis symbol ] // --------------------------------------------------------------------------- and SymbolsString(symbol) = lv symbol>>Symbol.string // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and SymbolsObject(symbol) = // --------------------------------------------------------------------------- symbol + objOffset1 + symbol>>Symbol.string.length rshift 1 // --------------------------------------------------------------------------- and SymbolsType(symbol) = (SymbolsObject(symbol)-1)>>ObjHdr.type // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and ObjectsSymbol(object) = object - (object-1)>>ObjHdr.objOffset // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and ObjectsString(object) = SymbolsString(ObjectsSymbol(object)) // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and ObjectsLength(object) = (object-1)>>ObjHdr.length // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and ObjectsType(object) = (object-1)>>ObjHdr.type // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and Hash(st, string) = valof // --------------------------------------------------------------------------- [ let hash = 0 for i = 1 to string>>String.length do hash = AccumulateHash(hash, string>>String.char^i) resultis hash rem st>>ST.lenHT ] // --------------------------------------------------------------------------- and AccumulateHash(hash, char) = valof // --------------------------------------------------------------------------- // hash _ (2*(hash+char)) mod (2^15-1) [ AccumulateHash = table [ 123120B // addzl 1 0 105142B // movol 0 1 szc 121620B // inczr 1 0 1401B // jmp 1 3 ] resultis AccumulateHash(hash, char) ]