/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.harness.lang.ast; import java.util.EnumSet; import java.util.Set; import org.mmtk.harness.lang.Visitor; import org.mmtk.harness.lang.runtime.BoolValue; import org.mmtk.harness.lang.runtime.IntValue; import org.mmtk.harness.lang.runtime.Value; import org.mmtk.harness.lang.type.Type; /** * Arithmetic and logical operators * * Operations themselves implemented in the appropriate Expression types * * This would be an enum but it needs to inherit from AST, so that we can * push operators onto an AST stack. */ public enum Operator { /* Equality */ EQ("==") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.equals(rhs)); } }, NE("!=") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(!lhs.equals(rhs)); } }, /* Integer comparison */ GT(">") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getIntValue() > rhs.getIntValue()); } }, LT("<") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getIntValue() < rhs.getIntValue()); } }, LE("<=") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getIntValue() <= rhs.getIntValue()); } }, GE(">=") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getIntValue() >= rhs.getIntValue()); } }, /* Logical */ AND("&&") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getBoolValue() && rhs.getBoolValue()); } }, OR("||") { @Override public Value operate(Value lhs, Value rhs) { return BoolValue.valueOf(lhs.getBoolValue() || rhs.getBoolValue()); } }, /* Unary */ NOT("!") { @Override public Value operate(Value operand) { return BoolValue.valueOf(!operand.getBoolValue()); } }, /* Mathematical */ PLUS("+") { @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() + rhs.getIntValue()); } }, MINUS("-") { @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() - rhs.getIntValue()); } @Override public Value operate(Value operand) { return new IntValue(- operand.getIntValue()); } }, MULT("*") { @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() * rhs.getIntValue()); } }, DIV("/") { @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() / rhs.getIntValue()); } }, REM("%") { @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() % rhs.getIntValue()); } }, LS("<<"){ @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() << rhs.getIntValue()); } }, RS(">>"){ @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() >> rhs.getIntValue()); } }, RSL(">>>"){ @Override public Value operate(Value lhs, Value rhs) { return new IntValue(lhs.getIntValue() >>> rhs.getIntValue()); } }; /* * Families of operators */ public static final Set<Operator> allOperators = EnumSet.allOf(Operator.class); public static final Set<Operator> unaryOperators = EnumSet.of(NOT, MINUS); public static final Set<Operator> binaryOperators = EnumSet.complementOf(EnumSet.of(NOT)); public static final Set<Operator> booleanOperators = EnumSet.of( AND, OR, NOT, GT, LT, LE, GE, EQ, NE); public static final Set<Operator> arithmeticOperators = EnumSet.of( PLUS, MINUS, MULT, DIV, REM, LS, RS, RSL); /** Printable representation */ private final String image; private Operator(String image) { this.image = image; } public final Type resultType(Type lhs, Type rhs) { if (booleanOperators.contains(this)) { return Type.BOOLEAN; } assert lhs == rhs; return lhs; } /** * @return true if this is a binary operation */ public boolean isBinary() { return binaryOperators.contains(this); } /** * @return true if this is a unary operation */ public boolean isUnary() { return unaryOperators.contains(this); } public String toString() { return image; } public void accept(Visitor v) { v.visit(this); } public Value operate(Value operand) { throw new RuntimeException("Unsupported unary operation, "+this); } public Value operate(Value lhs, Value rhs) { throw new RuntimeException("Unsupported binary operation, "+this); } }