/**
* 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.compiler;
import com.github.anba.es6draft.ast.scope.Name;
import com.github.anba.es6draft.compiler.assembler.MethodName;
import com.github.anba.es6draft.compiler.assembler.Type;
import com.github.anba.es6draft.compiler.assembler.Value;
import com.github.anba.es6draft.runtime.EnvironmentRecord;
/**
*
*/
abstract class BindingOp<ENVREC extends EnvironmentRecord> {
/**
* <h1>8.1.1 Environment Records - CreateImmutableBinding(N, S)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#createImmutableBinding(String, boolean)}
* <p>
* stack: [] {@literal ->} []
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param strict
* {@code true} for strict immutable bindings
* @param mv
* the instruction visitor
*/
abstract void createImmutableBinding(Value<? extends ENVREC> envRec, Name name, boolean strict,
InstructionVisitor mv);
/**
* <h1>8.1.1 Environment Records - CreateMutableBinding(N, D)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#createMutableBinding(String, boolean)}
* <p>
* stack: [] {@literal ->} []
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param deletable
* {@code true} for deletable mutable bindings
* @param mv
* the instruction visitor
*/
abstract void createMutableBinding(Value<? extends ENVREC> envRec, Name name, boolean deletable,
InstructionVisitor mv);
/**
* <h1>8.1.1 Environment Records - InitializeBinding(N, V)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#initializeBinding(String, Object)}
* <p>
* stack: [] {@literal ->} []
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param value
* the initial binding value
* @param mv
* the instruction visitor
*/
abstract void initializeBinding(Value<? extends ENVREC> envRec, Name name, Value<?> value,
InstructionVisitor mv);
/**
* <h1>8.1.1 Environment Records - HasBinding(N)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#hasBinding(String)}
* <p>
* stack: [] {@literal ->} [boolean]
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param mv
* the instruction visitor
*/
abstract void hasBinding(Value<? extends ENVREC> envRec, Name name, InstructionVisitor mv);
/**
* <h1>8.1.1 Environment Records - GetBindingValue(N,S)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#getBindingValue(String, boolean)}
* <p>
* stack: [] {@literal ->} [{@literal <value>}]
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param strict
* {@code true} if in strict-mode code
* @param mv
* the instruction visitor
*/
abstract void getBindingValue(Value<? extends ENVREC> envRec, Name name, boolean strict,
InstructionVisitor mv);
/**
* <h1>8.1.1 Environment Records - SetMutableBinding(N, V, S)</h1>
* <p>
* Emit function call for: {@link EnvironmentRecord#setMutableBinding(String, Object, boolean)}
* <p>
* stack: [] {@literal ->} []
*
* @param envRec
* the environment record
* @param name
* the binding name
* @param value
* the binding value
* @param strict
* {@code true} if in strict-mode code
* @param mv
* the instruction visitor
*/
abstract void setMutableBinding(Value<? extends ENVREC> envRec, Name name, Value<?> value,
boolean strict, InstructionVisitor mv);
/**
* Returns the {@code BindingOp} implementation for the binding name.
*
* @param envRec
* the environment record
* @param name
* the binding name
* @return the {@code BindingOp}
*/
@SuppressWarnings("unchecked")
static <ENV extends EnvironmentRecord, E extends ENV> BindingOp<ENV> of(Value<E> envRec,
Name name) {
return (BindingOp<ENV>) LOOKUP;
}
private static final class Methods {
// class: EnvironmentRecord
static final MethodName EnvironmentRecord_hasBinding = MethodName.findInterface(
Types.EnvironmentRecord, "hasBinding",
Type.methodType(Type.BOOLEAN_TYPE, Types.String));
static final MethodName EnvironmentRecord_createMutableBinding = MethodName.findInterface(
Types.EnvironmentRecord, "createMutableBinding",
Type.methodType(Type.VOID_TYPE, Types.String, Type.BOOLEAN_TYPE));
static final MethodName EnvironmentRecord_createImmutableBinding = MethodName.findInterface(
Types.EnvironmentRecord, "createImmutableBinding",
Type.methodType(Type.VOID_TYPE, Types.String, Type.BOOLEAN_TYPE));
static final MethodName EnvironmentRecord_initializeBinding = MethodName.findInterface(
Types.EnvironmentRecord, "initializeBinding",
Type.methodType(Type.VOID_TYPE, Types.String, Types.Object));
static final MethodName EnvironmentRecord_getBindingValue = MethodName.findInterface(
Types.EnvironmentRecord, "getBindingValue",
Type.methodType(Types.Object, Types.String, Type.BOOLEAN_TYPE));
static final MethodName EnvironmentRecord_setMutableBinding = MethodName.findInterface(
Types.EnvironmentRecord, "setMutableBinding",
Type.methodType(Type.VOID_TYPE, Types.String, Types.Object, Type.BOOLEAN_TYPE));
}
protected final void createImmutableBindingShared(Value<? extends ENVREC> envRec, Name name,
boolean strict, InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.iconst(strict);
mv.invoke(Methods.EnvironmentRecord_createImmutableBinding);
}
protected final void createMutableBindingShared(Value<? extends ENVREC> envRec, Name name,
boolean deletable, InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.iconst(deletable);
mv.invoke(Methods.EnvironmentRecord_createMutableBinding);
}
protected final void initializeBindingShared(Value<? extends ENVREC> envRec, Name name,
Value<?> value, InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.load(value);
mv.invoke(Methods.EnvironmentRecord_initializeBinding);
}
protected final void hasBindingShared(Value<? extends EnvironmentRecord> envRec, Name name,
InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.invoke(Methods.EnvironmentRecord_hasBinding);
}
protected final void getBindingShared(Value<? extends ENVREC> envRec, Name name, boolean strict,
InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.iconst(strict);
mv.invoke(Methods.EnvironmentRecord_getBindingValue);
}
protected final void setMutableBindingShared(Value<? extends ENVREC> envRec, Name name,
Value<?> value, boolean strict, InstructionVisitor mv) {
mv.load(envRec);
mv.aconst(name.getIdentifier());
mv.load(value);
mv.iconst(strict);
mv.invoke(Methods.EnvironmentRecord_setMutableBinding);
}
static final BindingOp<EnvironmentRecord> LOOKUP = new BindingOp<EnvironmentRecord>() {
@Override
void createImmutableBinding(Value<? extends EnvironmentRecord> envRec, Name name,
boolean strict, InstructionVisitor mv) {
createImmutableBindingShared(envRec, name, strict, mv);
}
@Override
void createMutableBinding(Value<? extends EnvironmentRecord> envRec, Name name,
boolean deletable, InstructionVisitor mv) {
createMutableBindingShared(envRec, name, deletable, mv);
}
@Override
void initializeBinding(Value<? extends EnvironmentRecord> envRec, Name name, Value<?> value,
InstructionVisitor mv) {
initializeBindingShared(envRec, name, value, mv);
}
@Override
void hasBinding(Value<? extends EnvironmentRecord> envRec, Name name,
InstructionVisitor mv) {
hasBindingShared(envRec, name, mv);
}
@Override
void getBindingValue(Value<? extends EnvironmentRecord> envRec, Name name, boolean strict,
InstructionVisitor mv) {
getBindingShared(envRec, name, strict, mv);
}
@Override
void setMutableBinding(Value<? extends EnvironmentRecord> envRec, Name name, Value<?> value,
boolean strict, InstructionVisitor mv) {
setMutableBindingShared(envRec, name, value, strict, mv);
}
};
}