Package macromedia.asc.embedding

Source Code of macromedia.asc.embedding.BatchCompiler$Pair

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package macromedia.asc.embedding;

import macromedia.abc.AbcParser;
import macromedia.asc.embedding.avmplus.ActionBlockEmitter;
import macromedia.asc.embedding.avmplus.GlobalBuilder;
import macromedia.asc.parser.*;
import macromedia.asc.semantics.*;
import macromedia.asc.util.*;
import macromedia.asc.util.graph.DependencyGraph;
import macromedia.asc.util.graph.Algorithms;
import macromedia.asc.util.graph.Visitor;
import macromedia.asc.util.graph.Vertex;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;

/**
* asc batch compiler
*/
public class BatchCompiler
{
  private static List<File> file;
  private static List<Context> cx;
  private static List<ActionBlockEmitter> emitter;
  private static List<ProgramNode> node;
  private static List<FlowAnalyzer> fa;
  private static Set<Pair> inheritance;
  private static Set<Pair> type;

  private static ContextStatics s;

  public static void main(String[] args) throws Throwable
  {
    long startTime = System.currentTimeMillis();

    init(args);

    int start = 0, end = file.size();

    while (start < end)
    {
      parse(start, end);
      fa_part1(start, end);
      resolveInheritance(start, end);

      start = end;
      end = file.size();

      if (start < end) continue;

      sortInheritance();
      fa_part2();
      resolveType();

      start = end;
      end = file.size();

      if (start < end) continue;

      importType();
      ce();
      cg();

      // In theory, this should be in a second compile loop in order to reduce memory usage.
      resolveExpression();

      start = end;
      end = file.size();
    }

    clear();

    System.err.println("Files: " + file.size() + " Time: " + (System.currentTimeMillis() - startTime) + "ms");
  }

  private static void init(String[] args) throws Throwable
  {
    TypeValue.init();
    ObjectValue.init();
    s = new ContextStatics();
    //s.use_namespaces.addAll(null) // no automatic use_namespaces
    //s.es4_numerics = ...

    file = new ArrayList<File>(args.length);
    for (int i = 0, length = args.length; i < length; i++)
    {
      File f = new File(args[i]);
      if (f.exists() && f.isFile())
      {
        file.add(f.getCanonicalFile());
      }
    }

    cx = new ArrayList<Context>(file.size());
    for (int i = 0, length = file.size(); i < length; i++)
    {
      cx.add(new Context(s));
    }

    emitter = new ArrayList<ActionBlockEmitter>(file.size());
    for (int i = 0, length = file.size(); i < length; i++)
    {
      emitter.add(new ActionBlockEmitter(cx.get(i), file.get(i).getPath(), new StringPrintWriter(), new StringPrintWriter(), false, false, false, false));
    }

    node = new ArrayList<ProgramNode>(file.size());
    fa = new ArrayList<FlowAnalyzer>(file.size());
    inheritance = new HashSet<Pair>();
    type = new HashSet<Pair>();
  }

  private static void parse(int start, int end) throws Throwable
  {
    for (int i = start; i < end; i++)
    {
      cx.get(i).setEmitter(emitter.get(i));
      cx.get(i).setScriptName(file.get(i).getName());
      cx.get(i).setPath(file.get(i).getParent());

      if (file.get(i).getName().endsWith(".as"))
      {
        node.add(new Parser(cx.get(i), new FileInputStream(file.get(i)), file.get(i).getPath(), null).parseProgram());
      }
      else
      {
        node.add(new AbcParser(cx.get(i), file.get(i).getPath()).parseAbc());
      }

      cx.get(i).getNodeFactory().pkg_defs.clear();
    }
  }

  private static void fa_part1(int start, int end)
  {
    for (int i = start; i < end; i++)
    {
      if (cx.get(i).errorCount() == 0 && node.get(i).state == ProgramNode.Inheritance)
      {
        cx.get(i).pushScope(new ObjectValue(cx.get(i), new GlobalBuilder(), null));
        FlowGraphEmitter fgEmitter = new FlowGraphEmitter(cx.get(i), file.get(i).getPath(), false);
        fa.add(new FlowAnalyzer(fgEmitter));
        node.get(i).evaluate(cx.get(i), fa.get(i));
        cx.get(i).popScope();
      }
    }
  }

  private static void resolveInheritance(int start, int end) throws Throwable
  {
    for (int i = start; i < end; i++)
    {
      for (Iterator<ReferenceValue> k = node.get(i).fa_unresolved.iterator(); k.hasNext();)
      {
        ReferenceValue ref = k.next();
        boolean found = false;
        for (int j = 0, size = (ref.getImmutableNamespaces() != null) ? ref.getImmutableNamespaces().size() : 0; j < size; j++)
        {
          QName qname = new QName(ref.getImmutableNamespaces().get(j), ref.name);
          int where = findClass(qname);
          if (where != -1)
          {
            if (i != where)
            {
              Pair p = new Pair(i, where);
              if (!inheritance.contains(p))
              {
                inheritance.add(p);
              }
            }
            found = true;
            break;
          }
        }
        if (!found)
        {
          System.err.println(ref.toMultiName() + " in " + file.get(i) + " not resolved");
        }
      }

      node.get(i).fa_unresolved.clear();
    }
  }

  private static void sortInheritance() throws Throwable
  {
    for (Iterator<Pair> i = inheritance.iterator(); i.hasNext();)
    {
      Pair p = i.next();
      if (!p.processed)
      {
        fa.get(p.i).inheritSlots(node.get(p.where).frame, node.get(p.i).frame, node.get(p.i).frame.builder, cx.get(p.i));
        p.processed = true;
      }
    }

    final DependencyGraph<Integer> g = new DependencyGraph<Integer>();

    for (int i = 0, length = node.size(); i < length; i++)
    {
      String path = file.get(i).getPath();
      g.put(path, i);

      if (!g.containsVertex(path))
      {
        g.addVertex(new Vertex<String>(path));
      }

      for (Iterator<Pair> j = inheritance.iterator(); j.hasNext();)
      {
        Pair p = j.next();
        if (p.i == i)
        {
          g.addDependency(path, file.get(p.where).getPath());
        }
      }
    }

    final List<Integer> tsort = new ArrayList<Integer>(node.size());

    Algorithms.topologicalSort(g, new Visitor<String>()
    {
      public void visit(Vertex<String> v)
      {
        String name = v.getWeight();
        tsort.add(g.get(name));
      }
    });

    if (node.size() > tsort.size())
    {
      for (int i = 0, length = node.size(); i < length; i++)
      {
        int j = 0;
        for (; j < tsort.size(); j++)
        {
          if (tsort.get(j) == i)
          {
            break;
          }
        }
        if (j == tsort.size())
        {
          String path = file.get(i).getPath();
          System.out.println(path + " in circular reference");
        }
      }
    }
    else
    {
      List<File> tempFile = new ArrayList<File>(file.size());
      List<Context> tempCX = new ArrayList<Context>(cx.size());
      List<ActionBlockEmitter> tempEmitter = new ArrayList<ActionBlockEmitter>(emitter.size());
      List<ProgramNode> tempNode = new ArrayList<ProgramNode>(node.size());
      List<FlowAnalyzer> tempFA = new ArrayList<FlowAnalyzer>(fa.size());

      for (int i = 0, length = tsort.size(); i < length; i++)
      {
        int loc = tsort.get(i);

        tempFile.add(file.get(loc));
        tempCX.add(cx.get(loc));
        tempEmitter.add(emitter.get(loc));
        tempNode.add(node.get(loc));
        tempFA.add(fa.get(loc));
      }

      file = tempFile;
      cx = tempCX;
      emitter = tempEmitter;
      node = tempNode;
      fa = tempFA;

      for (Iterator<Pair> i = type.iterator(); i.hasNext();)
      {
        Pair p = i.next();
        for (int j = 0, length = tsort.size(); j < length; j++)
        {
          if (tsort.get(j) == p.i)
          {
            p.i = j;
            break;
          }
        }
        for (int j = 0, length = tsort.size(); j < length; j++)
        {
          if (tsort.get(j) == p.where)
          {
            p.where = j;
            break;
          }
        }
      }

      for (Iterator<Pair> i = inheritance.iterator(); i.hasNext();)
      {
        Pair p = i.next();
        for (int j = 0, length = tsort.size(); j < length; j++)
        {
          if (tsort.get(j) == p.i)
          {
            p.i = j;
            break;
          }
        }
        for (int j = 0, length = tsort.size(); j < length; j++)
        {
          if (tsort.get(j) == p.where)
          {
            p.where = j;
            break;
          }
        }
      }
    }
  }

  private static void fa_part2()
  {
    for (int i = 0, length = file.size(); i < length; i++)
    {
      if (cx.get(i).errorCount() == 0 && node.get(i).state == ProgramNode.Else)
      {
        cx.get(i).pushScope(node.get(i).frame);
        node.get(i).evaluate(cx.get(i), fa.get(i));
        cx.get(i).popScope();
      }
    }
  }

  private static void resolveType() throws Throwable
  {
    for (int i = 0, length = node.size(); i < length; i++)
    {
      for (Iterator<ReferenceValue> k = node.get(i).ce_unresolved.iterator(); k.hasNext();)
      {
        ReferenceValue ref = k.next();
        boolean found = false;
        for (int j = 0, size = (ref.getImmutableNamespaces() != null) ? ref.getImmutableNamespaces().size() : 0; j < size; j++)
        {
          QName qname = new QName(ref.getImmutableNamespaces().get(j), ref.name);
          int where = findClass(qname);
          if (where != -1)
          {
            if (i != where)
            {
              Pair p = new Pair(i, where);
              if (!type.contains(p))
              {
                type.add(p);
              }
            }
            found = true;
            break;
          }
        }
        if (!found)
        {
          System.err.println(ref.toMultiName() + " in " + file.get(i) + " not resolved");
        }
      }

      node.get(i).ce_unresolved.clear();
    }

    for (int i = 0, length = node.size(); i < length; i++)
    {
      for (Iterator<ReferenceValue> k = node.get(i).body_unresolved.iterator(); k.hasNext();)
      {
        ReferenceValue ref = k.next();
        boolean found = false;
        for (int j = 0, size = (ref.getImmutableNamespaces() != null) ? ref.getImmutableNamespaces().size() : 0; j < size; j++)
        {
          QName qname = new QName(ref.getImmutableNamespaces().get(j), ref.name);
          int where = findClass(qname);
          if (where != -1)
          {
            if (i != where)
            {
              Pair p = new Pair(i, where);
              if (!type.contains(p))
              {
                type.add(p);
              }
            }
            found = true;
            break;
          }
        }
        if (!found)
        {
          System.err.println(ref.toMultiName() + " in " + file.get(i) + " not resolved");
        }
      }

      node.get(i).body_unresolved.clear();
    }

    for (int i = 0, length = node.size(); i < length; i++)
    {
      for (Iterator<ReferenceValue> k = node.get(i).ns_unresolved.iterator(); k.hasNext();)
      {
        ReferenceValue ref = k.next();
        boolean found = false;
        for (int j = 0, size = (ref.getImmutableNamespaces() != null) ? ref.getImmutableNamespaces().size() : 0; j < size; j++)
        {
          QName qname = new QName(ref.getImmutableNamespaces().get(j), ref.name);
          int where = findDefinition(qname);
          if (where != -1)
          {
            if (i != where)
            {
              Pair p = new Pair(i, where);
              if (!type.contains(p))
              {
                type.add(p);
              }
            }
            found = true;
            break;
          }
        }
        if (!found)
        {
          System.err.println(ref.toMultiName() + " in " + file.get(i) + " not resolved");
        }
      }

      node.get(i).ns_unresolved.clear();
    }
  }

  private static void importType() throws Throwable
  {
    for (Iterator<Pair> i = type.iterator(); i.hasNext();)
    {
      Pair p = i.next();
      if (!p.processed)
      {
        if (!inheritance.contains(p))
        {
          fa.get(p.i).inheritSlots(node.get(p.where).frame, node.get(p.i).frame, node.get(p.i).frame.builder, cx.get(p.i));
        }
        p.processed = true;
      }
    }
  }

  private static void ce()
  {
    for (int i = 0, length = file.size(); i < length; i++)
    {
      if (cx.get(i).errorCount() == 0 && file.get(i).getName().endsWith(".as") && emitter.get(i) != null)
      {
        cx.get(i).pushScope(node.get(i).frame);
        ConstantEvaluator analyzer = new ConstantEvaluator(cx.get(i));
        node.get(i).evaluate(cx.get(i), analyzer);
        cx.get(i).popScope();
      }
    }
  }

  private static void cg() throws Throwable
  {
    for (int i = 0, length = file.size(); i < length; i++)
    {
      if (cx.get(i).errorCount() == 0 && file.get(i).getName().endsWith(".as") && emitter.get(i) != null)
      {
        cx.get(i).setEmitter(emitter.get(i));
        cx.get(i).pushScope(node.get(i).frame);
        CodeGenerator generator = new CodeGenerator(cx.get(i).getEmitter());
        node.get(i).evaluate(cx.get(i), generator);

        ByteList bytes = new ByteList();
        cx.get(i).getEmitter().emit(bytes);
        // String str = ((ActionBlockEmitter) cx.get(i).getEmitter()).il_str();
        emitter.set(i, null);
        FileOutputStream out = new FileOutputStream(new File(file.get(i).getParentFile(), file.get(i).getName().substring(0, file.get(i).getName().length() - "as".length()) + "abc"));
        System.err.println(file.get(i).getName() + ": " + bytes.size());
        out.write(bytes.toByteArray());
        out.flush();
        out.close();

        /*
        FileWriter fout = new FileWriter(new File(file.get(i).getParentFile(), file.get(i).getName().substring(0, file.get(i).getName().length() - "as".length()) + "il"));
        fout.write(str);
        fout.flush();
        fout.close();
                */

        cx.get(i).popScope();
      }
    }
  }

  private static void resolveExpression() throws Throwable
  {
    for (int i = 0, length = node.size(); i < length; i++)
    {
      for (Iterator<ReferenceValue> k = node.get(i).rt_unresolved.iterator(); k.hasNext();)
      {
        ReferenceValue ref = k.next();
        boolean found = false;
        for (int j = 0, size = (ref.getImmutableNamespaces() != null) ? ref.getImmutableNamespaces().size() : 0; j < size; j++)
        {
          QName qname = new QName(ref.getImmutableNamespaces().get(j), ref.name);
          if (qname.ns instanceof UnresolvedNamespace && ((UnresolvedNamespace) qname.ns).resolved)
          {
            found = true;
            break;
          }
          int where = findDefinition(qname);
          if (where != -1)
          {
            found = true;
            break;
          }
        }
        if (!found)
        {
          System.err.println(ref.toMultiName() + " in " + file.get(i) + " not resolved");
        }
      }

      node.get(i).rt_unresolved.clear();
    }
  }

  private static void clear()
  {
    s.clear();

    ObjectValue.clear();
    TypeValue.clear();
  }

  private static int findDefinition(QName defName) throws Throwable
  {
    for (int i = 0, length = node.size(); i < length; i++)
    {
      Names names = node.get(i).frame.builder.getNames();
      for (int j = 0; j < 4; j++)
      {
        if (names.containsKey(defName.name, defName.ns, j))
        {
          return i;
        }
      }
    }

    return searchClasspath(defName);
  }

  private static int findClass(QName className) throws Throwable
  {
    for (int i = 0, length = node.size(); i < length; i++)
    {
      for (int j = 0, size = (node.get(i).clsdefs != null) ? node.get(i).clsdefs.size() : 0; j < size; j++)
      {
        ClassDefinitionNode clsdef = node.get(i).clsdefs.get(j);
        if (clsdef.cframe.builder.classname.equals(className))
        {
          return i;
        }
      }
    }

    return searchClasspath(className);
  }

  private static int searchClasspath(QName qname) throws Throwable
  {
    String path = qname.ns.name.replace('.', File.separatorChar) + File.separatorChar + qname.name;
    File f = new File(path + ".as");
    if (f.exists() && f.isFile())
    {
      f = f.getCanonicalFile();
      Context context = new Context(s);

      int where = file.indexOf(f);
      if (where == -1)
      {
        file.add(f);
        cx.add(context);
        emitter.add(new ActionBlockEmitter(context, f.getPath(), new StringPrintWriter(), new StringPrintWriter(), false, false, false, false));
        where = file.size() - 1;
      }
      return where;
    }

    return -1;
  }

  static class Pair
  {
    Pair(int i, int where)
    {
      this.i = i;
      this.where = where;
      processed = false;
    }

    int i, where;
    boolean processed;

    public boolean equals(Object obj)
    {
      if (obj instanceof Pair)
      {
        return i == ((Pair) obj).i && where == ((Pair) obj).where;
      }
      else
      {
        return false;
      }
    }

    public int hashCode()
    {
      return (((1 * 17) + i) * 17) + where;
    }
  }
}
TOP

Related Classes of macromedia.asc.embedding.BatchCompiler$Pair

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.