// symtab-s.txt

//	  for som v2.3    21 Jan 2006
//	  one hash table + local shadow buffer
//	  search and insert O(1), no linear search for local

// interface:
//    install str	  -- search and insert string in symtab
//                    -- return index to table
//    enterLocal idx  -- enter local, shadow gvar if exist
//					  -- error if duplicate
//	  clearLocal	  -- clear local table
//    init_symtab

//    alloc iden string from a fixed array "nmstr"
//    to separate compiler/user allocation	12 June 2006
//
//    Celebrating H.M.King 60 years accend to the throne.

//    separate symtab to htab and symtab 	24 Aug 2007

enum
    2003 htabsize	  // a prime number
enum
    1000 tablesize
enum
    5000 namesize

// sym-entry is   (name,type,ref,arity,lv)
// local sym use: (name,type,ref,gv,lv)

enum
    5 elesize

// access functions by index

: getName a = symtab[a]
: getType a = symtab[a+1]
: getRef a = symtab[a+2]
: getArity a = symtab[a+3]
: getLv a = symtab[a+4]

: setName a nm = symtab[a] = nm
: setType a v = symtab[a+1] = v
: setRef a v = symtab[a+2] = v
: setArity a v = symtab[a+3] = v
: setLv a v = symtab[a+4] = v

to init_symtab | i k =
    htab = array htabsize
    symtab = array (tablesize*elesize)
    nmstr = array namesize	// identifier string
    Namep = 0				// pointer to nmstr
    freeSym = 0				// pointer to symtab
    lvlis = array MAXLV		// list of lv
    clearlis lvlis
    Nlv = 0

// hast string to v  0..tablesize-1
to hash s1 | i v a =
    i = 0
    v = 0
    a = s1[i]
    while a != 0
        v = v + a	// add all int
        i = i + 1
        a = s1[i]
    if (v < 0) v = 0 - v
    v % htabsize

// alloc space for string from nmstr[]
to makename nm | s =
    s = Namep
    Namep = Namep + (strlen nm) + 1
    if Namep >= namesize
        seterror "string space in symbol table is full"
    s = nmstr + s	// pointer to name string
    strcpy s nm
    s

// alloc a space in symtab
to newSym nm ty | k =
    freeSym = freeSym + elesize
    if freeSym >= (tablesize*elesize)
        seterror "symbol table full (symtab)"
    k = freeSym
    setName k nm
    setType k ty
    k

// hash with linear probe
//   if new, insert name, return index
//   i 0..tablesize-1, k point to symtab
to install nm | key i k =
    key = hash nm
    i = key
    while 1
        k = htab[i]
        if k == 0				// new, insert name
            k = newSym (makename nm) tyNEW
            htab[i] = k
            setLv k i			// back pointer to htab
            break
        if streq (getName k) nm	// found
            break
        i = (i+1) % htabsize
        if i == key		// wrap around, impossible
            seterror "symbol table full (htab)"
    k	// return index to symtab

to enterLocal idx | k h =
    Nlv = Nlv + 1
    case getType idx
        tyNEW:
            setType idx tyLOCAL
            setRef idx Nlv
            setArity idx 0		// not shadow
        tyGVAR:					// shadow
            h = getLv idx 		// pointer to htab
            k = newSym (getName idx) tyLOCAL
            setRef k Nlv
            setArity k idx		// point to gv
            htab[h] = k			// htab point here
            idx = k
        else:
            seterror "invalid local (enter)" // duplicate
    addlis lvlis idx

to clearLocal | idx i k =
    for i 1 (sizeoflis lvlis)
        k = lvlis[i]
        setType k tyNEW			// null it
        idx = getArity k
        if idx != 0				// shadow gv
            htab[getLv idx] = idx	// htab to gv
    clearlis lvlis
    Nlv = 0

// list index of export symbol (tyFUNC, tyGVAR)
// return num of sym
to getExportSym ar | k ty n =
    n = 0
    k = elesize
    while k <= freeSym
        ty = getType k
        if (ty == tyFUNC) | (ty == tyGVAR)
            ar[n] = k
            n = n + 1
        k = k + elesize
    n

// exsym = array 200
// nxsym = 0	 num of export sym

// must getExportSym first
//to findName type ref | i a k =
//	a = 0
//	for i 0 nxsym-1
//		k = exsym[i]
//		if ((getType k) == type) & ((getRef k) == ref)
//			a = getName k
//			break
//	a

// nmstr[] has unique symbols (494 for this compiler)
//to dumpName | s n =
//	n = 0
//	s = nmstr
//	while s < (nmstr + Namep)
//		prints s space
//		s = s + (strlen s) + 1
//		n = n + 1
//	nl print n nl

// update value of gvar
to dumpSym | i k type ref =
    fprint FO nxsym fnl
    for i 0 nxsym-1
        k = exsym[i]
        type = getType k
        ref = getRef k
//		if type == tyGVAR
//			setLv k M[ref]
        fprints FO getName k fspace
        fprint FO type fspace
        fprint FO ref fspace
        fprint FO getArity k fspace
        fprint FO getLv k fnl

// End
