package slangc.model.statements; import slang.data.List; import slangc.api.BytecodeInstructionWriter; import slangc.api.Reporter; import slangc.bytecode.TypeSignature; import slangc.model.InnerTypeScope; import slangc.model.LocalVariableSlot; import slangc.model.MemberModel; import slangc.model.StatementModel; import slangc.model.StatementOwner; import slangc.model.TypeModel; import slangc.parser.Branch; import slangc.parser.Node; public class VariableStatement extends StatementModel implements StatementOwner { private TypeModel type; private List slots = new List(); public VariableStatement(StatementOwner owner, Branch source) { super(owner, source); type = owner.resolveType(source.getSubnode(1)); Branch l = (Branch) source.getSubnode(2); for (int i = 0; i < l.countSubnodes(); i++) { slots.append(new LocalVariableSlot(this, (Branch)l.getSubnode(i), type)); } } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Variable statement:"); // do not recurse: type.dump(reporter, indent + incr, incr); for (int i = 0; i < slots.count(); i++) { slots.get(i).dump(reporter, indent + incr, incr); } } @Override public int resolveExpressions() { int nresolved = 0; for (int i = 0; i < slots.count(); i++) { nresolved += slots.get(i).resolveExpressions(); } return nresolved; } public boolean hasVariable(String name) { for (int i = 0; i < slots.count(); i++) { if (slots.get(i).getName().equals(name)) { return true; } } return false; } public LocalVariableSlot getVariable(String name) { for (int i = 0; i < slots.count(); i++) { if (slots.get(i).getName().equals(name)) { return slots.get(i); } } return null; } //@Override public InnerTypeScope getTypeScope() { return getOwner().getTypeScope(); } //@Override public TypeModel resolveType(Node subnode) { return getOwner().resolveType(subnode); } public MethodModel[] lookupSimpleMethod(String name) { // TODO: Better interface support return super.lookupSimpleMethod(name); } //@Override public MemberModel getMethodOrField() { return getOwner().getMethodOrField(); } @Override public void innerGenerate(BytecodeInstructionWriter w) { // The first pass declares each of the variables (this will reset them to default values) for (int i = 0; i < slots.count(); i++) { LocalVariableSlot s = slots.get(i); w.genDeclareLocal(s.getStorageType().getTypeSignature(), s.getIndex()); } // The second pass generates any initialisers for (int i = 0; i < slots.count(); i++) { LocalVariableSlot s = slots.get(i); if (s.hasInitialiser()) { TypeSignature storing = s.getInitialiser().generate(w); if (!storing.mappableEquals(s.getInitialiser().getResult().getValueTypeWithNullType(s.getStorageType()).getTypeSignature())) { w.genConvert(storing, s.getStorageType().getTypeSignature()); storing = s.getStorageType().getTypeSignature(); } w.genStoreLocalOrParam(s.getStorageType().getTypeSignature(), s.getIndex()); } } } }