PageRenderTime 59ms CodeModel.GetById 16ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/ooc/frontend/model/Foreach.java

http://github.com/nddrylliog/ooc
Java | 177 lines | 140 code | 35 blank | 2 comment | 31 complexity | 442bac649caf95497d02cd373f7026a3 MD5 | raw file
  1package org.ooc.frontend.model;
  2
  3import java.io.IOException;
  4
  5import org.ooc.frontend.Visitor;
  6import org.ooc.frontend.model.interfaces.MustBeResolved;
  7import org.ooc.frontend.model.tokens.Token;
  8import org.ooc.middle.OocCompilationError;
  9import org.ooc.middle.hobgoblins.Resolver;
 10
 11public class Foreach extends ControlStatement implements MustBeResolved {
 12
 13	protected Expression variable;
 14	protected Expression collection; // must be of type Range or Iterable
 15	
 16	public Foreach(Expression variable, Expression collection, Token startToken) {
 17		super(startToken);
 18		this.variable = variable;
 19		this.collection = collection;
 20	}
 21	
 22	public Expression getVariable() {
 23		return variable;
 24	}
 25	
 26	public void setVariable(VariableDecl variable) {
 27		this.variable = variable;
 28	}
 29	
 30	public Expression getCollection() {
 31		return collection;
 32	}
 33	
 34	public void setCollection(Expression range) {
 35		this.collection = range;
 36	}
 37	
 38	public void accept(Visitor visitor) throws IOException {
 39		visitor.visit(this);
 40	}
 41	
 42	public boolean hasChildren() {
 43		return true;
 44	}
 45	
 46	public void acceptChildren(Visitor visitor) throws IOException {
 47		// we don't want to resolve VariableAccesses - they should create new
 48		// variables, this fixes #64 http://github.com/nddrylliog/ooc/issues#issue/64
 49		if(variable instanceof VariableDecl) {
 50			variable.accept(visitor);
 51		}
 52		collection.accept(visitor);
 53		body.accept(visitor);
 54	}
 55	
 56	@Override
 57	public boolean replace(Node oldie, Node kiddo) {
 58		if(oldie == variable) {
 59			variable = (Expression) kiddo;
 60			return true;
 61		}
 62		
 63		if(oldie == collection) {
 64			collection = (Expression) kiddo;
 65			return true;
 66		}
 67		
 68		return false;
 69	}
 70	
 71	@Override
 72	public VariableDecl getVariable(String name) {
 73		if(variable instanceof VariableDecl) {
 74			VariableDecl varDecl = (VariableDecl) variable;
 75			if(varDecl.getName().equals(name)) return varDecl;
 76		} else if(variable instanceof VariableAccess) {
 77			VariableAccess varAcc = (VariableAccess) variable;
 78			if(varAcc.getName().equals(name)) return (VariableDecl) varAcc.getRef();
 79		}
 80		return super.getVariable(name);
 81	}
 82	
 83	@Override
 84	public void getVariables(NodeList<VariableDecl> variables) {
 85		if(variable instanceof VariableDecl) {
 86			VariableDecl varDecl = (VariableDecl) variable;
 87			variables.add(varDecl);
 88		} else if(variable instanceof VariableAccess) {
 89			VariableAccess varAcc = (VariableAccess) variable;
 90			if(varAcc.getRef() != null)
 91				variables.add((VariableDecl) varAcc.getRef());
 92		}
 93		super.getVariables(variables);
 94	}
 95
 96	public boolean isResolved() {
 97		return false;
 98	}
 99
100	@SuppressWarnings("unchecked")
101	public Response resolve(NodeList<Node> stack, Resolver res, boolean fatal) {
102		
103		if(collection.getType() == null ||
104		  (!collection.getType().getName().equals("Range") && collection.getType().getRef() == null)) {
105			if(fatal) {
106				throw new OocCompilationError(collection, stack, "Couldn't resolve type "
107						+collection.getType()+" of foreach's collection "+collection+" (ref = "
108							+(collection.getType() == null ? "null" : collection.getType().getRef()));
109			}
110			return Response.LOOP;
111		}
112		
113		if(collection.getType().getPointerLevel() > 0) {
114			Type targetType = new Type("ArrayList", collection.startToken);
115			targetType.getTypeParams().add(new TypeAccess(collection.getType().dereference(), collection.startToken));
116			collection = new Cast(collection, targetType, collection.startToken);
117			return Response.LOOP;
118		}
119
120		if(collection instanceof RangeLiteral) {
121			return Response.OK;
122		}
123		
124		MemberCall iterCall = new MemberCall(collection, "iterator", "", startToken);
125		Response resp = Response.LOOP;
126		int gardeFou = 10;
127		while(resp == Response.LOOP) {
128			resp = iterCall.resolve(stack, res, true);
129			gardeFou--;
130			if(gardeFou <= 0) return Response.LOOP;
131		}
132		
133		Type iterType = iterCall.getType();
134		iterType.resolve(stack, res, false);
135		if(iterType.getRef() == null) {
136			if(fatal) throw new OocCompilationError(this, stack, "couldn't resolve iterType "+iterType);
137			return Response.LOOP;
138		}
139		
140		int lineIndex = stack.find(Line.class);
141		Line line = (Line) stack.get(lineIndex);
142		NodeList<Line> list = (NodeList<Line>) stack.get(lineIndex - 1);
143		
144		Block block = new Block(startToken);
145		
146		VariableDecl vdfe = new VariableDecl(iterType, generateTempName("iter", stack), iterCall, startToken, null);
147		VariableAccess iterAcc = new VariableAccess(vdfe, startToken);
148		iterAcc.setRef(vdfe);
149		
150		MemberCall hasNextCall = new MemberCall(iterAcc, "hasNext", "", startToken);
151		hasNextCall.resolve(stack, res, true);
152		While while1 = new While(hasNextCall, startToken);
153		
154		MemberCall nextCall = new MemberCall(iterAcc, "next", "", startToken);
155		nextCall.resolve(stack, res, true);
156		
157		if(variable instanceof VariableAccess) {
158			VariableAccess varAcc = (VariableAccess) variable;
159			if(varAcc.getRef() == null) {
160				Type innerType = iterCall.getType().getTypeParams().getFirst().getType();
161				VariableDecl varDecl = new VariableDecl(innerType, varAcc.getName(), varAcc.startToken, null);
162				block.getBody().add(0, new Line(varDecl));
163			}
164		}
165		
166		while1.getBody().add(new Line(new Assignment(variable, nextCall, startToken)));
167		while1.getBody().addAll(getBody());
168		
169		list.replace(line, new Line(block));
170		block.getBody().add(new Line(vdfe));
171		block.getBody().add(new Line(while1));
172		
173		return Response.LOOP;
174		
175	}
176	
177}