// symtab-s.txt

//	  for som v2.3    21 Jan 2006

// interface:
//    search str	  -- search and insert string in symname
//                    -- return index to table, if new attr=0
//    enterLocal str  -- enter local at the end of table
//					  -- error if duplicate
//    init_symtab

enum
	1009 tablesize	  // a prime number
enum
	64 localsize

// symentry is (name,type,ref,arity,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 =
	symtab = array (tablesize+localsize+1)*elesize
	Nlv = 0
	k = 0
	for i 0 tablesize-1		// zero symtab name
		setName k 0
		k = k + elesize

// 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 % tablesize

to dumpSym | i k nm =
	prints "symbol table" nl
	k = 0
	for i 0 tablesize-1
		nm = getName k
		if nm != 0
			prints nm space
			print (getType k) space
			print (getRef k) nl
		k = k + elesize

to dumpLocal | i k nm =
	prints "local symbol" nl
	k = (tablesize+1)*elesize
	for i 1 Nlv
		nm = getName k
		if nm != 0
			prints nm  print (getRef k) nl
		k = k + elesize

// hash with linear probe
//   if new, insert name, return index
//   i 0..tablesize-1, k = i*elesize
to install nm | key i k nm2 =
	key = hash nm
	i = key
	while 1
		k = i * elesize
		nm2 = getName k
		if nm2 == 0		// not found, insert name
			nm2 = array ((strlen nm) + 1)
			strcpy nm2 nm
			setName k nm2
			setType k tyNEW
			break
		if streq nm2 nm
			break		// found
		i = (i+1) % tablesize
		if i == key		// wrap around
			seterror "symbol table full" // impossible case
	k	// return index

to enterLocal nm | i k nm2 =
	k = (tablesize+1)*elesize
	for i 1 Nlv
		if streq (getName k) nm
			seterror "duplicate local"
		k = k + elesize
	// k is at the end of table
	Nlv = Nlv + 1
	if Nlv >= localsize
		seterror "local sym overflow"
	nm2 = array ((strlen nm) + 1)
	strcpy nm2 nm
	setName k nm2
	setRef k Nlv
	setType k tyLOCAL

// search local, if not found then search&insert global
to search nm | k i f =
	k = (tablesize+1)*elesize
	f = 0
	for i 1 Nlv			// first, search local
		if streq (getName k) nm
			f = 1
			break
		k = k + elesize
	if f
		getRef k
	else				// if not found, install
		install nm

to enterGlobal name type ref | a =
	a = install name
	setType a type
	setRef a ref

// End
