/**
* Copyright (c) 2012-2016 André Bargull
* Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms.
*
* <https://github.com/anba/es6draft>
*/
package com.github.anba.es6draft.runtime.types.builtins;
import static com.github.anba.es6draft.runtime.objects.iteration.GeneratorAbstractOperations.GeneratorStart;
import static com.github.anba.es6draft.runtime.types.builtins.OrdinaryFunction.FunctionInitialize;
import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.LexicalEnvironment;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.RuntimeInfo;
import com.github.anba.es6draft.runtime.objects.iteration.GeneratorObject;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.ScriptObject;
/**
* <h1>9 Ordinary and Exotic Objects Behaviours</h1>
* <ul>
* <li>9.2 ECMAScript Function Objects
* </ul>
*/
public final class OrdinaryGenerator extends FunctionObject {
/**
* Constructs a new Generator Function object.
*
* @param realm
* the realm object
*/
protected OrdinaryGenerator(Realm realm) {
super(realm);
}
@Override
protected OrdinaryGenerator allocateNew() {
return FunctionAllocate(getRealm().defaultContext(), getPrototype(), isStrict(), getFunctionKind());
}
/**
* 9.2.1 [[Call]] (thisArgument, argumentsList)
*/
@Override
public GeneratorObject call(ExecutionContext callerContext, Object thisValue, Object... args) {
try {
return (GeneratorObject) getCallMethod().invokeExact(this, callerContext, thisValue, args);
} catch (Throwable e) {
throw FunctionObject.<RuntimeException> rethrow(e);
}
}
/**
* 9.2.1 [[Call]] (thisArgument, argumentsList)
*/
@Override
public GeneratorObject tailCall(ExecutionContext callerContext, Object thisValue, Object... args) throws Throwable {
return (GeneratorObject) getTailCallMethod().invokeExact(this, callerContext, thisValue, args);
}
/**
* 14.4 Generator Function Definitions
* <p>
* 14.4.14 Runtime Semantics: EvaluateBody
*
* <pre>
* GeneratorBody : FunctionBody
* </pre>
*
* @param cx
* the execution context
* @param functionObject
* the generator function object
* @return the generator result value
*/
public static GeneratorObject EvaluateBody(ExecutionContext cx, OrdinaryGenerator functionObject) {
/* steps 1-2 */
GeneratorObject gen = OrdinaryCreateFromConstructor(cx, functionObject, Intrinsics.GeneratorPrototype,
GeneratorObject::new);
/* step 3 */
GeneratorStart(cx, gen, functionObject.getCode());
/* step 4 */
return gen;
}
/* ***************************************************************************************** */
/**
* 9.2.3 FunctionAllocate (functionPrototype, strict [,functionKind] )
*
* @param cx
* the execution context
* @param functionPrototype
* the function prototype
* @param strict
* the strict mode flag
* @param kind
* the function kind
* @return the new generator function object
*/
public static OrdinaryGenerator FunctionAllocate(ExecutionContext cx, ScriptObject functionPrototype,
boolean strict, FunctionKind kind) {
assert kind != FunctionKind.ClassConstructor;
Realm realm = cx.getRealm();
/* steps 1-5 (implicit) */
/* steps 6-9 */
OrdinaryGenerator f = new OrdinaryGenerator(realm);
/* steps 10-14 */
f.allocate(realm, functionPrototype, strict, kind, ConstructorKind.Base);
/* step 15 */
return f;
}
/**
* 9.2.6 GeneratorFunctionCreate (kind, ParameterList, Body, Scope, Strict)
*
* @param cx
* the execution context
* @param kind
* the function kind
* @param function
* the function code
* @param scope
* the lexical environment
* @return the new generator function object
*/
public static OrdinaryGenerator GeneratorFunctionCreate(ExecutionContext cx, FunctionKind kind,
RuntimeInfo.Function function, LexicalEnvironment<?> scope) {
assert function.isGenerator() && kind != FunctionKind.ClassConstructor;
/* step 1 */
ScriptObject functionPrototype = cx.getIntrinsic(Intrinsics.Generator);
/* step 2 */
OrdinaryGenerator f = FunctionAllocate(cx, functionPrototype, function.isStrict(), kind);
/* step 3 */
FunctionInitialize(f, kind, function, scope, cx.getCurrentExecutable());
return f;
}
}