package mumbler.truffle.node.special; import mumbler.truffle.node.MumblerNode; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; @NodeChild("valueNode") @NodeField(name = "slot", type = FrameSlot.class) public abstract class DefineNode extends MumblerNode { protected abstract FrameSlot getSlot(); protected abstract Node getValueNode(); @Specialization(guards = "isLongKind()") protected long writeLong(VirtualFrame virtualFrame, long value) { virtualFrame.setLong(this.getSlot(), value); return value; } @Specialization(guards = "isBooleanKind()") protected boolean writeBoolean(VirtualFrame virtualFrame, boolean value) { virtualFrame.setBoolean(this.getSlot(), value); return value; } @Specialization(contains = {"writeLong", "writeBoolean"}) protected Object write(VirtualFrame virtualFrame, Object value) { FrameSlot slot = this.getSlot(); if (slot.getKind() != FrameSlotKind.Object) { CompilerDirectives.transferToInterpreterAndInvalidate(); slot.setKind(FrameSlotKind.Object); } virtualFrame.setObject(slot, value); return value; } protected boolean isLongKind() { return this.isKind(this.getSlot(), FrameSlotKind.Long); } protected boolean isBooleanKind() { return this.isKind(this.getSlot(), FrameSlotKind.Boolean); } private boolean isKind(FrameSlot slot, FrameSlotKind kind) { if (slot.getKind() == kind) { return true; } if (slot.getKind() == FrameSlotKind.Illegal) { CompilerDirectives.transferToInterpreterAndInvalidate(); slot.setKind(kind); return true; } return false; } @Override public String toString() { return "(define " + this.getSlot().getIdentifier() + " " + this.getValueNode() + ")"; } }