/**
* 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 java.io.PrintStream;
import com.github.anba.es6draft.ast.Node;
import com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType;
import com.github.anba.es6draft.compiler.assembler.Code.MethodCode;
import com.github.anba.es6draft.compiler.assembler.Field;
import com.github.anba.es6draft.compiler.assembler.FieldName;
import com.github.anba.es6draft.compiler.assembler.InstructionAssembler;
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.types.Null;
import com.github.anba.es6draft.runtime.types.Undefined;
/**
*
*/
class InstructionVisitor extends InstructionAssembler {
private static final class Fields {
static final FieldName Null_NULL = FieldName.findStatic(Types.Null, "NULL", Types.Null);
static final FieldName Undefined_UNDEFINED = FieldName.findStatic(Types.Undefined, "UNDEFINED",
Types.Undefined);
static final FieldName System_out = FieldName.findStatic(Type.of(System.class), "out",
Type.of(PrintStream.class));
}
private static final class Methods {
static final MethodName PrintStream_println = MethodName.findVirtual(Type.of(PrintStream.class), "println",
Type.methodType(Type.VOID_TYPE, Types.String));
}
protected InstructionVisitor(MethodCode method) {
super(method);
}
/**
* The {@code undefined} value.
*
* @return {@code undefined} value
*/
final Value<Undefined> undefinedValue() {
return new Field<>(Fields.Undefined_UNDEFINED);
}
/**
* The {@code null} value.
*
* @return {@code null} value
*/
final Value<Null> nullValue() {
return new Field<>(Fields.Null_NULL);
}
/**
* ∅ → undefined
*/
final void loadUndefined() {
get(Fields.Undefined_UNDEFINED);
}
/**
* ∅ → null
*/
final void loadNull() {
get(Fields.Null_NULL);
}
/**
* Emit a line number declaration.
*
* @param node
* the node instance
*/
final void lineInfo(Node node) {
lineInfo(node.getBeginLine());
}
/**
* Prints a message to {@code System.out}.
*
* @param message
* the message string
*/
final void println(String message) {
get(Fields.System_out);
aconst(message);
invoke(Methods.PrintStream_println);
}
/**
* value → value, value
*
* @param type
* the topmost stack value
*/
public void dup(ValType type) {
switch (type.size()) {
case 1:
dup();
return;
case 2:
dup2();
return;
case 0:
default:
throw new AssertionError();
}
}
/**
* value → []
*
* @param type
* the topmost stack value
*/
public void pop(ValType type) {
switch (type.size()) {
case 0:
return;
case 1:
pop();
return;
case 2:
pop2();
return;
default:
throw new AssertionError();
}
}
/**
* lvalue, rvalue → rvalue, lvalue, rvalue
*
* @param ltype
* the second topmost stack value
* @param rtype
* the topmost stack value
*/
public void dupX(ValType ltype, ValType rtype) {
int lsize = ltype.size(), rsize = rtype.size();
if (lsize == 1 && rsize == 1) {
dupX1();
} else if (lsize == 1 && rsize == 2) {
dup2X1();
} else if (lsize == 2 && rsize == 1) {
dupX2();
} else if (lsize == 2 && rsize == 2) {
dup2X2();
} else {
throw new AssertionError();
}
}
/**
* lvalue, rvalue → rvalue, lvalue
*
* @param ltype
* the second topmost stack value
* @param rtype
* the topmost stack value
*/
public void swap(ValType ltype, ValType rtype) {
int lsize = ltype.size(), rsize = rtype.size();
if (lsize == 0 || rsize == 0) {
return;
} else if (lsize == 1 && rsize == 1) {
swap();
} else if (lsize == 1 && rsize == 2) {
swap1_2();
} else if (lsize == 2 && rsize == 1) {
swap2_1();
} else if (lsize == 2 && rsize == 2) {
swap2();
} else {
throw new AssertionError();
}
}
/**
* value → boxed
*
* @param type
* the value type
*/
public void toBoxed(ValType type) {
if (type.isJavaPrimitive()) {
toBoxed(type.toType());
}
}
/**
* boxed → value
*
* @param type
* the value type
*/
public void toUnboxed(ValType type) {
if (type.isJavaPrimitive()) {
toUnboxed(type.toType());
}
}
/**
* Pop all stack entries.
* <p>
* stack: [...] → []
*/
public void popStack() {
if (getStackSize() > 0) {
Type[] stack = getStack();
for (int i = stack.length - 1; i >= 0; --i) {
pop(stack[i]);
}
}
}
}