EMMA Coverage Report (generated Sat Dec 08 18:13:49 GMT 2007)
[all classes][uk.co.zonetora.fj.typecheck]

COVERAGE SUMMARY FOR SOURCE FILE [TypeCheck.java]

nameclass, %method, %block, %line, %
TypeCheck.java25%  (1/4)30%  (6/20)29%  (117/401)38%  (29/76)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class TypeCheck$10%   (0/1)0%   (0/2)0%   (0/21)0%   (0/3)
TypeCheck$1 (TypeCheck, ClassName): void 0%   (0/1)0%   (0/9)0%   (0/2)
run (): void 0%   (0/1)0%   (0/12)0%   (0/1)
     
class TypeCheck$20%   (0/1)0%   (0/3)0%   (0/20)0%   (0/3)
TypeCheck$2 (TypeCheck, MethodInvocation): void 0%   (0/1)0%   (0/9)0%   (0/2)
access$1 (TypeCheck$2): TypeCheck 0%   (0/1)0%   (0/3)0%   (0/1)
run (Method): Runnable 0%   (0/1)0%   (0/8)0%   (0/1)
     
class TypeCheck$2$10%   (0/1)0%   (0/2)0%   (0/95)0%   (0/13)
TypeCheck$2$1 (TypeCheck$2, Method, MethodInvocation): void 0%   (0/1)0%   (0/12)0%   (0/2)
run (): void 0%   (0/1)0%   (0/83)0%   (0/11)
     
class TypeCheck100% (1/1)46%  (6/13)44%  (117/265)47%  (29/62)
access$0 (TypeCheck): void 0%   (0/1)0%   (0/3)0%   (0/1)
access$1 (TypeCheck): List 0%   (0/1)0%   (0/4)0%   (0/1)
access$2 (TypeCheck): ClassTable 0%   (0/1)0%   (0/3)0%   (0/1)
access$3 (TypeCheck): Deque 0%   (0/1)0%   (0/3)0%   (0/1)
appyRule (Cast): void 0%   (0/1)0%   (0/32)0%   (0/8)
appyRule (FieldAccess): void 0%   (0/1)0%   (0/28)0%   (0/7)
appyRule (MethodInvocation): void 0%   (0/1)0%   (0/31)0%   (0/8)
appyRule (Variable): void 100% (1/1)54%  (15/28)83%  (5/6)
appyRule (ObjectCreation): void 100% (1/1)58%  (42/73)62%  (8/13)
TypeCheck (TypeEnvironment, ClassTable): void 100% (1/1)100% (22/22)100% (7/7)
preserveTypeStack (): void 100% (1/1)100% (9/9)100% (2/2)
restoreTypeStack (): List 100% (1/1)100% (21/21)100% (5/5)
typeCheck (Term): ClassName 100% (1/1)100% (8/8)100% (2/2)

1package uk.co.zonetora.fj.typecheck;
2 
3import java.util.ArrayDeque;
4import java.util.ArrayList;
5import java.util.Deque;
6import java.util.List;
7 
8import uk.co.zonetora.fj.ast.analysis.DepthFirstAdapter;
9import uk.co.zonetora.fj.model.ArgumentName;
10import uk.co.zonetora.fj.model.Cast;
11import uk.co.zonetora.fj.model.ClassName;
12import uk.co.zonetora.fj.model.FieldAccess;
13import uk.co.zonetora.fj.model.Method;
14import uk.co.zonetora.fj.model.MethodInvocation;
15import uk.co.zonetora.fj.model.ObjectCreation;
16import uk.co.zonetora.fj.model.Term;
17import uk.co.zonetora.fj.model.Variable;
18import uk.co.zonetora.fj.passes.FJException;
19import uk.co.zonetora.fj.util.Arrow;
20import uk.co.zonetora.fj.util.Maybe;
21import uk.co.zonetora.fj.util.Tuple;
22 
23import static uk.co.zonetora.fj.util.ListUtil.*;
24 
25public class TypeCheck {
26 
27    private final Deque<ClassName> typeStack;
28    private final Deque<Deque<ClassName>> backupStack;
29    
30    private final TypeEnvironment typeEnvironment;
31    private final ClassTable classTable;
32    private boolean stupidWarningTriggered;
33    
34    public TypeCheck(TypeEnvironment typeEnvironment, ClassTable classTable) {
35        this.typeEnvironment = typeEnvironment;
36        this.classTable = classTable;
37        this.typeStack = new ArrayDeque<ClassName>();
38        this.backupStack = new ArrayDeque<Deque<ClassName>>();
39        
40        this.stupidWarningTriggered = false;
41    }
42 
43    public ClassName typeCheck(Term code) throws FJException {
44    
45        code.visit(this);
46        
47        return this.typeStack.pop();
48    }
49 
50    public void appyRule(Cast cast) {
51        cast.getCastedTerm().visit(this);
52        
53        ClassName castedTermType = this.typeStack.pop();
54        
55        ClassName typeToCastTo = cast.getTypeToCastTo();
56        
57        if(this.classTable.subtype(castedTermType, typeToCastTo)) {
58         /* ok */   
59        } else if(this.classTable.subtype(typeToCastTo, castedTermType)) {
60         /* ok */
61        } else {
62            this.stupidWarningTriggered = true;
63        }
64        
65        this.typeStack.push(typeToCastTo);
66        
67    }
68 
69    public void appyRule(FieldAccess access) {
70        
71        access.getPath().visit(this);
72        
73        ClassName pathType = this.typeStack.pop();
74        
75        try {
76            ClassName fieldType = this.classTable.lookupField(access.getFieldName(), pathType);
77            
78            this.typeStack.push(fieldType);
79            
80        } catch (FJException e) {
81            throw new FJTypeCheckException(e);
82        }
83        
84    }
85 
86 
87    public void appyRule(final MethodInvocation invocation) {
88        invocation.getPath().visit(this);
89        final ClassName pathType = this.typeStack.pop();
90        
91        Maybe<Method> m = this.classTable.mType(invocation.getMethodName(), pathType);
92        
93        m.maybe(
94                new Runnable() { 
95                    public void run() {
96                        throw new FJTypeCheckException("Can't find method in " + pathType);
97                    }
98                },
99                
100                new Arrow<Method, Runnable> () {
101                    public Runnable run(final Method arg) {
102                        return new Runnable() {
103                            public void run() {
104 
105                                if(arg.getArguments().size() != invocation.getArguments().size()) {
106                                    throw new FJTypeCheckException("Invoking a method with incorrect number of arguments");
107                                }
108                                
109                                preserveTypeStack();
110                                
111                                for(Term e : invocation.getArguments() ) {
112                                    e.visit(TypeCheck.this);
113                                }
114                                
115                                List<ClassName> argTypes = restoreTypeStack();
116                                
117                                for(Tuple<ClassName, ClassName> cnPair : zip(argTypes, mapFst(arg.getArguments()))) {
118                                    if(!TypeCheck.this.classTable.subtype(cnPair.getX(), cnPair.getY())) {
119                                        throw new FJTypeCheckException("Invoking a method with an argument that is not a subtype");
120                                    }
121                                }
122                                
123                                TypeCheck.this.typeStack.push(arg.getReturnType());
124                            }
125                        };
126                    }
127                }).run();
128                
129    }
130 
131    public void appyRule(ObjectCreation creation) {
132        List<ClassName> fieldTypes = mapFst(this.classTable.fields(creation.getNewClassName()));
133        List<Term> terms = creation.getArgumentTerms();
134        
135        if(fieldTypes.size() != terms.size()) {
136            throw new FJTypeCheckException("'new' with wrong number of arguments for the constructor");
137        }
138        
139        preserveTypeStack();
140        for(Term t : terms) {
141            t.visit(this);
142        }
143        List<ClassName> argTypes = restoreTypeStack();
144        
145        for(Tuple<ClassName, ClassName> cnPair : zip(argTypes, fieldTypes)) {
146            if(!this.classTable.subtype(cnPair.getX(), cnPair.getY())) {
147                throw new FJTypeCheckException("Invoking new with an argument that is not of the right type");
148            }
149        }
150        
151        this.typeStack.push(creation.getNewClassName());
152    }
153 
154    public void appyRule(Variable variable) {
155        ArgumentName arg = variable.getArgumentName();
156        
157        ClassName cn = this.typeEnvironment.getBinding(arg);
158        if(cn == null) { 
159            throw new FJTypeCheckException("Variable: " + arg + " is unknown");
160        }
161        
162        this.typeStack.push(cn);
163    }
164 
165    
166    private void preserveTypeStack() {
167        this.backupStack.push(new ArrayDeque<ClassName>(this.typeStack));
168    }
169 
170    private List<ClassName> restoreTypeStack() {
171        Deque<ClassName> old = this.backupStack.pop();
172        List<ClassName> current = new ArrayList<ClassName>(this.typeStack);
173        this.typeStack.clear();
174        this.typeStack.addAll(old);
175        return current;
176    }
177    
178 
179}

[all classes][uk.co.zonetora.fj.typecheck]
EMMA 2.0.5312 (C) Vladimir Roubtsov