PageRenderTime 296ms CodeModel.GetById 121ms app.highlight 14ms RepoModel.GetById 157ms app.codeStats 0ms

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

http://github.com/nddrylliog/ooc
Java | 149 lines | 114 code | 30 blank | 5 comment | 30 complexity | bd2bcff41e0a164f1945b82b1e3c8bf9 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 Match extends Expression implements MustBeResolved {
 12
 13	private Type type;
 14	protected NodeList<Case> cases;
 15	protected Expression expr;
 16
 17	public Match(Expression expr, Token startToken) {
 18		super(startToken);
 19		if(expr == null) {
 20			this.expr = new BoolLiteral(true, this.startToken);
 21		} else {
 22			this.expr = expr;
 23		}
 24		this.cases = new NodeList<Case>();
 25	}
 26	
 27	@Override
 28	public boolean replace(Node oldie, Node kiddo) {
 29		if(oldie == expr) {
 30			expr = (Expression) kiddo;
 31			return true;
 32		}
 33		return false;
 34	}
 35
 36	public void accept(Visitor visitor) throws IOException {
 37		visitor.visit(this);
 38	}
 39
 40	public void acceptChildren(Visitor visitor) throws IOException {
 41		expr.accept(visitor);
 42		cases.accept(visitor);
 43	}
 44
 45	public boolean hasChildren() {
 46		return true;
 47	}
 48	
 49	public NodeList<Case> getCases() {
 50		return cases;
 51	}
 52	
 53	public Expression getExpr() {
 54		return expr;
 55	}
 56
 57	public Type getType() {
 58		return type;
 59	}
 60
 61	public boolean isResolved() {
 62		return false;
 63	}
 64 
 65	public Response resolve(NodeList<Node> stack, Resolver res, boolean fatal) {
 66		
 67		Node parent = stack.peek();
 68		
 69		if(type == null) resolveType(stack, res, fatal);
 70		
 71		if(type == null && !(parent instanceof Line)) {
 72			if(fatal) {
 73				throw new OocCompilationError(this, stack, "Couldn't figure out type of match");
 74			}
 75			return Response.LOOP;
 76		}
 77		
 78		if(parent instanceof Line) {
 79			// alright =)
 80		} else if(parent instanceof VariableDecl) {
 81			VariableDecl vDecl = (VariableDecl) stack.get(stack.find(VariableDecl.class));
 82			vDecl.setType(vDecl.getType()); // fixate the type
 83			addAfterLine(stack, this);
 84			VariableAccess varAcc = new VariableAccess(vDecl, parent.startToken);
 85			toAssign(stack, varAcc);
 86			stack.peek().replace(this, null);
 87		} else if(parent instanceof Assignment) {
 88			// it's alright =)
 89		} else {
 90			// we're being USED! as an expression somewhere, let's unwrap to a varDecl.
 91			VariableDecl varDecl = new VariableDecl(getType(), generateTempName("match", stack), startToken, null);
 92			addBeforeLine(stack, varDecl);
 93			addBeforeLine(stack, this);
 94			VariableAccess varAcc = new VariableAccess(varDecl, startToken);
 95			toAssign(stack, varAcc);
 96			stack.peek().replace(this, varAcc);
 97		}
 98		
 99		return Response.OK;
100		
101	}
102
103	private void resolveType(NodeList<Node> stack, Resolver res, boolean fatal) {
104		
105		int funcIndex = stack.find(FunctionDecl.class);
106		int returnIndex = stack.find(ValuedReturn.class);
107		
108		if(funcIndex != -1 && returnIndex != -1) {
109			FunctionDecl funcDecl = (FunctionDecl) stack.get(funcIndex);
110			if(funcDecl.getReturnType().isGeneric()) {
111				type = funcDecl.getReturnType();
112			}
113		}
114		
115		if(type == null) {
116		
117			// TODO make it more intelligent e.g. cycle through all cases and
118			// check that all types are compatible and find a common denominator
119			if(cases.isEmpty()) return;
120			Case first = cases.getFirst();
121			if(first.getBody().isEmpty()) return;
122			Statement statement = first.getBody().getFirst().getStatement();
123			if(!(statement instanceof Expression)) return;
124			type = ((Expression) statement).getType();
125			
126		}
127		
128	}
129
130	private void toAssign(NodeList<Node> stack, VariableAccess varAcc)
131			throws OocCompilationError {
132		for(Case case1: cases) {
133			if(case1.getBody().isEmpty()) {
134				throw new OocCompilationError(case1, stack, "Empty case in a match used as an expression!");
135			}
136			Line last = case1.getBody().getLast();
137			if(!(last.getStatement() instanceof Expression)) {
138				throw new OocCompilationError(case1, stack, "In a match used as an expression, last statement of a case isn't an expression!");	
139			}
140			case1.getBody().replace(last, new Line(new Assignment(varAcc, (Expression) last.getStatement(), last.startToken)));
141		}
142	}
143	
144	@Override
145	public String toString() {
146		return "match "+expr+", with "+cases.size()+" cases";
147	}
148
149}