blob: c9937b193ced5a488cb5a62e919d709a09dd0840 [file] [log] [blame]
// 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.
// @dart = 2.10
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
import '../inferrer/abstract_value_domain.dart';
import 'builder.dart';
import 'nodes.dart';
/// Visits and concatenates the expressions in a string concatenation.
class KernelStringBuilder extends ir.Visitor<void> with ir.VisitorVoidMixin {
final KernelSsaGraphBuilder builder;
/// The string value generated so far.
HInstruction result = null;
KernelStringBuilder(this.builder);
AbstractValueDomain get _abstractValueDomain =>
builder.closedWorld.abstractValueDomain;
@override
void defaultNode(ir.Node node) {
failedAt(CURRENT_ELEMENT_SPANNABLE, 'Unexpected node: $node');
}
@override
void defaultExpression(ir.Expression node) {
node.accept(builder);
HInstruction expression = builder.pop();
// We want to use HStringify when:
// 1. The value is known to be a primitive type, because it might get
// constant-folded and codegen has some tricks with JavaScript
// conversions.
// 2. The value can be primitive, because the library stringifier has
// fast-path code for most primitives.
if (expression.isPrimitive(_abstractValueDomain).isPotentiallyTrue) {
append(stringify(expression));
return;
}
// TODO(efortuna): If we decide to do inlining before finishing constructing
// the control flow graph, we'd want to do the optimization of
// calling toString here if the type is provably a string rather than in the
// optimization phase (which is where we currently do it).
append(stringify(expression));
}
@override
void visitStringConcatenation(ir.StringConcatenation node) {
node.visitChildren(this);
}
void append(HInstruction expression) {
result = (result == null) ? expression : concat(result, expression);
}
HInstruction concat(HInstruction left, HInstruction right) {
HInstruction instruction =
HStringConcat(left, right, _abstractValueDomain.stringType);
builder.add(instruction);
return instruction;
}
HInstruction stringify(HInstruction expression) {
HInstruction instruction =
HStringify(expression, _abstractValueDomain.stringType)
..sourceInformation = expression.sourceInformation;
builder.add(instruction);
return instruction;
}
}