blob: 3333d8a7fa24271330d603d3a33fdfc0965f157e [file] [log] [blame]
// Copyright (c) 2021, 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.
import 'dart:convert';
import 'nodes.dart';
import '../../../compiler_new.dart' as api;
import '../../kernel/front_end_adapter.dart' show CompilerFileSystem;
/// [Parser] parsers a program split constraints json file and returns a
/// [ConstraintData] object.
class Parser {
final Map<String, NamedNode> nameMap = {};
final List<RelativeOrderNode> orderedNodes = [];
T _lookup<T>(Map<String, dynamic> nodeJson, String key) {
var value = nodeJson[key];
if (value == null) {
throw 'Missing "$key" key in $nodeJson';
}
return value;
}
void parseReference(Map<String, dynamic> nodeJson) {
String name = _lookup(nodeJson, 'name');
String uriAndPrefixString = _lookup(nodeJson, 'import');
var uriAndPrefix = uriAndPrefixString.split('#');
if (uriAndPrefix.length != 2) {
throw 'Invalid "import" "uri#prefix" value in $nodeJson';
}
var uri = Uri.parse(uriAndPrefix[0]);
var prefix = uriAndPrefix[1];
var referenceNode = ReferenceNode(name, uri, prefix);
nameMap[name] = referenceNode;
}
CombinerType parseCombinerType(Map<String, dynamic> nodeJson) {
String type = nodeJson['type'];
switch (type) {
case 'fuse':
return CombinerType.fuse;
case 'and':
return CombinerType.and;
default:
throw 'Unrecognized Combiner $nodeJson';
}
}
void parseCombiner(Map<String, dynamic> nodeJson) {
String name = _lookup(nodeJson, 'name');
List<dynamic> referencesJson = _lookup(nodeJson, 'nodes');
Set<ReferenceNode> references = {};
for (String reference in referencesJson) {
references.add(nameMap[reference]);
}
var combinerNode =
CombinerNode(name, parseCombinerType(nodeJson), references);
nameMap[name] = combinerNode;
}
NamedNode _lookupNode(Map<String, dynamic> nodeJson, String key) {
var node = nameMap[_lookup(nodeJson, key)];
if (node == null) {
throw 'Invalid "$key" name in $nodeJson';
}
return node;
}
void parseOrder(Map<String, dynamic> nodeJson) {
var predecessor = _lookupNode(nodeJson, 'predecessor');
var successor = _lookupNode(nodeJson, 'successor');
var orderNode =
RelativeOrderNode(predecessor: predecessor, successor: successor);
orderedNodes.add(orderNode);
}
/// Reads a program split constraints json file and returns a [Nodes] object
/// reflecting the parsed constraints.
Future<ConstraintData> read(api.CompilerInput provider, Uri path) async {
String programSplitJson =
await CompilerFileSystem(provider).entityForUri(path).readAsString();
List<dynamic> doc = json.decode(programSplitJson);
List<Map<String, dynamic>> referenceConstraints = [];
List<Map<String, dynamic>> combinerConstraints = [];
List<Map<String, dynamic>> orderConstraints = [];
for (Map<String, dynamic> constraint in doc) {
switch (constraint['type']) {
case 'reference':
referenceConstraints.add(constraint);
break;
case 'and':
case 'fuse':
combinerConstraints.add(constraint);
break;
case 'order':
orderConstraints.add(constraint);
break;
default:
throw 'Unrecognized constraint type in $constraint';
}
}
// Parse references, than combiners, than finally sequences.
referenceConstraints.forEach(parseReference);
combinerConstraints.forEach(parseCombiner);
orderConstraints.forEach(parseOrder);
return ConstraintData(nameMap.values.toList(), orderedNodes);
}
}