// 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
//    small update for som v5               25 Oct 2009

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 = 1				// pointer to nmstr
	freeSym = 0				// pointer to symtab
	lvlis = array MAXLV		// list of lv
	clearlis lvlis
	Nlv = 0
	// make anonymous symbol, idx = 0, 25 Oct 2009
	nmstr[0] = 0			// null name
	setName 0 0
	setType 0 tySP			// type special
	setLv 0 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


