package eu.wietsevenema.lang.oberon.interpreter; import java.util.HashMap; import java.util.Map; import eu.wietsevenema.lang.oberon.ast.types.VarType; import eu.wietsevenema.lang.oberon.exceptions.SymbolAlreadyDeclaredException; import eu.wietsevenema.lang.oberon.exceptions.SymbolNotDeclaredException; import eu.wietsevenema.lang.oberon.exceptions.TypeNotDeclaredException; import eu.wietsevenema.lang.oberon.interpreter.values.Value; public class InterpreterScope implements Scope { InterpreterScope parent; private Map<String, Bindable> symbols = new HashMap<String, Bindable>(); private Map<String, VarType> types = new HashMap<String, VarType>(); public InterpreterScope() { } public InterpreterScope(InterpreterScope parent) { this.parent = parent; } @Override public InterpreterScope getParent() { return parent; } @Override public VarType lookupType(String symbol) throws TypeNotDeclaredException { VarType result = types.get(symbol); if (result == null && this.parent != null) { result = parent.lookupType(symbol); } if (result == null) { throw new TypeNotDeclaredException("Type '" + symbol + "' is not a builtin type nor declared."); } return result; } @Override public void declareType(String symbol, VarType type) { assert type != null; types.put(symbol, type); } private Bindable lookupSymbol(String symbol) throws SymbolNotDeclaredException { Bindable result = symbols.get(symbol); if (result == null && this.parent != null) { result = parent.lookupSymbol(symbol); } if (result == null) { throw new SymbolNotDeclaredException(); } return result; } public Value lookupValue(String symbol) throws SymbolNotDeclaredException { ValueReference valueRef = (ValueReference) this.lookupSymbol(symbol); return valueRef.getValue(); } public ValueReference lookupValueReference(String symbol) throws SymbolNotDeclaredException { return (ValueReference) lookupSymbol(symbol); } @Override public Procedure lookupProc(String symbol) throws SymbolNotDeclaredException { return (Procedure) lookupSymbol(symbol); } private void declareSymbol(String symbol, Bindable bindable) throws SymbolAlreadyDeclaredException { assert bindable != null; if (!symbols.containsKey(symbol)) { symbols.put(symbol, bindable); } else { throw new SymbolAlreadyDeclaredException(); } } public void declareValue(String symbol, Value value) throws SymbolAlreadyDeclaredException { this.declareSymbol(symbol, new ValueReference(value)); } public void declareValueReference(String symbol, ValueReference valueRef) throws SymbolAlreadyDeclaredException { declareSymbol(symbol, valueRef); } @Override public void declareProc(String symbol, Procedure proc) throws SymbolAlreadyDeclaredException { declareSymbol(symbol, proc); } }