deep-c-rsc/JCGO/jtrsrc/com/ivmaisoft/jcgo/Context.java
2021-07-16 17:12:20 -05:00

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;
}
}