com.strobel.reflection.emit.ScopeTree Maven / Gradle / Ivy
/*
* ScopeTree.java
*
* Copyright (c) 2012 Mike Strobel
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.reflection.emit;
import java.util.Arrays;
/**
* @author strobelm
*/
@SuppressWarnings("PackageVisibleField")
final class ScopeTree {
ScopeTree() {
_openScopeCount = 0;
_count = 0;
}
/*
* Find the current active lexical scope. For example, if we have
* "Open Open Open Close", we will return 1 as the second BeginScope
* is currently active.
*/
int getCurrentActiveScopeIndex() {
int closeCount = 0;
int i = _count - 1;
if (_count == 0) {
return -1;
}
for (; closeCount > 0 || _scopeActions[i] == ScopeAction.Close; i--) {
if (_scopeActions[i] == ScopeAction.Open) {
closeCount--;
}
else {
closeCount++;
}
}
return i;
}
void addLocalSymInfoToCurrentScope(
final String name,
final byte[] signature,
final int slot,
final int startOffset,
final int endOffset) {
final int i = getCurrentActiveScopeIndex();
if (_localSymInfos[i] == null) {
_localSymInfos[i] = new LocalSymInfo();
}
_localSymInfos[i].addLocalSymInfo(name, signature, slot, startOffset, endOffset);
}
void addPackageImportToCurrentScope(final String packageName) {
final int i = getCurrentActiveScopeIndex();
if (_localSymInfos[i] == null) {
_localSymInfos[i] = new LocalSymInfo();
}
_localSymInfos[i].addPackageImport(packageName);
}
void addScopeInfo(final ScopeAction action, final int offset) {
if (action == ScopeAction.Close && _openScopeCount <= 0) {
throw new IllegalStateException("Tried to close unmatched symbol scope.");
}
// make sure that arrays are large enough to hold addition info
ensureCapacity();
_scopeActions[_count] = action;
_offsets[_count] = offset;
_localSymInfos[_count] = null;
_count++;
if (action == ScopeAction.Open) {
_openScopeCount++;
}
else {
_openScopeCount--;
}
}
/**
* Helper to ensure arrays are large enough
*/
void ensureCapacity() {
if (_count == 0) {
// First time. Allocate the arrays.
_offsets = new int[InitialSize];
_scopeActions = new ScopeAction[InitialSize];
_localSymInfos = new LocalSymInfo[InitialSize];
}
else if (_count == _offsets.length) {
// the arrays are full. Enlarge the arrays
// It would probably be simpler to just use Lists here.
final int newSize = _count * 2;
_offsets = Arrays.copyOf(_offsets, newSize);
_scopeActions = Arrays.copyOf(_scopeActions, newSize);
_localSymInfos = Arrays.copyOf(_localSymInfos, newSize);
}
}
/*
void emitScopeTree(final ISymbolWriter symWriter) {
int i;
for (i = 0; i < _count; i++) {
if (_scopeActions[i] == ScopeAction.Open) {
symWriter.openScope(_offsets[i]);
}
else {
symWriter.closeScope(_offsets[i]);
}
if (_localSymInfos[i] != null) {
_localSymInfos[i].emitLocalSymInfo(symWriter);
}
}
}
*/
int[] _offsets; // array of offsets
ScopeAction[] _scopeActions; // array of scope actions
int _count; // how many entries in the arrays are occupied
int _openScopeCount; // keep track how many scopes are open
LocalSymInfo[] _localSymInfos; // keep track debugging local information
final static int InitialSize = 16;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy