Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Issue 2777883002: Remove Fasta's copy of accessors.dart. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 fasta.body_builder; 5 library fasta.body_builder;
6 6
7 import '../parser/parser.dart' show FormalParameterType, optional; 7 import '../parser/parser.dart' show FormalParameterType, optional;
8 8
9 import '../parser/error_kind.dart' show ErrorKind; 9 import '../parser/error_kind.dart' show ErrorKind;
10 10
11 import '../parser/identifier_context.dart' show IdentifierContext; 11 import '../parser/identifier_context.dart' show IdentifierContext;
12 12
13 import 'package:kernel/ast.dart'; 13 import 'package:kernel/ast.dart';
14 14
15 import 'package:kernel/clone.dart' show CloneVisitor; 15 import 'package:kernel/clone.dart' show CloneVisitor;
16 16
17 import 'package:kernel/transformations/flags.dart' show TransformerFlag; 17 import 'package:kernel/transformations/flags.dart' show TransformerFlag;
18 18
19 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; 19 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
20 20
21 import 'package:kernel/core_types.dart' show CoreTypes; 21 import 'package:kernel/core_types.dart' show CoreTypes;
22 22
23 import 'package:kernel/frontend/accessors.dart'
24 show buildIsNull, makeBinary, makeLet;
25
23 import '../parser/dart_vm_native.dart' show skipNativeClause; 26 import '../parser/dart_vm_native.dart' show skipNativeClause;
24 27
25 import '../scanner/token.dart' 28 import '../scanner/token.dart'
26 show BeginGroupToken, Token, isBinaryOperator, isMinusOperator; 29 show BeginGroupToken, Token, isBinaryOperator, isMinusOperator;
27 30
28 import '../errors.dart' show formatUnexpected, internalError; 31 import '../errors.dart' show formatUnexpected, internalError;
29 32
30 import '../source/scope_listener.dart' 33 import '../source/scope_listener.dart'
31 show JumpTargetKind, NullValue, ScopeListener; 34 show JumpTargetKind, NullValue, ScopeListener;
32 35
33 import '../builder/scope.dart' show ProblemBuilder, Scope; 36 import '../builder/scope.dart' show ProblemBuilder, Scope;
34 37
35 import '../source/outline_builder.dart' show asyncMarkerFromTokens; 38 import '../source/outline_builder.dart' show asyncMarkerFromTokens;
36 39
37 import 'builder_accessors.dart'; 40 import 'builder_accessors.dart';
38 41
39 import 'frontend_accessors.dart' show buildIsNull, makeBinary, makeLet;
40
41 import '../quote.dart' 42 import '../quote.dart'
42 show 43 show
43 Quote, 44 Quote,
44 analyzeQuote, 45 analyzeQuote,
45 unescape, 46 unescape,
46 unescapeFirstStringPart, 47 unescapeFirstStringPart,
47 unescapeLastStringPart, 48 unescapeLastStringPart,
48 unescapeString; 49 unescapeString;
49 50
50 import '../modifier.dart' show Modifier, constMask, finalMask; 51 import '../modifier.dart' show Modifier, constMask, finalMask;
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 String operator = token.stringValue; 591 String operator = token.stringValue;
591 if (identical("!=", operator)) { 592 if (identical("!=", operator)) {
592 operator = "=="; 593 operator = "==";
593 negate = true; 594 negate = true;
594 } 595 }
595 if (!isBinaryOperator(operator) && !isMinusOperator(operator)) { 596 if (!isBinaryOperator(operator) && !isMinusOperator(operator)) {
596 return buildCompileTimeError( 597 return buildCompileTimeError(
597 "Not an operator: '$operator'.", token.charOffset); 598 "Not an operator: '$operator'.", token.charOffset);
598 } else { 599 } else {
599 Expression result = 600 Expression result =
600 makeBinary(a, new Name(operator), null, b, token.charOffset); 601 makeBinary(a, new Name(operator), null, b, offset: token.charOffset);
601 if (isSuper) { 602 if (isSuper) {
602 result = toSuperMethodInvocation(result); 603 result = toSuperMethodInvocation(result);
603 } 604 }
604 return negate ? new Not(result) : result; 605 return negate ? new Not(result) : result;
605 } 606 }
606 } 607 }
607 608
608 void doLogicalExpression(Token token) { 609 void doLogicalExpression(Token token) {
609 Expression argument = popForValue(); 610 Expression argument = popForValue();
610 Expression receiver = popForValue(); 611 Expression receiver = popForValue();
(...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after
1550 push(NullValue.Expression); 1551 push(NullValue.Expression);
1551 } 1552 }
1552 1553
1553 @override 1554 @override
1554 void handleIndexedExpression( 1555 void handleIndexedExpression(
1555 Token openCurlyBracket, Token closeCurlyBracket) { 1556 Token openCurlyBracket, Token closeCurlyBracket) {
1556 debugEvent("IndexedExpression"); 1557 debugEvent("IndexedExpression");
1557 Expression index = popForValue(); 1558 Expression index = popForValue();
1558 var receiver = pop(); 1559 var receiver = pop();
1559 if (receiver is ThisAccessor && receiver.isSuper) { 1560 if (receiver is ThisAccessor && receiver.isSuper) {
1560 push(new SuperIndexAccessor(this, receiver.charOffset, index, 1561 push(new SuperIndexAccessor(this, receiver.offset, index,
1561 lookupSuperMember(indexGetName), lookupSuperMember(indexSetName))); 1562 lookupSuperMember(indexGetName), lookupSuperMember(indexSetName)));
1562 } else { 1563 } else {
1563 push(IndexAccessor.make(this, openCurlyBracket.charOffset, 1564 push(IndexAccessor.make(this, openCurlyBracket.charOffset,
1564 toValue(receiver), index, null, null)); 1565 toValue(receiver), index, null, null));
1565 } 1566 }
1566 } 1567 }
1567 1568
1568 @override 1569 @override
1569 void handleUnaryPrefixExpression(Token token) { 1570 void handleUnaryPrefixExpression(Token token) {
1570 debugEvent("UnaryPrefixExpression"); 1571 debugEvent("UnaryPrefixExpression");
1571 var receiver = pop(); 1572 var receiver = pop();
1572 if (optional("!", token)) { 1573 if (optional("!", token)) {
1573 push(new Not(toValue(receiver))); 1574 push(new Not(toValue(receiver)));
1574 } else { 1575 } else {
1575 String operator = token.stringValue; 1576 String operator = token.stringValue;
1576 if (optional("-", token)) { 1577 if (optional("-", token)) {
1577 operator = "unary-"; 1578 operator = "unary-";
1578 } 1579 }
1579 if (receiver is ThisAccessor && receiver.isSuper) { 1580 if (receiver is ThisAccessor && receiver.isSuper) {
1580 push(toSuperMethodInvocation(buildMethodInvocation( 1581 push(toSuperMethodInvocation(buildMethodInvocation(
1581 new ThisExpression()..fileOffset = receiver.charOffset, 1582 new ThisExpression()..fileOffset = receiver.offset,
1582 new Name(operator), 1583 new Name(operator),
1583 new Arguments.empty(), 1584 new Arguments.empty(),
1584 token.charOffset))); 1585 token.charOffset)));
1585 } else { 1586 } else {
1586 push(buildMethodInvocation(toValue(receiver), new Name(operator), 1587 push(buildMethodInvocation(toValue(receiver), new Name(operator),
1587 new Arguments.empty(), token.charOffset)); 1588 new Arguments.empty(), token.charOffset));
1588 } 1589 }
1589 } 1590 }
1590 } 1591 }
1591 1592
1592 Name incrementOperator(Token token) { 1593 Name incrementOperator(Token token) {
1593 if (optional("++", token)) return plusName; 1594 if (optional("++", token)) return plusName;
1594 if (optional("--", token)) return minusName; 1595 if (optional("--", token)) return minusName;
1595 return internalError("Unknown increment operator: ${token.lexeme}"); 1596 return internalError("Unknown increment operator: ${token.lexeme}");
1596 } 1597 }
1597 1598
1598 @override 1599 @override
1599 void handleUnaryPrefixAssignmentExpression(Token token) { 1600 void handleUnaryPrefixAssignmentExpression(Token token) {
1600 debugEvent("UnaryPrefixAssignmentExpression"); 1601 debugEvent("UnaryPrefixAssignmentExpression");
1601 var accessor = pop(); 1602 var accessor = pop();
1602 if (accessor is BuilderAccessor) { 1603 if (accessor is BuilderAccessor) {
1603 push(accessor.buildPrefixIncrement( 1604 push(accessor.buildPrefixIncrement(incrementOperator(token),
1604 incrementOperator(token), token.charOffset)); 1605 offset: token.charOffset));
1605 } else { 1606 } else {
1606 push(wrapInvalid(toValue(accessor))); 1607 push(wrapInvalid(toValue(accessor)));
1607 } 1608 }
1608 } 1609 }
1609 1610
1610 @override 1611 @override
1611 void handleUnaryPostfixAssignmentExpression(Token token) { 1612 void handleUnaryPostfixAssignmentExpression(Token token) {
1612 debugEvent("UnaryPostfixAssignmentExpression"); 1613 debugEvent("UnaryPostfixAssignmentExpression");
1613 var accessor = pop(); 1614 var accessor = pop();
1614 if (accessor is BuilderAccessor) { 1615 if (accessor is BuilderAccessor) {
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 void finalize(Expression expression) { 2482 void finalize(Expression expression) {
2482 assert(nextCascade.variable.initializer is InvalidExpression); 2483 assert(nextCascade.variable.initializer is InvalidExpression);
2483 nextCascade.variable.initializer = expression; 2484 nextCascade.variable.initializer = expression;
2484 expression.parent = nextCascade.variable; 2485 expression.parent = nextCascade.variable;
2485 } 2486 }
2486 } 2487 }
2487 2488
2488 abstract class ContextAccessor extends BuilderAccessor { 2489 abstract class ContextAccessor extends BuilderAccessor {
2489 final BuilderHelper helper; 2490 final BuilderHelper helper;
2490 2491
2491 final int charOffset;
2492
2493 final BuilderAccessor accessor; 2492 final BuilderAccessor accessor;
2494 2493
2495 ContextAccessor(this.helper, this.charOffset, this.accessor); 2494 final int offset;
2495
2496 ContextAccessor(this.helper, this.offset, this.accessor);
2497
2498 @override
2499 Expression get builtBinary => internalError("Unsupported operation.");
2500
2501 @override
2502 void set builtBinary(Expression expression) {
2503 internalError("Unsupported operation.");
2504 }
2505
2506 @override
2507 Expression get builtGetter => internalError("Unsupported operation.");
2508
2509 @override
2510 void set builtGetter(Expression expression) {
2511 internalError("Unsupported operation.");
2512 }
2496 2513
2497 String get plainNameForRead => internalError("Unsupported operation."); 2514 String get plainNameForRead => internalError("Unsupported operation.");
2498 2515
2499 Expression doInvocation(int charOffset, Arguments arguments) { 2516 Expression doInvocation(int charOffset, Arguments arguments) {
2500 return internalError("Unhandled: ${runtimeType}", uri, charOffset); 2517 return internalError("Unhandled: ${runtimeType}", uri, charOffset);
2501 } 2518 }
2502 2519
2503 Expression buildSimpleRead(); 2520 Expression buildSimpleRead();
2504 2521
2505 Expression buildForEffect(); 2522 Expression buildForEffect();
2506 2523
2507 Expression buildAssignment(Expression value, {bool voidContext: false}) { 2524 Expression buildAssignment(Expression value, {bool voidContext: false}) {
2508 return makeInvalidWrite(value); 2525 return makeInvalidWrite(value);
2509 } 2526 }
2510 2527
2511 Expression buildNullAwareAssignment(Expression value, DartType type, 2528 Expression buildNullAwareAssignment(Expression value, DartType type,
2512 {bool voidContext: false}) { 2529 {bool voidContext: false}) {
2513 return makeInvalidWrite(value); 2530 return makeInvalidWrite(value);
2514 } 2531 }
2515 2532
2516 Expression buildCompoundAssignment( 2533 Expression buildCompoundAssignment(Name binaryOperator, Expression value,
2517 Name binaryOperator, Expression value, int charOffset, 2534 {int offset: TreeNode.noOffset,
2518 {bool voidContext: false, Procedure interfaceTarget}) { 2535 bool voidContext: false,
2536 Procedure interfaceTarget}) {
2519 return makeInvalidWrite(value); 2537 return makeInvalidWrite(value);
2520 } 2538 }
2521 2539
2522 Expression buildPrefixIncrement(Name binaryOperator, int charOffset, 2540 Expression buildPrefixIncrement(Name binaryOperator,
2523 {bool voidContext: false, Procedure interfaceTarget}) { 2541 {int offset: TreeNode.noOffset,
2542 bool voidContext: false,
2543 Procedure interfaceTarget}) {
2524 return makeInvalidWrite(null); 2544 return makeInvalidWrite(null);
2525 } 2545 }
2526 2546
2527 Expression buildPostfixIncrement(Name binaryOperator, int charOffset, 2547 Expression buildPostfixIncrement(Name binaryOperator,
2528 {bool voidContext: false, Procedure interfaceTarget}) { 2548 {int offset: TreeNode.noOffset,
2549 bool voidContext: false,
2550 Procedure interfaceTarget}) {
2529 return makeInvalidWrite(null); 2551 return makeInvalidWrite(null);
2530 } 2552 }
2531 2553
2532 makeInvalidRead() => internalError("not supported"); 2554 makeInvalidRead() => internalError("not supported");
2533 2555
2534 Expression makeInvalidWrite(Expression value) { 2556 Expression makeInvalidWrite(Expression value) {
2535 return helper.buildCompileTimeError( 2557 return helper.buildCompileTimeError(
2536 "Can't be used as left-hand side of assignment.", charOffset); 2558 "Can't be used as left-hand side of assignment.", offset);
2537 } 2559 }
2538 } 2560 }
2539 2561
2540 class DelayedAssignment extends ContextAccessor { 2562 class DelayedAssignment extends ContextAccessor {
2541 final Expression value; 2563 final Expression value;
2542 2564
2543 final String assignmentOperator; 2565 final String assignmentOperator;
2544 2566
2545 DelayedAssignment(BuilderHelper helper, int charOffset, 2567 DelayedAssignment(BuilderHelper helper, int charOffset,
2546 BuilderAccessor accessor, this.value, this.assignmentOperator) 2568 BuilderAccessor accessor, this.value, this.assignmentOperator)
2547 : super(helper, charOffset, accessor); 2569 : super(helper, charOffset, accessor);
2548 2570
2549 Expression buildSimpleRead() { 2571 Expression buildSimpleRead() {
2550 return handleAssignment(false); 2572 return handleAssignment(false);
2551 } 2573 }
2552 2574
2553 Expression buildForEffect() { 2575 Expression buildForEffect() {
2554 return handleAssignment(true); 2576 return handleAssignment(true);
2555 } 2577 }
2556 2578
2557 Expression handleAssignment(bool voidContext) { 2579 Expression handleAssignment(bool voidContext) {
2558 if (identical("=", assignmentOperator)) { 2580 if (identical("=", assignmentOperator)) {
2559 return accessor.buildAssignment(value, voidContext: voidContext); 2581 return accessor.buildAssignment(value, voidContext: voidContext);
2560 } else if (identical("+=", assignmentOperator)) { 2582 } else if (identical("+=", assignmentOperator)) {
2561 return accessor.buildCompoundAssignment(plusName, value, charOffset, 2583 return accessor.buildCompoundAssignment(plusName, value,
2562 voidContext: voidContext); 2584 offset: offset, voidContext: voidContext);
2563 } else if (identical("-=", assignmentOperator)) { 2585 } else if (identical("-=", assignmentOperator)) {
2564 return accessor.buildCompoundAssignment(minusName, value, charOffset, 2586 return accessor.buildCompoundAssignment(minusName, value,
2565 voidContext: voidContext); 2587 offset: offset, voidContext: voidContext);
2566 } else if (identical("*=", assignmentOperator)) { 2588 } else if (identical("*=", assignmentOperator)) {
2567 return accessor.buildCompoundAssignment(multiplyName, value, charOffset, 2589 return accessor.buildCompoundAssignment(multiplyName, value,
2568 voidContext: voidContext); 2590 offset: offset, voidContext: voidContext);
2569 } else if (identical("%=", assignmentOperator)) { 2591 } else if (identical("%=", assignmentOperator)) {
2570 return accessor.buildCompoundAssignment(percentName, value, charOffset, 2592 return accessor.buildCompoundAssignment(percentName, value,
2571 voidContext: voidContext); 2593 offset: offset, voidContext: voidContext);
2572 } else if (identical("&=", assignmentOperator)) { 2594 } else if (identical("&=", assignmentOperator)) {
2573 return accessor.buildCompoundAssignment(ampersandName, value, charOffset, 2595 return accessor.buildCompoundAssignment(ampersandName, value,
2574 voidContext: voidContext); 2596 offset: offset, voidContext: voidContext);
2575 } else if (identical("/=", assignmentOperator)) { 2597 } else if (identical("/=", assignmentOperator)) {
2576 return accessor.buildCompoundAssignment(divisionName, value, charOffset, 2598 return accessor.buildCompoundAssignment(divisionName, value,
2577 voidContext: voidContext); 2599 offset: offset, voidContext: voidContext);
2578 } else if (identical("<<=", assignmentOperator)) { 2600 } else if (identical("<<=", assignmentOperator)) {
2579 return accessor.buildCompoundAssignment(leftShiftName, value, charOffset, 2601 return accessor.buildCompoundAssignment(leftShiftName, value,
2580 voidContext: voidContext); 2602 offset: offset, voidContext: voidContext);
2581 } else if (identical(">>=", assignmentOperator)) { 2603 } else if (identical(">>=", assignmentOperator)) {
2582 return accessor.buildCompoundAssignment(rightShiftName, value, charOffset, 2604 return accessor.buildCompoundAssignment(rightShiftName, value,
2583 voidContext: voidContext); 2605 offset: offset, voidContext: voidContext);
2584 } else if (identical("??=", assignmentOperator)) { 2606 } else if (identical("??=", assignmentOperator)) {
2585 return accessor.buildNullAwareAssignment(value, const DynamicType(), 2607 return accessor.buildNullAwareAssignment(value, const DynamicType(),
2586 voidContext: voidContext); 2608 voidContext: voidContext);
2587 } else if (identical("^=", assignmentOperator)) { 2609 } else if (identical("^=", assignmentOperator)) {
2588 return accessor.buildCompoundAssignment(caretName, value, charOffset, 2610 return accessor.buildCompoundAssignment(caretName, value,
2589 voidContext: voidContext); 2611 offset: offset, voidContext: voidContext);
2590 } else if (identical("|=", assignmentOperator)) { 2612 } else if (identical("|=", assignmentOperator)) {
2591 return accessor.buildCompoundAssignment(barName, value, charOffset, 2613 return accessor.buildCompoundAssignment(barName, value,
2592 voidContext: voidContext); 2614 offset: offset, voidContext: voidContext);
2593 } else if (identical("~/=", assignmentOperator)) { 2615 } else if (identical("~/=", assignmentOperator)) {
2594 return accessor.buildCompoundAssignment(mustacheName, value, charOffset, 2616 return accessor.buildCompoundAssignment(mustacheName, value,
2595 voidContext: voidContext); 2617 offset: offset, voidContext: voidContext);
2596 } else { 2618 } else {
2597 return internalError("Unhandled: $assignmentOperator"); 2619 return internalError("Unhandled: $assignmentOperator");
2598 } 2620 }
2599 } 2621 }
2600 2622
2601 Initializer buildFieldInitializer( 2623 Initializer buildFieldInitializer(
2602 Map<String, FieldInitializer> initializers) { 2624 Map<String, FieldInitializer> initializers) {
2603 if (!identical("=", assignmentOperator) || 2625 if (!identical("=", assignmentOperator) ||
2604 !accessor.isThisPropertyAccessor) { 2626 !accessor.isThisPropertyAccessor) {
2605 return accessor.buildFieldInitializer(initializers); 2627 return accessor.buildFieldInitializer(initializers);
2606 } 2628 }
2607 String name = accessor.plainNameForRead; 2629 String name = accessor.plainNameForRead;
2608 FieldInitializer initializer = initializers[name]; 2630 FieldInitializer initializer = initializers[name];
2609 if (initializer != null && initializer.value == null) { 2631 if (initializer != null && initializer.value == null) {
2610 initializers.remove(name); 2632 initializers.remove(name);
2611 initializer.value = value..parent = initializer; 2633 initializer.value = value..parent = initializer;
2612 return initializer; 2634 return initializer;
2613 } 2635 }
2614 return accessor.buildFieldInitializer(initializers); 2636 return accessor.buildFieldInitializer(initializers);
2615 } 2637 }
2616 } 2638 }
2617 2639
2618 class DelayedPostfixIncrement extends ContextAccessor { 2640 class DelayedPostfixIncrement extends ContextAccessor {
2619 final Name binaryOperator; 2641 final Name binaryOperator;
2620 2642
2621 final Procedure interfaceTarget; 2643 final Procedure interfaceTarget;
2622 2644
2623 DelayedPostfixIncrement(BuilderHelper helper, int charOffset, 2645 DelayedPostfixIncrement(BuilderHelper helper, int offset,
2624 BuilderAccessor accessor, this.binaryOperator, this.interfaceTarget) 2646 BuilderAccessor accessor, this.binaryOperator, this.interfaceTarget)
2625 : super(helper, charOffset, accessor); 2647 : super(helper, offset, accessor);
2626 2648
2627 Expression buildSimpleRead() { 2649 Expression buildSimpleRead() {
2628 return accessor.buildPostfixIncrement(binaryOperator, charOffset, 2650 return accessor.buildPostfixIncrement(binaryOperator,
2629 voidContext: false, interfaceTarget: interfaceTarget); 2651 offset: offset, voidContext: false, interfaceTarget: interfaceTarget);
2630 } 2652 }
2631 2653
2632 Expression buildForEffect() { 2654 Expression buildForEffect() {
2633 return accessor.buildPostfixIncrement(binaryOperator, charOffset, 2655 return accessor.buildPostfixIncrement(binaryOperator,
2634 voidContext: true, interfaceTarget: interfaceTarget); 2656 offset: offset, voidContext: true, interfaceTarget: interfaceTarget);
2635 } 2657 }
2636 } 2658 }
2637 2659
2638 class JumpTarget extends Builder { 2660 class JumpTarget extends Builder {
2639 final List<Statement> users = <Statement>[]; 2661 final List<Statement> users = <Statement>[];
2640 2662
2641 final JumpTargetKind kind; 2663 final JumpTargetKind kind;
2642 2664
2643 final int functionNestingLevel; 2665 final int functionNestingLevel;
2644 2666
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2857 } else if (node is PrefixBuilder) { 2879 } else if (node is PrefixBuilder) {
2858 return node.name; 2880 return node.name;
2859 } else if (node is ThisAccessor) { 2881 } else if (node is ThisAccessor) {
2860 return node.isSuper ? "super" : "this"; 2882 return node.isSuper ? "super" : "this";
2861 } else if (node is BuilderAccessor) { 2883 } else if (node is BuilderAccessor) {
2862 return node.plainNameForRead; 2884 return node.plainNameForRead;
2863 } else { 2885 } else {
2864 return internalError("Unhandled: ${node.runtimeType}"); 2886 return internalError("Unhandled: ${node.runtimeType}");
2865 } 2887 }
2866 } 2888 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698