@Override
	public void readInternal(Environment env) throws IOException, TypeException {
		
		readChar(env);
		if (!(env.peek() instanceof VChar))	{
			return;
		}
		
		int ch = ((VChar)env.peek()).getChar();
		if (ch == -1)	{
			// End of stream, send the Terminator
			env.pop();
			env.pushReader("terminator");
			env.pushOp("read");
			return;
		}
		
		System.err.println("r(Discriminator): " + Character.toString((char) ch));
		
		IValue v = env.getBoundObject(Character.toString((char)ch));
		if (null != v && v instanceof IReader)	{
			if (!(v instanceof Ignore))	{
				// HACK: Shouldn't have to do a reader-specific test here
				// TODO: Have each reader configure whether or not it wants the first
				// character
				env.pop();
			}
			env.pushReader((IReader)v);
			env.pushOp("read");
		} else if (null != v && v instanceof VMacro)	{
			// We don't push the macro itself, instead we push the symbol
			// bound to the macro and let the stack evaluator do its job
			VSymbol sym = new VSymbol(Character.toString((char)ch));
			env.pop();
			env.push(sym);
			env.evaluateStack();
		} else if (null != v && v instanceof VWhitespace)	{
			env.pop();
			env.pushReader("discriminator");
			env.pushOp("read");
		} else {
			env.pushReader("symbol");
			env.pushOp("read");	
		}
	}