mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
383 lines
12 KiB
Java
383 lines
12 KiB
Java
|
/*
|
||
|
* @(#) $(JCGO)/jtrsrc/com/ivmaisoft/jcgo/Context.java --
|
||
|
* a part of JCGO translator.
|
||
|
**
|
||
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
||
|
* Copyright (C) 2001-2012 Ivan Maidanski <ivmai@mail.ru>
|
||
|
* All rights reserved.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* This 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, or (at your option)
|
||
|
* any later version.
|
||
|
**
|
||
|
* This software 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. See the GNU
|
||
|
* General Public License (GPL) for more details.
|
||
|
**
|
||
|
* Linking this library statically or dynamically with other modules is
|
||
|
* making a combined work based on this library. Thus, the terms and
|
||
|
* conditions of the GNU General Public License cover the whole
|
||
|
* combination.
|
||
|
**
|
||
|
* As a special exception, the copyright holders of this library give you
|
||
|
* permission to link this library with independent modules to produce an
|
||
|
* executable, regardless of the license terms of these independent
|
||
|
* modules, and to copy and distribute the resulting executable under
|
||
|
* terms of your choice, provided that you also meet, for each linked
|
||
|
* independent module, the terms and conditions of the license of that
|
||
|
* module. An independent module is a module which is not derived from
|
||
|
* or based on this library. If you modify this library, you may extend
|
||
|
* this exception to your version of the library, but you are not
|
||
|
* obligated to do so. If you do not wish to do so, delete this
|
||
|
* exception statement from your version.
|
||
|
*/
|
||
|
|
||
|
package com.ivmaisoft.jcgo;
|
||
|
|
||
|
import java.util.Enumeration;
|
||
|
|
||
|
/**
|
||
|
* This is the pass one context record.
|
||
|
*/
|
||
|
|
||
|
final class Context {
|
||
|
|
||
|
String fileName;
|
||
|
|
||
|
private/* final */ObjQueue importsSingle;
|
||
|
|
||
|
private/* final */ObjQueue importsOnDemand;
|
||
|
|
||
|
private BranchContext currentBranch;
|
||
|
|
||
|
String packageName = "";
|
||
|
|
||
|
ClassDefinition currentClass;
|
||
|
|
||
|
Term passZeroMethodDefnTerm;
|
||
|
|
||
|
MethodDefinition currentMethod;
|
||
|
|
||
|
ExpressionType currentVarType;
|
||
|
|
||
|
ClassDefinition typeClassDefinition;
|
||
|
|
||
|
int typeDims;
|
||
|
|
||
|
int modifiers;
|
||
|
|
||
|
Term varInitializer;
|
||
|
|
||
|
boolean lvalue;
|
||
|
|
||
|
boolean setOnly;
|
||
|
|
||
|
boolean hasBreakSimple;
|
||
|
|
||
|
boolean hasBreakDeep;
|
||
|
|
||
|
boolean hasContinueSimple;
|
||
|
|
||
|
boolean hasContinueDeep;
|
||
|
|
||
|
boolean isConditional;
|
||
|
|
||
|
LeftBrace localScope;
|
||
|
|
||
|
TryStatement currentTry;
|
||
|
|
||
|
ObjHashSet curTryChangedVars;
|
||
|
|
||
|
BreakableStmt currentLabelStmt;
|
||
|
|
||
|
TryStatement lastBreakableTry;
|
||
|
|
||
|
boolean breakableHidden;
|
||
|
|
||
|
int arrInitCount = -1;
|
||
|
|
||
|
boolean hasConstructor;
|
||
|
|
||
|
boolean insideAssertStmt;
|
||
|
|
||
|
ClassDefinition forClass;
|
||
|
|
||
|
int forceVmExc;
|
||
|
|
||
|
Context() {
|
||
|
importsSingle = new ObjQueue();
|
||
|
importsOnDemand = new ObjQueue();
|
||
|
}
|
||
|
|
||
|
private Context(ObjQueue importsSingle, ObjQueue importsOnDemand) {
|
||
|
this.importsSingle = importsSingle;
|
||
|
this.importsOnDemand = importsOnDemand;
|
||
|
}
|
||
|
|
||
|
void addImport(String name) {
|
||
|
if (name.endsWith(".*")) {
|
||
|
importsOnDemand.addLast(name.substring(0, name.length() - 1));
|
||
|
} else {
|
||
|
importsSingle.addLast(name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Context cloneForClass(ClassDefinition classDefn, ClassDefinition forClass) {
|
||
|
Context context = new Context(importsSingle, importsOnDemand);
|
||
|
context.fileName = fileName;
|
||
|
context.packageName = packageName;
|
||
|
context.currentClass = classDefn;
|
||
|
context.forClass = forClass;
|
||
|
return context;
|
||
|
}
|
||
|
|
||
|
void initBranch() {
|
||
|
currentBranch = new BranchContext();
|
||
|
addAccessedClass(Main.dict.get(Names.JAVA_LANG_CLASS));
|
||
|
currentBranch.accessedClasses.addElement(Main.dict
|
||
|
.get(Names.JAVA_LANG_STRING));
|
||
|
addAccessedClass(currentClass);
|
||
|
}
|
||
|
|
||
|
BranchContext saveBranch() {
|
||
|
BranchContext oldBranch = currentBranch;
|
||
|
Term.assertCond(oldBranch != null);
|
||
|
currentBranch = new BranchContext(oldBranch);
|
||
|
return oldBranch;
|
||
|
}
|
||
|
|
||
|
BranchContext swapBranch(BranchContext oldBranch) {
|
||
|
BranchContext otherBranch = currentBranch;
|
||
|
Term.assertCond(otherBranch != null);
|
||
|
currentBranch = oldBranch;
|
||
|
return otherBranch;
|
||
|
}
|
||
|
|
||
|
void intersectBranch(BranchContext otherBranch) {
|
||
|
Term.assertCond(currentBranch != null && otherBranch != null);
|
||
|
currentBranch.intersectWith(otherBranch, forClass);
|
||
|
}
|
||
|
|
||
|
void unionBranch(BranchContext otherBranch) {
|
||
|
Term.assertCond(currentBranch != null && otherBranch != null);
|
||
|
currentBranch.unionWith(otherBranch, false, false);
|
||
|
}
|
||
|
|
||
|
void unionBranchExceptLocals(BranchContext otherBranch, boolean isThis) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
currentBranch.unionWith(otherBranch, true, isThis);
|
||
|
}
|
||
|
|
||
|
boolean containsAccessedClass(ClassDefinition cd) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
ObjVector accessedClasses = currentBranch.accessedClasses;
|
||
|
int i = accessedClasses.identityLastIndexOf(cd);
|
||
|
return i >= 0 && (i == 0 || accessedClasses.elementAt(i - 1) != cd);
|
||
|
}
|
||
|
|
||
|
boolean addAccessedClass(ClassDefinition cd) {
|
||
|
Term.assertCond(currentBranch != null && cd != null);
|
||
|
ObjVector accessedClasses = currentBranch.accessedClasses;
|
||
|
if (cd.objectSize() != Type.CLASSINTERFACE)
|
||
|
return true;
|
||
|
ClassDefinition cd2 = cd;
|
||
|
do {
|
||
|
int i = accessedClasses.identityLastIndexOf(cd2);
|
||
|
if (i >= 0) {
|
||
|
if (i == 0 || accessedClasses.elementAt(i - 1) != cd2)
|
||
|
return cd2 == cd;
|
||
|
accessedClasses.removeElementAt(i);
|
||
|
} else {
|
||
|
accessedClasses.addElement(cd2);
|
||
|
}
|
||
|
} while (!cd.isInterface() && (cd2 = cd2.superClass(forClass)) != null);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
boolean addAccessedClassField(VariableDefinition v) {
|
||
|
ClassDefinition cd = v.definingClass();
|
||
|
if (containsAccessedClass(cd))
|
||
|
return true;
|
||
|
if (!v.isLiteral()) {
|
||
|
addAccessedClass(cd);
|
||
|
return false;
|
||
|
}
|
||
|
if (v.isJavaConstant())
|
||
|
return true;
|
||
|
ObjVector accessedClasses = currentBranch.accessedClasses;
|
||
|
if (accessedClasses.identityLastIndexOf(cd) >= 0)
|
||
|
return true;
|
||
|
accessedClasses.addElement(cd);
|
||
|
accessedClasses.addElement(cd);
|
||
|
if (!cd.isInterface()) {
|
||
|
while ((cd = cd.superClass(forClass)) != null
|
||
|
&& accessedClasses.identityLastIndexOf(cd) < 0) {
|
||
|
accessedClasses.addElement(cd);
|
||
|
accessedClasses.addElement(cd);
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void setVarNotNull(VariableDefinition v) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
if (v.isLocalOrParam() || v.isFinalVariable()) {
|
||
|
ObjVector nonNullVars = currentBranch.nonNullVars;
|
||
|
if (nonNullVars.identityLastIndexOf(v) < 0) {
|
||
|
nonNullVars.addElement(v);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void clearVarNotNull(VariableDefinition v) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
ObjVector nonNullVars = currentBranch.nonNullVars;
|
||
|
int index = nonNullVars.identityLastIndexOf(v);
|
||
|
if (index >= 0) {
|
||
|
nonNullVars.removeElementAt(index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
boolean isVarNotNull(VariableDefinition v) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
return currentBranch.nonNullVars.identityLastIndexOf(v) >= 0;
|
||
|
}
|
||
|
|
||
|
void setActualType(VariableDefinition v, ExpressionType actualType) {
|
||
|
Term.assertCond(currentBranch != null && actualType != null);
|
||
|
int s0;
|
||
|
if ((v.isLocalOrParam() || v.isFinalVariable())
|
||
|
&& ((s0 = v.exprType().objectSize()) == Type.CLASSINTERFACE || s0 == Type.OBJECTARRAY)) {
|
||
|
ObjVector actTypeVars = currentBranch.actTypeVars;
|
||
|
int index = actTypeVars.identityLastIndexOf(v);
|
||
|
if (index >= 0) {
|
||
|
currentBranch.varActualTypes.setElementAt(actualType, index);
|
||
|
} else {
|
||
|
actTypeVars.addElement(v);
|
||
|
currentBranch.varActualTypes.addElement(actualType);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void resetVarForLoopOrTry(VariableDefinition v) {
|
||
|
clearVarNotNull(v);
|
||
|
ObjVector actTypeVars = currentBranch.actTypeVars;
|
||
|
int index = actTypeVars.identityLastIndexOf(v);
|
||
|
if (index >= 0) {
|
||
|
actTypeVars.removeElementAt(index);
|
||
|
currentBranch.varActualTypes.removeElementAt(index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ExpressionType getActualType(VariableDefinition v) {
|
||
|
Term.assertCond(currentBranch != null);
|
||
|
return currentBranch.getActualType(v);
|
||
|
}
|
||
|
|
||
|
ClassDefinition resolveClass(String name, boolean allowNotFound,
|
||
|
boolean checkFields) {
|
||
|
int i = name.indexOf('.', 0);
|
||
|
String first = i >= 0 ? name.substring(0, i) : name;
|
||
|
String qualified = null;
|
||
|
if (localScope != null) {
|
||
|
qualified = localScope.resolveLocalClass(first);
|
||
|
}
|
||
|
if (qualified == null) {
|
||
|
ClassDefinition cd = currentClass;
|
||
|
while (cd != null) {
|
||
|
LeftBrace scope = cd.outerScope();
|
||
|
if (scope != null) {
|
||
|
qualified = scope.resolveLocalClass(first);
|
||
|
if (qualified != null)
|
||
|
break;
|
||
|
}
|
||
|
qualified = cd.resolveInnerClass(first, checkFields, forClass);
|
||
|
if (qualified != null)
|
||
|
break;
|
||
|
cd = cd.outerClass();
|
||
|
}
|
||
|
}
|
||
|
if (qualified != null && qualified.length() == 0)
|
||
|
return null;
|
||
|
if (qualified == null || Main.dict.get(qualified).outerClass() == null) {
|
||
|
first = getQualifiedName(first);
|
||
|
if (first != null) {
|
||
|
qualified = first;
|
||
|
}
|
||
|
}
|
||
|
if (i < 0) {
|
||
|
if (qualified == null) {
|
||
|
if (!allowNotFound)
|
||
|
return null;
|
||
|
qualified = packageName + name;
|
||
|
}
|
||
|
return Main.dict.get(qualified);
|
||
|
}
|
||
|
do {
|
||
|
if (qualified != null && Main.dict.exists(qualified)) {
|
||
|
qualified = Main.dict.get(qualified).resolveInnerClass(
|
||
|
name.substring(i + 1), checkFields, forClass);
|
||
|
if (qualified != null)
|
||
|
return qualified.length() > 0 ? Main.dict.get(qualified)
|
||
|
: null;
|
||
|
}
|
||
|
i = name.indexOf('.', i + 1);
|
||
|
if (i < 0)
|
||
|
break;
|
||
|
qualified = name.substring(0, i);
|
||
|
} while (true);
|
||
|
return allowNotFound || Main.dict.exists(name) ? Main.dict.get(name)
|
||
|
: null;
|
||
|
}
|
||
|
|
||
|
private String getQualifiedName(String id) {
|
||
|
String dotId = "." + id;
|
||
|
String qualified;
|
||
|
Enumeration en = importsSingle.elements();
|
||
|
while (en.hasMoreElements()) {
|
||
|
qualified = (String) en.nextElement();
|
||
|
if (qualified.endsWith(dotId)) {
|
||
|
id = qualified;
|
||
|
dotId = "";
|
||
|
int i;
|
||
|
while (!Main.dict.exists(qualified)) {
|
||
|
i = qualified.lastIndexOf('.');
|
||
|
if (i < 0)
|
||
|
return id;
|
||
|
dotId = "$" + qualified.substring(i + 1) + dotId;
|
||
|
qualified = qualified.substring(0, i);
|
||
|
}
|
||
|
return qualified + dotId;
|
||
|
}
|
||
|
}
|
||
|
qualified = packageName + id;
|
||
|
if (!Main.dict.exists(qualified)) {
|
||
|
Enumeration en2 = importsOnDemand.elements();
|
||
|
while (en2.hasMoreElements()) {
|
||
|
qualified = (String) en2.nextElement();
|
||
|
int i = qualified.length() - 1;
|
||
|
qualified = qualified + id;
|
||
|
if (Main.dict.exists(qualified)
|
||
|
&& Main.dict.get(qualified).isPublic())
|
||
|
return qualified;
|
||
|
do {
|
||
|
qualified = qualified.substring(0, i) + "$"
|
||
|
+ qualified.substring(i + 1);
|
||
|
if (Main.dict.existsOrInner(qualified))
|
||
|
return qualified;
|
||
|
i = qualified.lastIndexOf('.', i - 1);
|
||
|
} while (i > 0);
|
||
|
}
|
||
|
qualified = Names.JAVA_LANG_0 + id;
|
||
|
if (!Main.dict.exists(qualified)) {
|
||
|
qualified = Main.dict.exists(id) ? id : null;
|
||
|
}
|
||
|
}
|
||
|
return qualified;
|
||
|
}
|
||
|
}
|