📄 function.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.ESId;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;/** * Function is an intermediate form representing an expression. */class Function { static ESId PROTOTYPE = ESId.intern("prototype"); Parser parser; ParseClass cl; private Function parent; int funDepth; private int lambdaCount = 0; ArrayList formals; Expr returnType; ArrayList variables = new ArrayList(); // child closures ArrayList functions; private IntMap funMap; boolean isClass; ESId classProto; // null for non-classes Function constructor; String name; ESId id; int num; boolean isSilent; boolean hasCall; boolean hasThis; boolean allowLocals; boolean allowJavaLocals; boolean needsScope; ArrayList data = new ArrayList(); private HashMap vars = new HashMap(); CharBuffer tail; private int iterCount; private int tempCount; private int stmtCount; private int stmtTop; private HashMap usedVars; private boolean isGlobal; // True if an arguments variable needs to be created. eval, closures, // the arguments variable and "with" will set this. private boolean needsArguments; private boolean needsStatementResults; // True if any variable can be used even if not explicitly referenced // e.g. if the "arguments" variable is used. private boolean useAllVariables; // True if the function contains an eval private boolean isEval; // True if the function contains a switch private boolean hasSwitch; Function(ParseClass cl, Function parent, String name, ESId id, boolean isClass) { this.id = id; this.name = name; this.parent = parent; this.cl = cl; if (parent == null || isClass) funDepth = 0; else funDepth = parent.funDepth + 1; num = -1; isGlobal = parent == null; allowLocals = funDepth >= 1 || isClass; allowJavaLocals = allowLocals; needsStatementResults = parent == null; } void setFast(boolean isFast) { if (isFast) { allowLocals = true; allowJavaLocals = true; } } Function getParent() { return parent; } boolean isGlobalScope() { return ! needsScope && (getFunctionDepth() == 0 || getFunctionDepth() == 1 && ! needsArguments()); } boolean needsStatementResults() { return needsStatementResults; } void setNeedsResults() { needsStatementResults = true; } void setEval() { setArguments(); needsStatementResults = true; isEval = true; } boolean useAllVariables() { return isEval || useAllVariables; } void setUseAllVariables() { useAllVariables = true; } String getStatementVar() { if (! needsStatementResults()) return null; else return "_val" + stmtCount; } void pushStatementLoop() { if (! needsStatementResults()) return; stmtCount++; if (stmtCount > stmtTop) stmtTop = stmtCount; } void popStatementLoop() { if (! needsStatementResults()) return; stmtCount--; } void setCall() { this.hasCall = true; } void setThis() { this.hasThis = true; } /** * Force all unassigned variables to become object vars. */ void setVars() { Iterator iter = vars.values().iterator(); while (iter.hasNext()) { Variable var = (Variable) iter.next(); var.getType(); } } boolean isGlobal() { return isGlobal; } int getFunctionDepth() { return funDepth; } void disableGlobal() { isGlobal = false; } void disallowLocal() { if (parent != null) { allowJavaLocals = false; allowLocals = false; needsScope = true; } } void disallowJavaLocal() { allowJavaLocals = false; } void setNeedsScope() { if (parent != null) needsScope = true; } void setArguments() { needsArguments = true; setNeedsScope(); disallowLocal(); } boolean needsArguments() { return needsArguments; } boolean allowLocals() { return allowLocals; } boolean allowJavaLocals() { return allowLocals && allowJavaLocals; } void useClosureVar(ESId name) { for (Function fun = parent; fun != null; fun = fun.parent) { Variable var = (Variable) fun.vars.get(name); fun.needsArguments = true; if (var != null) var.setUsedByClosure(); else { if (fun.usedVars == null) fun.usedVars = new HashMap(); fun.usedVars.put(name, name); } } } /** * Returns true if the variable is declared. */ boolean hasVar(ESId name) { return vars.get(name) != null; } /** * Returns a new variable. */ IdExpr newVar(Block block, ESId name) { return newVar(block, name, null); } /** * Returns a new variable. */ IdExpr newVar(Block block, ESId name, Expr type) { Variable var = (Variable) vars.get(name); if (var == null && type == null) { var = cl.getVariable(name); if (var != null) { return new IdExpr(block, var); } } if (var == null) { var = new Variable(block, name, type, false); vars.put(name, var); if (usedVars != null && usedVars.get(name) != null) var.setUsedByClosure(); } useClosureVar(name); return new IdExpr(block, var); } /** * Add a variable to the function. If the function is the global * function, add it to the class. */ void addVariable(Block block, ESId id, Expr type) { if (variables == null) variables = new ArrayList(); Variable var = (Variable) vars.get(id); if (var == null) { var = new Variable(block, id, type, allowLocals); vars.put(id, var); if (usedVars != null && usedVars.get(id) != null) var.setUsedByClosure(); // Only add global variables if they're declared, not if defined // by use. if (parent == null && type != null) cl.addVariable(id, var); } else if (parent != null) var.setLocal(); if (! variables.contains(var) && (formals == null || ! formals.contains(var))) variables.add(var); useClosureVar(id); } int getIter() { return iterCount++; } String getTemp() { return "temp" + tempCount++; } void setConstructor(Function constructor) { isClass = true; this.constructor = constructor; } void setClassProto(ESId classProto) { isClass = true; this.classProto = classProto; } void setCodeNumber(int num) { this.num = num; } void addFormal(Block block, ESId id, Expr type) { if (formals == null) formals = new ArrayList(); Variable var = new Variable(block, id, type, true); var.setUsed(); formals.add(var);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -