📄 parseclass.java
字号:
/* * Copyright (c) 1998-2006 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.*;import com.caucho.java.LineMap;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import com.caucho.vfs.Path;import com.caucho.vfs.WriteStream;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;class ParseClass { private String srcFilename; private LineMap lineMap; private Parser parser; // The full classname of the generated script. private String className; // The package name of the generated script. private String pkg; // The class name. private String name; private ESId proto; // the global parse class private ParseClass root; // class instance variables private HashMap variables = new HashMap(); // child classes private ArrayList classes = new ArrayList(); // class methods private ArrayList functions = new ArrayList(); private IntMap funMap = new IntMap(); private HashMap names = new HashMap(); private HashMap literals = new HashMap(); private HashMap mangledSet = new HashMap(); private Function global; private int unique; private int callDepth; private ArrayList imports = new ArrayList(); private ArrayList javaImports = new ArrayList(); private WriteStream os; private int printDepth; private boolean isFirst; private int destLine; private Path sourcePath; /** * Creates a new parse class. * * @param srcFilename the name of the source (*.js) * @param name the classname. */ ParseClass(String srcFilename, String name) { this.srcFilename = srcFilename; this.root = this; className = name; int p = name.lastIndexOf('.'); if (p >= 0) { pkg = name.substring(0, p); this.name = name.substring(p + 1); } else { this.name = name; } lineMap = new LineMap(name, srcFilename); lineMap.add(1, 1); destLine = 1; } /** * Sets the source path for searching import classes. */ void setSourcePath(Path sourcePath) { this.sourcePath = sourcePath; } /** * Gets the script search path */ Path getScriptPath() { return root.parser.getScriptPath(); } void setParser(Parser parser) { root.parser = parser; } void setWriteStream(WriteStream os) { this.os = os; } /** * Creates a child subclasses of this class. * * @param id the new class name. */ ParseClass newClass(ESId id) { ParseClass cl = new ParseClass(srcFilename, id.toString()); classes.add(cl); cl.root = root; return cl; } Function newFunction(Function oldFun, ESId id, boolean isClass) { if (id == null) id = ESId.intern("$lambda" + unique++); String realId = "_f_" + id.toString(); while (names.get(realId) != null) { realId = realId + unique++; } names.put(realId, realId); Function fun = new Function(this, oldFun, realId, id, isClass); setFunction(fun); return fun; } void setFunction(Function function) { int index; if ((index = funMap.get(function.name)) >= 0) { function.num = index; functions.set(index, function); } else { function.num = functions.size(); funMap.put(function.name, functions.size()); functions.add(function); } } void addImport(String importName) { if (! imports.contains(importName)) imports.add(importName); } /** * Adds a Java class/package import to the list. */ void addJavaImport(String importName) { if (! javaImports.contains(importName)) javaImports.add(importName); } /** * Gets a class variable. */ Variable getVariable(ESId id) { return (Variable) variables.get(id); } /** * Sets a new class variable. */ void addVariable(ESId id, Variable var) { variables.put(id, var); var.setJavaGlobal(true); } void setGlobal(Function global) { this.global = global; } void setProto(ESId proto) { this.proto = proto; } void addFunction(Function function) { setFunction(function); } void writeCode(WriteStream os) throws IOException { this.os = os; println("/**"); println(" * Generated by " + com.caucho.Version.FULL_VERSION); println(" */"); println(); println("package " + pkg + ";"); println("import java.io.*;"); println("import com.caucho.es.*;"); println("import com.caucho.util.*;"); for (int i = 0; i < javaImports.size(); i++) println("import " + javaImports.get(i) + ";"); println("public class " + name + " extends com.caucho.es.Script {"); pushDepth(); writeExecute(); writeClassContents(); writeLastModified(); printLineMap(); popDepth(); println("}"); } /** * Writes the contents of the class. Actually generates two classes. * One is a straight Java class, the other is the wrapper. */ void writeClassContents() throws IOException { if (os == null) os = root.os; String name = this == root ? "js_global" : this.name; println(); println("public static class " + name + " {"); pushDepth(); println(name + "_es _js;"); Iterator iter = variables.values().iterator(); while (iter.hasNext()) { Variable var = (Variable) iter.next(); writeVarDecl(var, true); } for (int i = 0; i < functions.size(); i++) { Function fun = (Function) functions.get(i); println(); fun.writeCode(this); } popDepth(); println("}"); println(); if (name.equals("js_global")) println("public static class js_global_es extends ESGlobal {"); else println("public static class " + name + "_es extends ESClass {"); pushDepth(); println(name + " _js_object;"); println(); println(); if (name.equals("js_global")) { println("js_global_es(Global resin)"); println("{"); println(" super(resin);"); println(" resin.setGlobal(this);"); } else { println(name + "_es()"); println("{"); } println(" _js_object = new " + name + "();"); println(" _js_object._js = this;"); println("}"); writeMap(); printGetProperty(); printPropNames(); writeInit(); writeWrapperInit(name); writeStaticInit(); writeExport(); popDepth(); println("}"); for (int i = 0; i < classes.size(); i++) { ParseClass subClass = (ParseClass) classes.get(i); subClass.setWriteStream(os); subClass.writeClassContents(); } } void writeExport() throws IOException { println(); println("public void export(ESObject dst) throws Throwable"); println("{"); println(" ESBase tmp;"); for (int i = 0; global.functions != null && i < global.functions.size(); i++) { Function fun = (Function) global.functions.get(i); println(" tmp = getProperty(\"" + fun.id + "\");"); println(" dst.put(\"" + fun.id + "\", tmp, ESBase.DONT_ENUM);"); } for (int i = 0; i < classes.size(); i++) { ParseClass cl = (ParseClass) classes.get(i); Function fun = cl.getFunction(ESId.intern(cl.name)); println(" tmp = getProperty(\"" + cl.name + "\");"); println(" dst.put(\"" + cl.name + "\", tmp, ESBase.DONT_ENUM);"); } println("}"); } void writeExecute() throws IOException { println("public ESGlobal initClass(Global resin) throws Throwable"); println("{"); pushDepth(); println("resin.addScript(\"" + className + "\", this);"); println("js_global_es test = new js_global_es(resin);"); println("test._init(resin, test);"); println("return test;"); popDepth(); println("}"); } void writeWrapperInit(String name) throws IOException { } void writeVarDecl(Variable var, boolean init) throws IOException { if (var.getType() == Expr.TYPE_BOOLEAN) { print("boolean " + var.getId()); if (init) println(" = false;"); else println(";"); } else if (var.getType() == Expr.TYPE_INTEGER) { print("int " + var.getId()); if (init) println(" = 0;"); else println(";"); } else if (var.getType() == Expr.TYPE_NUMBER) { print("double " + var.getId()); if (init) println(" = Double.NaN;"); else println(";"); } else if (var.getType() == Expr.TYPE_STRING) { print("ESString " + var.getId()); if (init) println(" = ESString.create(\"\");"); else println(";"); } else if (var.getType() == Expr.TYPE_JAVA && var.getTypeExpr() != null) { TypeExpr type = (TypeExpr) var.getTypeExpr(); println(type.getTypeName() + " " + var.getId() + ";"); } else { if (init) println("ESBase " + var.getId() + " = ESBase.esUndefined;"); else println("ESBase " + var.getId() + ";"); } } void printId(ESId id) throws IOException { print("js_global_es."); print(getMangledLiteral(id)); } String getMangledLiteral(ESBase value) { String literal = (String) literals.get(value); if (literal == null) { literal = mangleLiteral(value); literals.put(value, literal); } return literal; } // XXX: hacks void pushCall() { callDepth++; } void popCall(int n) { callDepth -= n; } int getCallDepth() { return callDepth; } void printLiteral(ESBase obj) throws IOException { if (obj == null) print("ESBase.esNull"); else if (obj instanceof ESNull) print("ESBase.esNull"); else if (obj instanceof ESUndefined) print("ESBase.esUndefined"); else if (obj == ESBoolean.TRUE) print("ESBoolean.TRUE"); else if (obj == ESBoolean.FALSE) print("ESBoolean.FALSE"); else { String literal = (String) literals.get(obj); if (literal == null) { try { if (obj instanceof ESNumber && Double.isNaN(obj.toNum())) { print("ESNumber.NaN"); return; } } catch (Throwable e) { } literal = mangleLiteral(obj); literals.put(obj, literal); } print("js_global_es."); print(literal); } } private String mangleLiteral(Object obj) { String s = obj.toString(); CharBuffer cb = new CharBuffer("_l_"); for (int i = 0; i < s.length() && i < 32; i++) { char ch = s.charAt(i); // Java can't really deal with non-ascii? if (Character.isJavaIdentifierPart(ch) && ch >= ' ' && ch < 127) cb.append(ch); else if (cb.getLastChar() != '_') cb.append("_"); } if (mangledSet.get(cb) != null) cb.append("_" + unique++); mangledSet.put(cb, cb); return cb.toString(); } /** * Writes the method map. */ void writeMap() throws IOException { println("public ESBase call(int n, Call call, int length)"); println(" throws Throwable"); println("{"); println(" switch(n) {"); for (int i = 0; i < functions.size(); i++) { Function fun = (Function) functions.get(i); println(" case " + i + ":"); print(" return ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -