root/trunk/ProjectFortress/src/com/sun/fortress/compiler/StaticChecker.java @ 3835

Revision 3835, 14.8 KB (checked in by sukyoungryu, 6 months ago)

[type checker] Fixed small things in the Scala type checker. Matched some error messages from the Java type checker and the Scala type checker. Do not type check programs with syntax errors. Moved two tests from not_working_static_tests to compiler_tests.

Line 
1/*******************************************************************************
2    Copyright 2009 Sun Microsystems, Inc.,
3    4150 Network Circle, Santa Clara, California 95054, U.S.A.
4    All rights reserved.
5
6    U.S. Government Rights - Commercial software.
7    Government users are subject to the Sun Microsystems, Inc. standard
8    license agreement and applicable provisions of the FAR and its supplements.
9
10    Use is subject to license terms.
11
12    This distribution may include materials developed by third parties.
13
14    Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15    trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16 ******************************************************************************/
17
18package com.sun.fortress.compiler;
19
20import static com.sun.fortress.exceptions.InterpreterBug.bug;
21
22import java.util.ArrayList;
23import java.util.HashSet;
24import java.util.List;
25import java.util.Map;
26
27import com.sun.fortress.Shell;
28import com.sun.fortress.compiler.index.ApiIndex;
29import com.sun.fortress.compiler.index.ComponentIndex;
30import com.sun.fortress.compiler.typechecker.InferenceVarInserter;
31import com.sun.fortress.compiler.typechecker.InferenceVarReplacer;
32import com.sun.fortress.compiler.typechecker.TypeChecker;
33import com.sun.fortress.compiler.typechecker.TypeCheckerOutput;
34import com.sun.fortress.compiler.typechecker.TypeCheckerResult;
35import com.sun.fortress.compiler.typechecker.TypeEnv;
36import com.sun.fortress.compiler.typechecker.TypeNormalizer;
37import com.sun.fortress.compiler.typechecker.TypesUtil;
38import com.sun.fortress.compiler.typechecker.constraints.ConstraintUtil;
39import com.sun.fortress.compiler.typechecker.TypeAnalyzer;
40import com.sun.fortress.exceptions.StaticError;
41import com.sun.fortress.nodes.Api;
42import com.sun.fortress.nodes.APIName;
43import com.sun.fortress.nodes.Component;
44import com.sun.fortress.nodes.Node;
45import com.sun.fortress.nodes.Type;
46import com.sun.fortress.repository.FortressRepository;
47import com.sun.fortress.scala_src.typechecker.CoercionTest;
48import com.sun.fortress.scala_src.typechecker.ExportChecker;
49import com.sun.fortress.scala_src.typechecker.TraitTable;
50import com.sun.fortress.scala_src.typechecker.TypeHierarchyChecker;
51import com.sun.fortress.scala_src.typechecker.TypeWellFormedChecker;
52import com.sun.fortress.scala_src.typechecker.OverloadingChecker;
53import com.sun.fortress.scala_src.typechecker.STypeChecker;
54import com.sun.fortress.scala_src.typechecker.STypeCheckerFactory;
55import com.sun.fortress.scala_src.useful.Lists;
56import edu.rice.cs.plt.iter.IterUtil;
57import edu.rice.cs.plt.tuple.Option;
58import edu.rice.cs.plt.tuple.Pair;
59
60/**
61 * Verifies all static properties of a valid Fortress program that require
62 * interpreting types.  Assumes all names referring to APIs are fully-qualified,
63 * and that the other transformations handled by the {@link Disambiguator} have
64 * been performed.  In addition to checking the program, performs the following
65 * transformations:
66 * <ul>
67 * <li>All unknown placeholder types are provided explicit (inferred) values.</li>
68 * <li>Explicit coercions are added where needed. (Not yet!) </li>
69 * <li>Juxtapositions are given a binary structure.</li>
70 * <li>FieldRefs that refer to methods and that are followed by an argument expression
71 *     become MethodInvocations.</li>
72 * </li>
73 */
74public class StaticChecker {
75
76    public static class ApiResult extends StaticPhaseResult {
77        private final Map<APIName, ApiIndex> _apis;
78        private final List<APIName> _failedApis;
79        private final TypeCheckerOutput _typeCheckerOutput;
80
81        public ApiResult(Map<APIName, ApiIndex> apis,
82                               List<APIName> failedApis,
83                               Iterable<? extends StaticError> errors,
84                               TypeCheckerOutput typeCheckerOutput) {
85            super(errors);
86            _apis = apis;
87            _failedApis = failedApis;
88            _typeCheckerOutput = typeCheckerOutput;
89        }
90        public Map<APIName, ApiIndex> apis() { return _apis; }
91        public List<APIName> failed() { return _failedApis; }
92
93        public TypeCheckerOutput typeCheckerOutput() {
94            return this._typeCheckerOutput;
95        }
96    }
97
98    /**
99     * Check the given apis. To support circular references, the apis should appear
100     * in the given environment.
101     */
102    public static ApiResult checkApis(Map<APIName, ApiIndex> apis,
103                                      GlobalEnvironment env,
104                                      FortressRepository repository) {
105        List<APIName> failedApis = new ArrayList<APIName>();
106        Iterable<? extends StaticError> errors = new HashSet<StaticError>();
107        if ( Shell.getTypeChecking() == true &&
108             WellKnownNames.areCompilerLibraries() ) {
109            HashSet<Api> checkedApis = new HashSet<Api>();
110            TypeCheckerOutput type_checker_output = TypeCheckerOutput.emptyOutput();
111
112            for (APIName apiName : apis.keySet()) {
113                TypeCheckerResult checked = checkApi(apis.get(apiName), env, repository);
114                checkedApis.add((Api)checked.ast());
115                if (!checked.isSuccessful()) failedApis.add(apiName);
116                errors = IterUtil.compose(checked.errors(), errors);
117                type_checker_output = new TypeCheckerOutput( type_checker_output,
118                                                             checked.getTypeCheckerOutput() );
119            }
120            return new ApiResult
121                (IndexBuilder.buildApis(checkedApis,
122                                        System.currentTimeMillis()).apis(),
123                 failedApis,
124                 errors,
125                 type_checker_output);
126        } else
127            return new ApiResult(apis, failedApis, errors,
128                                 TypeCheckerOutput.emptyOutput());
129    }
130
131    public static class ComponentResult extends StaticPhaseResult {
132        private final Map<APIName, ComponentIndex> _components;
133        private final List<APIName> _failedComponents;
134        private final TypeCheckerOutput _typeCheckerOutput;
135
136        public ComponentResult(Map<APIName, ComponentIndex> components,
137                               List<APIName> failedComponents,
138                               Iterable<? extends StaticError> errors,
139                               TypeCheckerOutput typeCheckerOutput) {
140            super(errors);
141            _components = components;
142            _failedComponents = failedComponents;
143            _typeCheckerOutput = typeCheckerOutput;
144        }
145        public Map<APIName, ComponentIndex> components() { return _components; }
146        public List<APIName> failed() { return _failedComponents; }
147
148        public TypeCheckerOutput typeCheckerOutput() {
149            return this._typeCheckerOutput;
150        }
151    }
152
153    /** Statically check the given components. */
154    public static ComponentResult
155        checkComponents(Map<APIName, ComponentIndex> components,
156                        GlobalEnvironment env,
157                        FortressRepository repository)
158    {
159        HashSet<Component> checkedComponents = new HashSet<Component>();
160        Iterable<? extends StaticError> errors = new HashSet<StaticError>();
161        List<APIName> failedComponents = new ArrayList<APIName>();
162
163        TypeCheckerOutput type_checker_output = TypeCheckerOutput.emptyOutput();
164
165        for (APIName componentName : components.keySet()) {
166            TypeCheckerResult checked = checkComponent(components.get(componentName), env,
167                                                       repository);
168            checkedComponents.add((Component)checked.ast());
169            if (!checked.isSuccessful())
170                failedComponents.add(componentName);
171
172            errors = IterUtil.compose(checked.errors(), errors);
173            type_checker_output = new TypeCheckerOutput( type_checker_output, checked.getTypeCheckerOutput() );
174        }
175        return new ComponentResult
176            (IndexBuilder.buildComponents(checkedComponents,
177                                          System.currentTimeMillis()).
178             components(),
179             failedComponents,
180             errors,
181             type_checker_output);
182    }
183
184    public static TypeCheckerResult checkComponent(ComponentIndex component,
185                                                   GlobalEnvironment env,
186                                                   FortressRepository repository) {
187        if (Shell.getTypeChecking() == true) {
188            // Check type hierarchy to ensure acyclicity.
189            List<StaticError> errors = new TypeHierarchyChecker(component, env, repository).checkHierarchy();
190            if (! errors.isEmpty()) {
191                return new TypeCheckerResult(component.ast(), errors);
192            }
193
194            Node component_ast = component.ast();
195            // Replace implicit types with explicit ones.
196            component_ast = component_ast.accept(new InferenceVarInserter());
197            component_ast = component_ast.accept(new TypeNormalizer());
198            component = IndexBuilder.builder.buildComponentIndex((Component)component_ast,
199                                                                 System.currentTimeMillis());
200            TraitTable traitTable = new TraitTable(component, env);
201            TypeAnalyzer typeAnalyzer = TypeAnalyzer.make(traitTable);
202
203            if (Shell.testCoercion())
204                errors.addAll(new CoercionTest(typeAnalyzer).run());
205
206            errors.addAll(new TypeHierarchyChecker(component, env, repository).checkAcyclicHierarchy());
207            errors.addAll(new TypeWellFormedChecker(component, env, typeAnalyzer).check());
208
209            TypeCheckerResult result;
210            if ( ! Shell.getScala() ) {
211                // typecheck...
212                result = typeCheck(component, env, traitTable, component_ast, false);
213                // then replace inference variables...
214                InferenceVarReplacer rep = new InferenceVarReplacer(result.getIVarResults());
215                component_ast = (Component)result.ast().accept(rep);
216                // then typecheck again!!!
217                component = IndexBuilder.builder.buildComponentIndex((Component)component_ast,
218                                                                     System.currentTimeMillis());
219                result = typeCheck(component, env, traitTable, component_ast, true);
220            } else {
221                TypeEnv typeEnv = typeCheckEnv(component, env);
222                ConstraintUtil.useScalaFormulas();
223                STypeChecker typeChecker = STypeCheckerFactory.make(component, traitTable, typeEnv, typeAnalyzer);
224                component_ast = typeChecker.typecheck(component_ast);
225                component = IndexBuilder.builder.buildComponentIndex((Component)component_ast,
226                    System.currentTimeMillis());
227                errors.addAll(Lists.toJavaList(typeChecker.getErrors()));
228                result = new TypeCheckerResult(component_ast, errors);
229            }
230            result.setAst(result.ast().accept(new TypeNormalizer()));
231            // There should be no Inference vars left at this point
232            if( TypesUtil.assertAfterTypeChecking(result.ast()) )
233                bug("Result of typechecking still contains ArrayType/MatrixType/_InferenceVarType.\n" +
234                    result.ast());
235
236            errors.addAll(new TypeWellFormedChecker(component, env, typeAnalyzer).check());
237            if ( ! errors.isEmpty() ) {
238                result = addErrors(errors, result);
239                return result;
240            }
241
242            // Check overloadings in this component.
243            errors.addAll(new OverloadingChecker(component, env, repository).checkOverloading());
244            if ( ! errors.isEmpty() ) {
245                result = addErrors(errors, result);
246                return result;
247            }
248
249            // Check the set of exported APIs in this component.
250            errors.addAll(ExportChecker.checkExports(component, env, repository));
251            result = addErrors(errors, result);
252            return result;
253         } else {
254             return new TypeCheckerResult(component.ast(), IterUtil.<StaticError>empty());
255         }
256    }
257
258    private static TypeCheckerResult typeCheck(ComponentIndex component,
259                                               GlobalEnvironment env,
260                                               TraitTable traitTable,
261                                               Node component_ast,
262                                               boolean postInference) {
263        TypeEnv typeEnv = typeCheckEnv(component, env);
264        ConstraintUtil.useJavaFormulas();
265        TypeChecker typeChecker = new TypeChecker(traitTable, typeEnv,
266                                                  component, postInference);
267        return component_ast.accept(typeChecker);
268    }
269
270    private static TypeEnv typeCheckEnv(ComponentIndex component,
271                                        GlobalEnvironment env) {
272        TypeEnv typeEnv = TypeEnv.make(component);
273        // Add all top-level function names to the component-level environment.
274        typeEnv = typeEnv.extendWithFunctions(component.functions());
275        // Iterate over top-level variables,
276        // adding each to the component-level environment.
277        typeEnv = typeEnv.extend(component.variables());
278        // Add all top-level object names to the component-level environment.
279        typeEnv = typeEnv.extendWithTypeConses(component.typeConses());
280        return typeEnv;
281    }
282
283    public static TypeCheckerResult checkApi(ApiIndex api,
284                                             GlobalEnvironment env,
285                                             FortressRepository repository) {
286        // Check type hierarchy to ensure acyclicity.
287        List<StaticError> errors = new TypeHierarchyChecker(api, env, repository).checkHierarchy();
288        if (! errors.isEmpty()) {
289            return new TypeCheckerResult(api.ast(), errors);
290        }
291        Node api_ast = api.ast();
292        TypeCheckerResult result = new TypeCheckerResult(api_ast, errors);
293        result.setAst(result.ast().accept(new TypeNormalizer()));
294        // There should be no Inference vars left at this point
295        if( TypesUtil.assertAfterTypeChecking(result.ast()) )
296            bug("Result of typechecking still contains ArrayType/MatrixType/_InferenceVarType.\n" +
297                result.ast());
298        // Check overloadings in this API.
299        errors = new OverloadingChecker(api, env, repository).checkOverloading();
300        result = addErrors(errors, result);
301        return result;
302    }
303
304    private static TypeCheckerResult addErrors(List<StaticError> errors,
305                                               TypeCheckerResult result) {
306        if ( ! errors.isEmpty() ) {
307            for ( StaticError error : errors ) {
308                result = TypeCheckerResult.addError(result, error);
309            }
310        }
311        return result;
312    }
313
314}
Note: See TracBrowser for help on using the browser.