use of org.lflang.lf.Code in project lingua-franca by lf-lang.
the class UtilityExtensions method trimCode.
/**
* Trims the hostcode of reactions.
*/
public String trimCode(final Code tokenizedCode) {
if (tokenizedCode == null || StringExtensions.isNullOrEmpty(tokenizedCode.getBody())) {
return "";
}
try {
ICompositeNode node = NodeModelUtils.findActualNodeFor(tokenizedCode);
String code = node != null ? node.getText() : null;
int contentStart = 0;
List<String> lines = new ArrayList<>();
Arrays.stream(code.split("\n")).dropWhile(line -> !line.contains("{=")).forEachOrdered(lines::add);
// Remove start pattern
if (!lines.isEmpty()) {
if (IterableExtensions.head(lines).trim().equals("{=")) {
// skip
lines.remove(0);
} else {
lines.set(0, IterableExtensions.head(lines).replace("{=", "").trim());
contentStart = 1;
}
}
// Remove end pattern
if (!lines.isEmpty()) {
if (IterableExtensions.last(lines).trim().equals("=}")) {
// skip
lines.remove(lines.size() - 1);
} else {
lines.set(lines.size() - 1, IterableExtensions.last(lines).replace("=}", ""));
}
}
// Find indentation
String indentation = null;
while (indentation == null && lines.size() > contentStart) {
String firstLine = lines.get(contentStart);
String trimmed = firstLine.trim();
if (trimmed.isEmpty()) {
lines.set(contentStart, "");
contentStart++;
} else {
int firstCharIdx = firstLine.indexOf(trimmed.charAt(0));
indentation = firstLine.substring(0, firstCharIdx);
}
}
// Remove root indentation
if (!lines.isEmpty()) {
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).startsWith(indentation)) {
lines.set(i, lines.get(i).substring(indentation.length()));
}
}
}
return String.join("\n", lines);
} catch (Exception e) {
e.printStackTrace();
return tokenizedCode.getBody();
}
}
use of org.lflang.lf.Code in project lingua-franca by lf-lang.
the class ASTUtils method insertGeneratedDelays.
/**
* Find connections in the given resource that have a delay associated with them,
* and reroute them via a generated delay reactor.
* @param resource The AST.
* @param generator A code generator.
*/
public static void insertGeneratedDelays(Resource resource, GeneratorBase generator) {
// The resulting changes to the AST are performed _after_ iterating
// in order to avoid concurrent modification problems.
List<Connection> oldConnections = new ArrayList<>();
Map<EObject, List<Connection>> newConnections = new LinkedHashMap<>();
Map<EObject, List<Instantiation>> delayInstances = new LinkedHashMap<>();
Iterable<Reactor> containers = Iterables.filter(IteratorExtensions.toIterable(resource.getAllContents()), Reactor.class);
// Iterate over the connections in the tree.
for (Reactor container : containers) {
for (Connection connection : allConnections(container)) {
if (connection.getDelay() != null) {
EObject parent = connection.eContainer();
// Assume all the types are the same, so just use the first on the right.
Type type = ((Port) connection.getRightPorts().get(0).getVariable()).getType();
Reactor delayClass = getDelayClass(type, generator);
String generic = generator.getTargetTypes().supportsGenerics() ? generator.getTargetTypes().getTargetType(InferredType.fromAST(type)) : "";
Instantiation delayInstance = getDelayInstance(delayClass, connection, generic, !generator.generateAfterDelaysWithVariableWidth());
// Stage the new connections for insertion into the tree.
List<Connection> connections = convertToEmptyListIfNull(newConnections.get(parent));
connections.addAll(rerouteViaDelay(connection, delayInstance));
newConnections.put(parent, connections);
// Stage the original connection for deletion from the tree.
oldConnections.add(connection);
// Stage the newly created delay reactor instance for insertion
List<Instantiation> instances = convertToEmptyListIfNull(delayInstances.get(parent));
instances.add(delayInstance);
delayInstances.put(parent, instances);
}
}
}
// Remove old connections; insert new ones.
oldConnections.forEach(connection -> {
var container = connection.eContainer();
if (container instanceof Reactor) {
((Reactor) container).getConnections().remove(connection);
} else if (container instanceof Mode) {
((Mode) container).getConnections().remove(connection);
}
});
newConnections.forEach((container, connections) -> {
if (container instanceof Reactor) {
((Reactor) container).getConnections().addAll(connections);
} else if (container instanceof Mode) {
((Mode) container).getConnections().addAll(connections);
}
});
// Finally, insert the instances and, before doing so, assign them a unique name.
delayInstances.forEach((container, instantiations) -> instantiations.forEach(instantiation -> {
if (container instanceof Reactor) {
instantiation.setName(getUniqueIdentifier((Reactor) container, "delay"));
((Reactor) container).getInstantiations().add(instantiation);
} else if (container instanceof Mode) {
instantiation.setName(getUniqueIdentifier((Reactor) container.eContainer(), "delay"));
((Mode) container).getInstantiations().add(instantiation);
}
}));
}
use of org.lflang.lf.Code in project lingua-franca by lf-lang.
the class CodeBuilder method prSourceLineNumber.
/**
* Print the #line compiler directive with the line number of
* the specified object.
* @param eObject The node.
*/
public void prSourceLineNumber(EObject eObject) {
var node = NodeModelUtils.getNode(eObject);
if (node != null) {
// For code blocks (delimited by {= ... =}, unfortunately,
// we have to adjust the offset by the number of newlines before {=.
// Unfortunately, this is complicated because the code has been
// tokenized.
var offset = 0;
if (eObject instanceof Code) {
offset += 1;
}
// Extract the filename from eResource, an astonishingly difficult thing to do.
URI resolvedURI = CommonPlugin.resolve(eObject.eResource().getURI());
// pr(output, "#line " + (node.getStartLine() + offset) + ' "' + FileConfig.toFileURI(fileConfig.srcFile) + '"')
pr("#line " + (node.getStartLine() + offset) + " \"" + resolvedURI + "\"");
}
}
Aggregations