cbc/net/loveruby/cflat/entity/ToplevelScope.java

134 lines
4.2 KiB
Java

package net.loveruby.cflat.entity;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.exception.*;
import java.util.*;
public class ToplevelScope extends Scope {
protected Map<String, Entity> entities;
protected List<DefinedVariable> staticLocalVariables; // cache
public ToplevelScope() {
super();
entities = new LinkedHashMap<String, Entity>();
staticLocalVariables = null;
}
public boolean isToplevel() {
return true;
}
public ToplevelScope toplevel() {
return this;
}
public Scope parent() {
return null;
}
/** Declare variable or function globally. */
// #@@range/declareEntity{
public void declareEntity(Entity entity) throws SemanticException {
Entity e = entities.get(entity.name());
if (e != null) {
throw new SemanticException("duplicated declaration: " +
entity.name() + ": " +
e.location() + " and " + entity.location());
}
entities.put(entity.name(), entity);
}
// #@@}
/** Define variable or function globally. */
// #@@range/defineEntity{
public void defineEntity(Entity entity) throws SemanticException {
Entity e = entities.get(entity.name());
if (e != null && e.isDefined()) {
throw new SemanticException("duplicated definition: " +
entity.name() + ": " +
e.location() + " and " + entity.location());
}
entities.put(entity.name(), entity);
}
// #@@}
/** Searches and gets entity searching scopes upto ToplevelScope. */
// #@@range/get{
public Entity get(String name) throws SemanticException {
Entity ent = entities.get(name);
if (ent == null) {
throw new SemanticException("unresolved reference: " + name);
}
return ent;
}
// #@@}
/** Returns a list of all global variables.
* "All global variable" means:
*
* * has global scope
* * defined or undefined
* * public or private
*/
public List<Variable> allGlobalVariables() {
List<Variable> result = new ArrayList<Variable>();
for (Entity ent : entities.values()) {
if (ent instanceof Variable) {
result.add((Variable)ent);
}
}
result.addAll(staticLocalVariables());
return result;
}
public List<DefinedVariable> definedGlobalScopeVariables() {
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
for (Entity ent : entities.values()) {
if (ent instanceof DefinedVariable) {
result.add((DefinedVariable)ent);
}
}
result.addAll(staticLocalVariables());
return result;
}
public List<DefinedVariable> staticLocalVariables() {
if (staticLocalVariables == null) {
staticLocalVariables = new ArrayList<DefinedVariable>();
for (LocalScope s : children) {
staticLocalVariables.addAll(s.staticLocalVariables());
}
Map<String, Integer> seqTable = new HashMap<String, Integer>();
for (DefinedVariable var : staticLocalVariables) {
Integer seq = seqTable.get(var.name());
if (seq == null) {
var.setSequence(0);
seqTable.put(var.name(), 1);
}
else {
var.setSequence(seq);
seqTable.put(var.name(), seq + 1);
}
}
}
return staticLocalVariables;
}
public void checkReferences(ErrorHandler h) {
for (Entity ent : entities.values()) {
if (ent.isDefined()
&& ent.isPrivate()
&& !ent.isConstant()
&& !ent.isRefered()) {
h.warn(ent.location(), "unused variable: " + ent.name());
}
}
// do not check parameters
for (LocalScope funcScope : children) {
for (LocalScope s : funcScope.children) {
s.checkReferences(h);
}
}
}
}