Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 import 'package:front_end/src/fasta/type_inference/local_type_inferrer.dart'; | |
| 2 import 'package:kernel/ast.dart' show DartType, InterfaceType; | |
| 3 import 'package:kernel/core_types.dart'; | |
| 4 | |
| 5 abstract class Block implements Statement { | |
| 6 Iterable<Statement> get shadowStatements; | |
| 7 | |
| 8 @override | |
| 9 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
| 10 for (var statement in shadowStatements) { | |
| 11 statement.shadowInfer(inferrer, context); | |
| 12 } | |
| 13 } | |
| 14 } | |
| 15 | |
| 16 abstract class Expression { | |
| 17 DartType shadowInfer( | |
| 18 LocalTypeInferrer inferrer, DartType context, bool typeNeeded); | |
| 19 } | |
| 20 | |
| 21 abstract class FunctionExpression implements Expression { | |
| 22 void set shadowInferredReturnType(DartType type); | |
| 23 | |
| 24 Statement get shadowBody; | |
| 25 | |
| 26 bool get shadowIsAsync; | |
| 27 | |
| 28 bool get shadowIsExpressionFunction; | |
| 29 | |
| 30 bool get shadowIsGenerator; | |
| 31 | |
| 32 DartType shadowMakeFunctionType(); | |
| 33 | |
| 34 @override | |
| 35 DartType shadowInfer( | |
| 36 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
| 37 // TODO(paulberry): infer argument types and type parameters. | |
| 38 // TODO(paulberry): full support for generators. | |
| 39 Statement body = shadowBody; | |
| 40 // TODO(paulberry): Dart 1.0 rules say we only need to set the function | |
| 41 // node's return type if it uses expression syntax. Does that make sense | |
| 42 // for Dart 2.0? | |
| 43 bool needToSetReturnType = shadowIsExpressionFunction; | |
| 44 bool returnTypeNeeded = typeNeeded || needToSetReturnType; | |
| 45 bool isAsync = shadowIsAsync; | |
| 46 var functionContext = new FunctionContext( | |
| 47 inferrer, returnTypeNeeded, isAsync, shadowIsGenerator); | |
| 48 body.shadowInfer(inferrer, functionContext); | |
| 49 DartType inferredReturnType; | |
| 50 if (needToSetReturnType || typeNeeded) { | |
| 51 inferredReturnType = functionContext.inferredReturnType; | |
| 52 if (isAsync) { | |
| 53 inferredReturnType = new InterfaceType( | |
| 54 inferrer.coreTypes.futureClass, <DartType>[inferredReturnType]); | |
| 55 } | |
| 56 } | |
| 57 if (needToSetReturnType) { | |
| 58 this.shadowInferredReturnType = inferredReturnType; | |
| 59 } | |
| 60 if (typeNeeded) { | |
| 61 return shadowMakeFunctionType(); | |
| 62 } else { | |
| 63 return null; | |
| 64 } | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 abstract class IntLiteral implements Expression { | |
| 69 @override | |
| 70 DartType shadowInfer( | |
| 71 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
| 72 return typeNeeded ? inferrer.coreTypes.intClass.rawType : null; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 abstract class ListLiteral implements Expression { | |
| 77 DartType get declaredTypeArgumentForInference; | |
| 78 | |
| 79 Iterable<Expression> get expressionsForInference; | |
| 80 | |
| 81 void set inferredTypeArgument(DartType type); | |
| 82 | |
| 83 @override | |
| 84 DartType shadowInfer( | |
| 85 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
| 86 DartType declaredTypeArgument = declaredTypeArgumentForInference; | |
| 87 DartType typeArgumentContext = declaredTypeArgument; | |
| 88 if (typeArgumentContext == null) { | |
| 89 if (context is InterfaceType && | |
| 90 context.classNode == inferrer.coreTypes.listClass && | |
| 91 context.typeArguments.length == 1) { | |
| 92 typeArgumentContext = context.typeArguments[0]; | |
| 93 } else if (context != null) { | |
| 94 // TODO(paulberry): report an error? | |
| 95 throw new UnimplementedError('$context'); | |
|
scheglov
2017/03/24 15:38:10
If I understand correctly, "context" will be Itera
Paul Berry
2017/03/24 17:59:50
You are correct. This entire method is a hack tha
| |
| 96 } | |
| 97 } | |
| 98 DartType inferredTypeArgument = typeArgumentContext; | |
| 99 bool typeArgumentNeeded = inferredTypeArgument == null; | |
| 100 for (Expression e in expressionsForInference) { | |
| 101 DartType t = | |
| 102 e.shadowInfer(inferrer, typeArgumentContext, typeArgumentNeeded); | |
| 103 if (typeArgumentNeeded) { | |
| 104 inferredTypeArgument = inferrer.union(inferredTypeArgument, t); | |
| 105 } | |
| 106 } | |
| 107 if (inferredTypeArgument == null) { | |
| 108 // Empty list. | |
| 109 throw new UnimplementedError(); | |
| 110 } | |
| 111 if (declaredTypeArgument == null) { | |
| 112 this.inferredTypeArgument = inferredTypeArgument; | |
| 113 } | |
| 114 if (typeNeeded) { | |
| 115 return new InterfaceType( | |
| 116 inferrer.coreTypes.listClass, <DartType>[inferredTypeArgument]); | |
| 117 } else { | |
| 118 return null; | |
| 119 } | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 abstract class NullLiteral implements Expression { | |
| 124 @override | |
| 125 DartType shadowInfer( | |
| 126 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
| 127 return typeNeeded ? inferrer.coreTypes.nullClass.rawType : null; | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 abstract class ReturnStatement implements Statement { | |
| 132 Expression get expressionForInference; | |
| 133 | |
| 134 @override | |
| 135 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
| 136 DartType expressionContext = null; // TODO(paulberry): probably wrong. | |
| 137 bool expressionTypeNeeded = | |
| 138 context.returnTypeNeeded && !context.isGenerator; | |
| 139 DartType expressionType = expressionForInference.shadowInfer( | |
| 140 inferrer, expressionContext, expressionTypeNeeded); | |
| 141 if (expressionTypeNeeded) { | |
| 142 if (context.isAsync) { | |
| 143 expressionType = _unwrapFuture(inferrer.coreTypes, expressionType); | |
| 144 } | |
| 145 context.recordReturnType(expressionType); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 DartType _unwrapFuture(CoreTypes coreTypes, DartType type) { | |
| 150 // TODO(paulberry): replace with a full implementation of what's in the spec | |
| 151 // (e.g. handle types derived from Future). Also probably move to Kernel. | |
| 152 if (type is InterfaceType && type.classNode == coreTypes.futureClass) { | |
| 153 return type.typeArguments[0]; | |
| 154 } else { | |
| 155 return type; | |
| 156 } | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 abstract class Statement { | |
| 161 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context); | |
| 162 } | |
| 163 | |
| 164 abstract class VariableDeclaration implements Statement { | |
| 165 DartType get shadowDeclaredType; | |
| 166 | |
| 167 DartType get shadowInferredType; | |
| 168 | |
| 169 void set shadowInferredType(DartType type); | |
| 170 | |
| 171 Expression get shadowInitializer; | |
| 172 | |
| 173 @override | |
| 174 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
| 175 Expression initializer = shadowInitializer; | |
| 176 if (initializer != null) { | |
| 177 DartType type = shadowDeclaredType; | |
| 178 DartType inferredType = | |
| 179 initializer.shadowInfer(inferrer, type, type == null); | |
| 180 if (type == null) { | |
| 181 this.shadowInferredType = inferredType; | |
| 182 } | |
| 183 } | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 abstract class VariableGet implements Expression { | |
| 188 VariableDeclaration get shadowDeclaration; | |
| 189 | |
| 190 @override | |
| 191 DartType shadowInfer( | |
| 192 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
| 193 return typeNeeded ? shadowDeclaration.shadowInferredType : null; | |
| 194 } | |
| 195 } | |
| OLD | NEW |