| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library kernel.transformations.closure.mock; |
| |
| import '../../ast.dart' |
| show |
| Arguments, |
| Block, |
| Class, |
| Constructor, |
| ConstructorInvocation, |
| DartType, |
| DynamicType, |
| EmptyStatement, |
| Expression, |
| ExpressionStatement, |
| Field, |
| FieldInitializer, |
| FunctionNode, |
| Initializer, |
| IntLiteral, |
| Library, |
| MethodInvocation, |
| Name, |
| NullLiteral, |
| Procedure, |
| ProcedureKind, |
| Program, |
| PropertyGet, |
| ReturnStatement, |
| Source, |
| Statement, |
| StaticInvocation, |
| Supertype, |
| VariableDeclaration, |
| VariableGet; |
| |
| import '../../core_types.dart' show CoreTypes; |
| |
| import '../../frontend/accessors.dart' |
| show |
| Accessor, |
| IndexAccessor, |
| PropertyAccessor, |
| ThisPropertyAccessor, |
| VariableAccessor; |
| |
| /// Extend the program with this mock: |
| /// |
| /// class Context { |
| /// final List list; |
| /// var parent; |
| /// Context(int i) : list = new List(i); |
| /// operator[] (int i) => list[i]; |
| /// operator[]= (int i, value) { |
| /// list[i] = value; |
| /// } |
| /// Context copy() { |
| /// Context c = new Context(list.length); |
| /// c.parent = parent; |
| /// c.list.setRange(0, list.length, list); |
| /// return c; |
| /// } |
| /// } |
| /// |
| /// Returns the mock. |
| Class mockUpContext(CoreTypes coreTypes, Program program) { |
| String fileUri = "dart:mock"; |
| |
| /// final List list; |
| Field listField = new Field(new Name("list"), |
| type: coreTypes.listClass.rawType, isFinal: true, fileUri: fileUri); |
| Accessor listFieldAccessor = |
| new ThisPropertyAccessor(listField.name, listField, null); |
| |
| /// var parent; |
| Field parentField = new Field(new Name("parent"), fileUri: fileUri); |
| Accessor parentFieldAccessor = |
| new ThisPropertyAccessor(parentField.name, parentField, parentField); |
| |
| List<Field> fields = <Field>[listField, parentField]; |
| |
| /// Context(int i) : list = new List(i); |
| VariableDeclaration iParameter = new VariableDeclaration("i", |
| type: coreTypes.intClass.rawType, isFinal: true); |
| |
| // TODO(karlklose): use the default factory when it is exposed again. |
| Procedure listConstructor = coreTypes.listClass.procedures.firstWhere( |
| (Procedure p) => p.name.name == 'filled'); |
| |
| Constructor constructor = new Constructor( |
| new FunctionNode(new EmptyStatement(), |
| positionalParameters: <VariableDeclaration>[iParameter]), |
| name: new Name(""), |
| initializers: <Initializer>[ |
| new FieldInitializer( |
| listField, |
| new StaticInvocation( |
| listConstructor, |
| new Arguments(<Expression>[ |
| new VariableAccessor(iParameter).buildSimpleRead(), |
| new NullLiteral(), |
| ], types: <DartType>[ |
| const DynamicType() |
| ]))) |
| ]); |
| |
| /// operator[] (int i) => list[i]; |
| iParameter = new VariableDeclaration("i", |
| type: coreTypes.intClass.rawType, isFinal: true); |
| Accessor accessor = IndexAccessor.make(listFieldAccessor.buildSimpleRead(), |
| new VariableAccessor(iParameter).buildSimpleRead(), null, null); |
| Procedure indexGet = new Procedure( |
| new Name("[]"), |
| ProcedureKind.Operator, |
| new FunctionNode(new ReturnStatement(accessor.buildSimpleRead()), |
| positionalParameters: <VariableDeclaration>[iParameter]), |
| fileUri: fileUri); |
| |
| /// operator[]= (int i, value) { |
| /// list[i] = value; |
| /// } |
| iParameter = new VariableDeclaration("i", |
| type: coreTypes.intClass.rawType, isFinal: true); |
| VariableDeclaration valueParameter = |
| new VariableDeclaration("value", isFinal: true); |
| accessor = IndexAccessor.make(listFieldAccessor.buildSimpleRead(), |
| new VariableAccessor(iParameter).buildSimpleRead(), null, null); |
| Expression expression = accessor.buildAssignment( |
| new VariableAccessor(valueParameter).buildSimpleRead(), |
| voidContext: true); |
| Procedure indexSet = new Procedure( |
| new Name("[]="), |
| ProcedureKind.Operator, |
| new FunctionNode(new ExpressionStatement(expression), |
| positionalParameters: <VariableDeclaration>[ |
| iParameter, |
| valueParameter |
| ]), |
| fileUri: fileUri); |
| |
| /// Context copy() { |
| /// Context c = new Context(list.length); |
| /// c.parent = parent; |
| /// c.list.setRange(0, list.length, list); |
| /// return c; |
| /// } |
| VariableDeclaration c = new VariableDeclaration("c", |
| initializer: new ConstructorInvocation( |
| constructor, |
| new Arguments(<Expression>[ |
| new PropertyGet( |
| listFieldAccessor.buildSimpleRead(), new Name("length")) |
| ]))); |
| Accessor accessCParent = PropertyAccessor.make( |
| new VariableGet(c), parentField.name, parentField, parentField); |
| Accessor accessCList = PropertyAccessor.make( |
| new VariableGet(c), listField.name, listField, null); |
| List<Statement> statements = <Statement>[ |
| c, |
| new ExpressionStatement(accessCParent.buildAssignment( |
| parentFieldAccessor.buildSimpleRead(), |
| voidContext: true)), |
| new ExpressionStatement(new MethodInvocation( |
| accessCList.buildSimpleRead(), |
| new Name("setRange"), |
| new Arguments(<Expression>[ |
| new IntLiteral(0), |
| new PropertyGet( |
| listFieldAccessor.buildSimpleRead(), new Name("length")), |
| listFieldAccessor.buildSimpleRead() |
| ]))), |
| new ReturnStatement(new VariableGet(c)) |
| ]; |
| Procedure copy = new Procedure(new Name("copy"), ProcedureKind.Method, |
| new FunctionNode(new Block(statements)), |
| fileUri: fileUri); |
| |
| List<Procedure> procedures = <Procedure>[indexGet, indexSet, copy]; |
| |
| Class contextClass = new Class( |
| name: "Context", |
| supertype: new Supertype(coreTypes.objectClass, const <DartType>[]), |
| constructors: [constructor], |
| fields: fields, |
| procedures: procedures, |
| fileUri: fileUri); |
| Library mock = new Library(Uri.parse(fileUri), |
| name: "mock", classes: [contextClass])..fileUri = fileUri; |
| program.libraries.add(mock); |
| mock.parent = program; |
| program.uriToSource[mock.fileUri] = new Source(<int>[0], ""); |
| return contextClass; |
| } |