/*
 * Bernoulli Compiler
 * Copyright (c) Cornell University
 * Department of Computer Science
 * 
 * Kamen Yotov (kamen@yotov.org)
 * 
 * $Source: C:/CVS/kyotov/kyotov/Research/BC/C/Symbols.cs,v $
 * $Revision: 1.8 $
 * $Date: 2002/08/09 02:35:53 $
 */

using System;
using System.Collections;
using System.Diagnostics;

using BC.Core;
using BC.Core.Exceptions;

namespace BC.C
{
	public enum SymbolType
	{
		Unknown,
		Value,
		Type
	};

	public class Symbols: ICloneable
	{
		Stack s = new Stack();

		public Symbols ()
		{
			OpenNewScope();
		}

		public void Add (string n, bool t)
		{
			if (n != null)
			{
				Hashtable c = (Hashtable)s.Peek();

				if (!c.Contains(n) || !(bool)c[n])
					c[n] = t;
			}
		}

		public void Add (string n)
		{
			Add(n, false);
		}

		public void Typify (string n)
		{
			Hashtable c = (Hashtable)s.Peek();

			Debug.Assert(c.Contains(n));

			c[n] = true;
		}

		public SymbolType Lookup (string n)
		{
			foreach (Hashtable h in s)
				if (h.Contains(n))
					return (bool)h[n] ? SymbolType.Type : SymbolType.Value;

			return SymbolType.Unknown;
		}

		public void OpenNewScope ()
		{
			s.Push(new Hashtable());
		}

		public void CloseScope ()
		{
			s.Pop();
		}

		public int Level
		{
			get
			{
				return s.Count;
			}
		}

		public object Clone ()
		{
			Symbols x = new Symbols();

			ArrayList a = new ArrayList();

			foreach (Hashtable h in s)
				a.Add(h.Clone());

			a.Reverse();

			x.s = new Stack(a);

			return x;
		}
	}
}
