Package com.caucho.es.parser

Source Code of com.caucho.es.parser.BinaryExpr

/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*   Free SoftwareFoundation, Inc.
*   59 Temple Place, Suite 330
*   Boston, MA 02111-1307  USA
*
* @author Scott Ferguson
*/

package com.caucho.es.parser;

import com.caucho.es.ESBase;
import com.caucho.es.ESException;
import com.caucho.es.ESNumber;
import com.caucho.es.ESWrapperException;

import java.io.IOException;

/**
* Expr is an intermediate form representing an expression.
*/
class BinaryExpr extends Expr {
  Expr left;
  Expr right;
  int op;
  String temp;
  boolean isSimple;
 
  protected BinaryExpr(Block block, Expr left, Expr right, int op)
  {
    super(block);
   
    this.left = left;
    this.right = right;
    this.op = op;
    isSimple = left.isSimple();
    if ((op == Lexer.AND || op == Lexer.OR) && ! isSimple)
      temp = block.function.getTemp();
  }

  static Expr create(Block block, Expr left, Expr right, int op)
    throws ESException
  {
    if (left != null)
      left.setUsed();
    if (right != null)
      right.setUsed();
   
    if (! (left instanceof LiteralExpr|| ! (right instanceof LiteralExpr))
      return new BinaryExpr(block, left, right, op);

    ESBase lvalue = ((LiteralExpr) left).getLiteral();
    ESBase rvalue = ((LiteralExpr) right).getLiteral();
    ESBase value;

    try {
      switch (op) {
      case '*':
        value = ESNumber.create(lvalue.toNum() * rvalue.toNum());
        break;
     
      case '/':
        value = ESNumber.create(lvalue.toNum() / rvalue.toNum());
        break;
     
      case '-':
        value = ESNumber.create(lvalue.toNum() - rvalue.toNum());
        break;
     
      case '%':
        value = ESNumber.create(lvalue.toNum() % rvalue.toNum());
        break;

      case Lexer.LSHIFT:
        value = ESNumber.create(lvalue.toInt32() << rvalue.toInt32());
        break;

      case Lexer.RSHIFT:
        value = ESNumber.create(lvalue.toInt32() >> rvalue.toInt32());
        break;

      case Lexer.URSHIFT:
        value = ESNumber.create(lvalue.toInt32() >>> rvalue.toInt32());
        break;

      case '&':
        value = ESNumber.create(lvalue.toInt32() & rvalue.toInt32());
        break;

      case '|':
        value = ESNumber.create(lvalue.toInt32() | rvalue.toInt32());
        break;

      case '^':
        value = ESNumber.create(lvalue.toInt32() ^ rvalue.toInt32());
        break;

      case Lexer.AND:
        value = lvalue.toBoolean() ? rvalue : lvalue;
        break;

      case Lexer.OR:
        value = lvalue.toBoolean() ? lvalue : rvalue;
        break;

      case ',':
        value = rvalue;
        break;

      default:
        throw new RuntimeException("" + (char) op);
      }
    } catch (Throwable e) {
      throw new ESWrapperException(e);
    }

    return new LiteralExpr(block, value);
  }
 
  int getType()
  {
   
    switch (op) {
    case '*':
    case '/':
    case '%':
      return TYPE_NUMBER;
     
    case '-':
      if (left.getType() == TYPE_INTEGER && right.getType() == TYPE_INTEGER)
        return TYPE_INTEGER;
      else
        return TYPE_NUMBER;

    case Lexer.LSHIFT:
    case Lexer.RSHIFT:
    case Lexer.URSHIFT:
    case '&':
    case '|':
    case '^':
      return TYPE_INTEGER;

    case Lexer.AND:
    case Lexer.OR:
      if (left.getType() == right.getType())
        return left.getType();
      else if (left.isNum() && right.isNum())
        return TYPE_NUMBER;
      else
        return TYPE_ES;

    case ',':
      return TYPE_ES;

    default:
      throw new RuntimeException("" + (char) op + " " + op);
    }
  }

  void exprStatement(Function fun) throws ESException
  {
    switch (op) {
    default:
      left.exprStatement(fun);
      right.exprStatement(fun);
      break;
    }
  }

  void printNumImpl() throws IOException
  {
    cl.print("(");
   
    switch (op) {
    case '*':
    case '/':
    case '-':
    case '%':
      left.printNum();
      cl.print(" " + (char) op + " ");
      right.printNum();
      break;

    case Lexer.AND:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        right.printNum();
        cl.print(":");
        left.printNum();
      }
      else {
        cl.print("(" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? ");
        right.printNum();
        cl.print(":" + temp + ".toNum()");
      }
      break;

    case Lexer.OR:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        left.printNum();
        cl.print(":");
        right.printNum();
      }
      else {
        cl.print("(" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? " + temp + ".toNum() : ");
        right.printNum();
      }
      break;

    default:
      throw new IOException("foo");
    }
   
    cl.print(")");
  }

  void printInt32Impl() throws IOException
  {
    cl.print("(");
   
    switch (op) {
    case '-':
      left.printInt32();
      cl.print(" " + (char) op + " ");
      right.printInt32();
      break;

    case Lexer.LSHIFT:
      left.printInt32();
      cl.print(" << ");
      right.printInt32();
      break;

    case Lexer.RSHIFT:
      left.printInt32();
      cl.print(" >> ");
      right.printInt32();
      break;

    case Lexer.URSHIFT:
      left.printInt32();
      cl.print(" >>> ");
      right.printInt32();
      break;

    case '&':
    case '|':
    case '^':
      left.printInt32();
      cl.print(" " + (char) op + " ");
      right.printInt32();
      break;

    case Lexer.AND:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        right.printInt32();
        cl.print(":");
        left.printInt32();
      }
      else {
        cl.print("(" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? ");
        right.printInt32();
        cl.print(":" + temp + ".toInt32()");
      }
      break;

    case Lexer.OR:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        left.printInt32();
        cl.print(":");
        right.printInt32();
      }
      else {
        cl.print("(" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? " + temp + ".toInt32() : ");
        right.printInt32();
      }
      break;

    default:
      throw new IOException("foo");
    }
   
    cl.print(")");
  }

  void printBoolean() throws IOException
  {
    switch (op) {
    case Lexer.AND:
      cl.print("(");
      left.printBoolean();
      cl.print(" && ");
      right.printBoolean();
      cl.print(")");
      break;

    case Lexer.OR:
      cl.print("(");
      left.printBoolean();
      cl.print(" || ");
      right.printBoolean();
      cl.print(")");
      break;

    default:
      super.printBoolean();
    }
  }

  void printBooleanImpl() throws IOException
  {
    cl.print("(");
   
    switch (op) {
    case Lexer.AND:
      left.printBoolean();
      cl.print(" && ");
      right.printBoolean();
      break;

    case Lexer.OR:
      left.printBoolean();
      cl.print(" || ");
      right.printBoolean();
      break;

    default:
      throw new IOException("foo");
    }
   
    cl.print(")");
  }

  void printImpl() throws IOException
  {
    switch (op) {
    case Lexer.AND:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        right.print();
        cl.print(":");
        left.print();
      }
      else {
        cl.print("((" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? ");
        right.print();
        cl.print(":" + temp + ")");
      }
      break;

    case Lexer.OR:
      if (isSimple) {
        left.printBoolean();
        cl.print(" ? ");
        left.print();
        cl.print(":");
        right.print();
      }
      else {
        cl.print("((" + temp + " = ");
        left.print();
        cl.print(").toBoolean() ? " + temp + " : ");
        right.print();
        cl.print(")");
      }
      break;

    case ',':
      cl.print("_env.comma(");
      left.print();
      cl.print(", ");
      right.print();
      cl.print(")");
      break;

    default:
      throw new IOException("foo");
    }
  }
}
TOP

Related Classes of com.caucho.es.parser.BinaryExpr

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.