/*
* $Id: Generator.java,v 1.9 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import anvil.Location;
import anvil.core.Any;
import anvil.core.AnyBindingEnumeration;
import anvil.core.AnyClass;
import anvil.script.compiler.FunctionBase;
import anvil.java.util.BindingEnumeration;
/**
* interface Generator
*
* @author: Jani Lehtim�ki
*/
public class Generator extends StackFrame implements BindingEnumeration
{
protected GeneratorDispatcher _dispatcher;
protected Any _next;
protected boolean _hasmore = true;
protected int _index;
protected boolean _running = false;
protected int _state;
protected Any _wrapper;
public Generator(Context context, Module script, AnyClass self, Function function, int maxlocals, int line)
{
super(script, self, function, maxlocals, line, true);
_escape = context.consumeEscape();
_wrapper = new AnyBindingEnumeration(this);
_dispatcher = ((FunctionBase)_function).getGeneratorDispatcher(context);
}
public String toString()
{
return "generator "+_function+" at state "+_state;
}
public final void detach()
{
//
}
public Any getWrapper()
{
return _wrapper;
}
public int getState()
{
return _state;
}
public void setState(int state)
{
_state = state;
}
public void setClosedState()
{
_state = -1;
}
public boolean hasMoreElements()
{
if (_hasmore) {
Any next = _next;
if (next == null) {
return getNextElement();
} else {
return true;
}
}
return false;
}
public Object nextKey()
{
return Any.create(_index);
}
public Object nextElement()
{
_index++;
try {
return _next;
} finally {
_next = null;
}
}
protected boolean getNextElement()
{
Context context = Context.getInstance();
synchronized(this) {
if (_running) {
throw context.BadState("Generator '"+this+"' is already running");
}
_running = true;
}
try {
context.push(this);
Any next = _dispatcher.execute(context, _self, this);
if (_state == -1) {
_hasmore = false;
}
_next = next;
} finally {
context.pop();
_running = false;
}
return _hasmore;
}
}