| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library kernel.transformations.closure.context; | 5 library kernel.transformations.closure.context; |
| 6 | 6 |
| 7 import '../../ast.dart' | 7 import '../../ast.dart' |
| 8 show | 8 show |
| 9 Arguments, | 9 Arguments, |
| 10 Class, | 10 Class, |
| 11 Expression, | 11 Expression, |
| 12 IntLiteral, | 12 IntLiteral, |
| 13 MethodInvocation, | 13 MethodInvocation, |
| 14 Name, | 14 Name, |
| 15 NullLiteral, | 15 NullLiteral, |
| 16 PropertyGet, | 16 PropertyGet, |
| 17 StringLiteral, | 17 StringLiteral, |
| 18 Throw, | 18 Throw, |
| 19 VariableDeclaration, | 19 VariableDeclaration, |
| 20 VariableGet, | 20 VariableGet, |
| 21 VariableSet; | 21 VariableSet, |
| 22 VectorGet, |
| 23 VectorSet, |
| 24 VectorCopy; |
| 22 | 25 |
| 23 import '../../frontend/accessors.dart' | 26 import '../../frontend/accessors.dart' show Accessor, VariableAccessor; |
| 24 show Accessor, IndexAccessor, VariableAccessor; | |
| 25 | 27 |
| 26 import 'converter.dart' show ClosureConverter; | 28 import 'converter.dart' show ClosureConverter; |
| 27 | 29 |
| 28 abstract class Context { | 30 abstract class Context { |
| 29 /// Returns a new expression for accessing this context. | 31 /// Returns a new expression for accessing this context. |
| 30 Expression get expression; | 32 Expression get expression; |
| 31 | 33 |
| 32 /// Returns an accessor (or null) for accessing this context. | 34 /// Returns an accessor (or null) for accessing this context. |
| 33 Accessor get accessor; | 35 Accessor get accessor; |
| 34 | 36 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 converter, accessor, <List<VariableDeclaration>>[]); | 105 converter, accessor, <List<VariableDeclaration>>[]); |
| 104 } | 106 } |
| 105 } | 107 } |
| 106 | 108 |
| 107 class LocalContext extends Context { | 109 class LocalContext extends Context { |
| 108 final ClosureConverter converter; | 110 final ClosureConverter converter; |
| 109 final Context parent; | 111 final Context parent; |
| 110 final VariableDeclaration self; | 112 final VariableDeclaration self; |
| 111 final IntLiteral size; | 113 final IntLiteral size; |
| 112 final List<VariableDeclaration> variables = <VariableDeclaration>[]; | 114 final List<VariableDeclaration> variables = <VariableDeclaration>[]; |
| 113 final Map<VariableDeclaration, Arguments> initializers = | 115 final Map<VariableDeclaration, VectorSet> initializers = |
| 114 <VariableDeclaration, Arguments>{}; | 116 <VariableDeclaration, VectorSet>{}; |
| 115 | 117 |
| 116 LocalContext._internal(this.converter, this.parent, this.self, this.size); | 118 LocalContext._internal(this.converter, this.parent, this.self, this.size); |
| 117 | 119 |
| 118 factory LocalContext(ClosureConverter converter, Context parent) { | 120 factory LocalContext(ClosureConverter converter, Context parent) { |
| 119 Class contextClass = converter.contextClass; | 121 Class contextClass = converter.contextClass; |
| 120 assert(contextClass.constructors.length == 1); | 122 assert(contextClass.constructors.length == 1); |
| 121 converter.rewriter | 123 converter.rewriter.insertContextDeclaration(parent.expression); |
| 122 .insertContextDeclaration(contextClass, parent.expression); | |
| 123 | 124 |
| 124 return new LocalContext._internal(converter, parent, | 125 return new LocalContext._internal(converter, parent, |
| 125 converter.rewriter.contextDeclaration, converter.rewriter.contextSize); | 126 converter.rewriter.contextDeclaration, converter.rewriter.contextSize); |
| 126 } | 127 } |
| 127 | 128 |
| 128 Expression get expression => accessor.buildSimpleRead(); | 129 Expression get expression => accessor.buildSimpleRead(); |
| 129 | 130 |
| 130 Accessor get accessor => new VariableAccessor(self); | 131 Accessor get accessor => new VariableAccessor(self); |
| 131 | 132 |
| 132 void extend(VariableDeclaration variable, Expression value) { | 133 void extend(VariableDeclaration variable, Expression value) { |
| 133 Arguments arguments = | 134 // Increase index by 1, because the parent occupies item 0, and all other |
| 134 new Arguments(<Expression>[new IntLiteral(variables.length), value]); | 135 // variables are therefore shifted by 1. |
| 135 converter.rewriter.insertExtendContext(expression, arguments); | 136 IntLiteral index = new IntLiteral(variables.length + 1); |
| 137 VectorSet initializer = new VectorSet(expression, index, value); |
| 138 index.parent = initializer; |
| 139 value.parent = initializer; |
| 140 |
| 141 converter.rewriter.insertExtendContext(initializer); |
| 136 ++size.value; | 142 ++size.value; |
| 137 variables.add(variable); | 143 variables.add(variable); |
| 138 initializers[variable] = arguments; | 144 initializers[variable] = initializer; |
| 139 } | 145 } |
| 140 | 146 |
| 141 void update(VariableDeclaration variable, Expression value) { | 147 void update(VariableDeclaration variable, Expression value) { |
| 142 Arguments arguments = initializers[variable]; | 148 VectorSet initializer = initializers[variable]; |
| 143 arguments.positional[1] = value; | 149 initializer.value = value; |
| 144 value.parent = arguments; | 150 value.parent = initializer; |
| 145 } | 151 } |
| 146 | 152 |
| 147 Expression lookup(VariableDeclaration variable) { | 153 Expression lookup(VariableDeclaration variable) { |
| 148 var index = variables.indexOf(variable); | 154 var index = variables.indexOf(variable); |
| 155 // Increase index by 1 in case of success, because the parent occupies |
| 156 // item 0, and all other variables are therefore shifted by 1. |
| 149 return index == -1 | 157 return index == -1 |
| 150 ? parent.lookup(variable) | 158 ? parent.lookup(variable) |
| 151 : new MethodInvocation(expression, new Name('[]'), | 159 : new VectorGet(expression, new IntLiteral(index + 1)); |
| 152 new Arguments(<Expression>[new IntLiteral(index)])); | |
| 153 } | 160 } |
| 154 | 161 |
| 155 Expression assign(VariableDeclaration variable, Expression value, | 162 Expression assign(VariableDeclaration variable, Expression value, |
| 156 {bool voidContext: false}) { | 163 {bool voidContext: false}) { |
| 157 var index = variables.indexOf(variable); | 164 var index = variables.indexOf(variable); |
| 165 // Increase index by 1 in case of success, because the parent occupies |
| 166 // item 0, and all other variables are therefore shifted by 1. |
| 158 return index == -1 | 167 return index == -1 |
| 159 ? parent.assign(variable, value, voidContext: voidContext) | 168 ? parent.assign(variable, value, voidContext: voidContext) |
| 160 : IndexAccessor | 169 : new VectorSet(expression, new IntLiteral(index + 1), value); |
| 161 .make(expression, new IntLiteral(index), null, null) | |
| 162 .buildAssignment(value, voidContext: voidContext); | |
| 163 } | 170 } |
| 164 | 171 |
| 165 Context toNestedContext([Accessor accessor]) { | 172 Context toNestedContext([Accessor accessor]) { |
| 166 accessor ??= this.accessor; | 173 accessor ??= this.accessor; |
| 167 List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[]; | 174 List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[]; |
| 168 var current = this; | 175 var current = this; |
| 169 while (current != null && current is! NoContext) { | 176 while (current != null && current is! NoContext) { |
| 170 if (current is LocalContext) { | 177 if (current is LocalContext) { |
| 171 variabless.add(current.variables); | 178 variabless.add(current.variables); |
| 172 current = current.parent; | 179 current = current.parent; |
| 173 } else if (current is NestedContext) { | 180 } else if (current is NestedContext) { |
| 174 variabless.addAll((current as NestedContext).variabless); | 181 variabless.addAll((current as NestedContext).variabless); |
| 175 current = null; | 182 current = null; |
| 176 } | 183 } |
| 177 } | 184 } |
| 178 return new NestedContext(converter, accessor, variabless); | 185 return new NestedContext(converter, accessor, variabless); |
| 179 } | 186 } |
| 180 | 187 |
| 181 Expression clone() { | 188 Expression clone() { |
| 182 self.isFinal = false; | 189 self.isFinal = false; |
| 183 return new VariableSet( | 190 return new VariableSet(self, new VectorCopy(new VariableGet(self))); |
| 184 self, | |
| 185 new MethodInvocation( | |
| 186 new VariableGet(self), new Name("copy"), new Arguments.empty())); | |
| 187 } | 191 } |
| 188 } | 192 } |
| 189 | 193 |
| 190 class NestedContext extends Context { | 194 class NestedContext extends Context { |
| 191 final ClosureConverter converter; | 195 final ClosureConverter converter; |
| 192 final Accessor accessor; | 196 final Accessor accessor; |
| 193 final List<List<VariableDeclaration>> variabless; | 197 final List<List<VariableDeclaration>> variabless; |
| 194 | 198 |
| 195 NestedContext(this.converter, this.accessor, this.variabless); | 199 NestedContext(this.converter, this.accessor, this.variabless); |
| 196 | 200 |
| 197 Expression get expression { | 201 Expression get expression { |
| 198 return accessor?.buildSimpleRead() ?? new NullLiteral(); | 202 return accessor?.buildSimpleRead() ?? new NullLiteral(); |
| 199 } | 203 } |
| 200 | 204 |
| 201 void extend(VariableDeclaration variable, Expression value) { | 205 void extend(VariableDeclaration variable, Expression value) { |
| 202 converter.context = new LocalContext(converter, this) | 206 converter.context = new LocalContext(converter, this) |
| 203 ..extend(variable, value); | 207 ..extend(variable, value); |
| 204 } | 208 } |
| 205 | 209 |
| 206 Expression lookup(VariableDeclaration variable) { | 210 Expression lookup(VariableDeclaration variable) { |
| 207 Expression context = expression; | 211 Expression context = expression; |
| 208 for (var variables in variabless) { | 212 for (var variables in variabless) { |
| 209 var index = variables.indexOf(variable); | 213 var index = variables.indexOf(variable); |
| 210 if (index != -1) { | 214 if (index != -1) { |
| 211 return new MethodInvocation(context, new Name('[]'), | 215 // Increase index by 1, because the parent occupies item 0, and all |
| 212 new Arguments(<Expression>[new IntLiteral(index)])); | 216 // other variables are therefore shifted by 1. |
| 217 return new VectorGet(context, new IntLiteral(index + 1)); |
| 213 } | 218 } |
| 214 context = new PropertyGet(context, new Name('parent')); | 219 // Item 0 of a context always points to its parent. |
| 220 context = new VectorGet(context, new IntLiteral(0)); |
| 215 } | 221 } |
| 216 throw 'Unbound NestedContext.lookup($variable)'; | 222 throw 'Unbound NestedContext.lookup($variable)'; |
| 217 } | 223 } |
| 218 | 224 |
| 219 Expression assign(VariableDeclaration variable, Expression value, | 225 Expression assign(VariableDeclaration variable, Expression value, |
| 220 {bool voidContext: false}) { | 226 {bool voidContext: false}) { |
| 221 Expression context = expression; | 227 Expression context = expression; |
| 222 for (List<VariableDeclaration> variables in variabless) { | 228 for (List<VariableDeclaration> variables in variabless) { |
| 223 var index = variables.indexOf(variable); | 229 var index = variables.indexOf(variable); |
| 224 if (index != -1) { | 230 if (index != -1) { |
| 225 return IndexAccessor | 231 // Increase index by 1, because the parent occupies item 0, and all |
| 226 .make(context, new IntLiteral(index), null, null) | 232 // other variables are therefore shifted by 1. |
| 227 .buildAssignment(value, voidContext: voidContext); | 233 return new VectorSet(context, new IntLiteral(index + 1), value); |
| 228 } | 234 } |
| 229 context = new PropertyGet(context, new Name('parent')); | 235 // Item 0 of a context always points to its parent. |
| 236 context = new VectorGet(context, new IntLiteral(0)); |
| 230 } | 237 } |
| 231 throw 'Unbound NestedContext.lookup($variable)'; | 238 throw 'Unbound NestedContext.lookup($variable)'; |
| 232 } | 239 } |
| 233 | 240 |
| 234 Context toNestedContext([Accessor accessor]) { | 241 Context toNestedContext([Accessor accessor]) { |
| 235 return new NestedContext(converter, accessor ?? this.accessor, variabless); | 242 return new NestedContext(converter, accessor ?? this.accessor, variabless); |
| 236 } | 243 } |
| 237 } | 244 } |
| OLD | NEW |