All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.cast.js.translator.JavaScriptTranslatorToCAst Maven / Gradle / Ivy

There is a newer version: 1.6.7
Show newest version
/*
 * Copyright (c) 2013 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.cast.js.translator;

import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.util.debug.Assertions;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public interface JavaScriptTranslatorToCAst extends TranslatorToCAst {

  interface WalkContext, T> extends TranslatorToCAst.WalkContext {

    @Override
    WalkContext getParent();

    default String script() {
      return getParent().script();
    }

    default int setOperation(T node) {
      return getParent().setOperation(node);
    }

    default boolean foundMemberOperation(T node) {
      return getParent().foundMemberOperation(node);
    }

    default void copyOperation(T from, T to) {
      getParent().copyOperation(from, to);
    }
  }

  class RootContext, T> extends TranslatorToCAst.RootContext
      implements WalkContext {

    @Override
    public WalkContext getParent() {
      assert false;
      return null;
    }

    @Override
    public String script() {
      return null;
    }

    @Override
    public T top() {
      Assertions.UNREACHABLE();
      return null;
    }

    @Override
    public void addNameDecl(CAstNode v) {
      Assertions.UNREACHABLE();
    }

    @Override
    public List getNameDecls() {
      Assertions.UNREACHABLE();
      return null;
    }

    @Override
    public CAstNode getCatchTarget() {
      Assertions.UNREACHABLE();
      return null;
    }

    @Override
    public int setOperation(T node) {
      return -1;
    }

    @Override
    public boolean foundMemberOperation(T node) {
      return false;
    }

    @Override
    public void copyOperation(T from, T to) {
      Assertions.UNREACHABLE();
    }
  }

  class FunctionContext, T>
      extends TranslatorToCAst.FunctionContext implements WalkContext {

    private final List initializers = new ArrayList<>();

    @Override
    public WalkContext getParent() {
      return (WalkContext) super.getParent();
    }

    protected FunctionContext(C parent, T s) {
      super(parent, s);
    }

    @Override
    public void addNameDecl(CAstNode v) {
      initializers.add(v);
    }

    @Override
    public List getNameDecls() {
      return initializers;
    }

    @Override
    public String script() {
      return parent.script();
    }

    @Override
    public CAstNode getCatchTarget() {
      return CAstControlFlowMap.EXCEPTION_TO_EXIT;
    }

    @Override
    public int setOperation(T node) {
      return parent.setOperation(node);
    }

    @Override
    public boolean foundMemberOperation(T node) {
      return parent.foundMemberOperation(node);
    }

    @Override
    public void copyOperation(T from, T to) {
      parent.copyOperation(from, to);
    }
  }

  class ScriptContext, T> extends FunctionContext {
    private final String script;

    ScriptContext(C parent, T s, String script) {
      super(parent, s);
      this.script = script;
    }

    @Override
    public String script() {
      return script;
    }
  }

  /**
   * Used to determine the value to be passed as the 'this' argument for a function call. This is
   * needed since in JavaScript, you can write a call e(...) where e is some arbitrary expression,
   * and in the case where e is a property access like e'.f, we must discover that the value of
   * expression e' is passed as the 'this' parameter.
   *
   * 

The general strategy is to store the value of the expression passed as the 'this' parameter * in baseVar, and then to use baseVar as the actual argument sub-node for the CAst call node */ class MemberDestructuringContext, T> implements WalkContext { private final WalkContext parent; /** * node for which we actually care about what the base pointer is. this helps to handle cases * like x.y.f(), where we would like to store x.y in baseVar, but not x when we recurse. */ private final Set baseFor = new HashSet<>(); private final int operationIndex; /** have we discovered a value to be passed as the 'this' parameter? */ private boolean foundBase = false; protected MemberDestructuringContext(C parent, T initialBaseFor, int operationIndex) { this.parent = parent; baseFor.add(initialBaseFor); this.operationIndex = operationIndex; } @Override public int setOperation(T node) { if (baseFor.contains(node)) { foundBase = true; return operationIndex; } else { return -1; } } @Override public boolean foundMemberOperation(T node) { return foundBase; } @Override public void copyOperation(T from, T to) { if (baseFor.contains(from)) baseFor.add(to); } @Override public WalkContext getParent() { return parent; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy