Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C] do not generate code without main reactor #1000

Merged
merged 5 commits into from
Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions org.lflang/src/org/lflang/generator/GeneratorBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,15 @@ public void doGenerate(Resource resource, LFGeneratorContext context) {
.map(it -> GeneratorUtils.getLFResource(it, fileConfig.getSrcGenBasePath(), context, errorReporter))
.collect(Collectors.toList())
);
GeneratorUtils.accommodatePhysicalActionsIfPresent(allResources, getTarget(), targetConfig, errorReporter);
GeneratorUtils.accommodatePhysicalActionsIfPresent(
allResources,
getTarget().setsKeepAliveOptionAutomatically(),
targetConfig,
errorReporter
);
// FIXME: Should the GeneratorBase pull in `files` from imported
// resources?

// Reroute connections that have delays associated with them via
// generated delay reactors.
transformDelays();
Expand Down
74 changes: 49 additions & 25 deletions org.lflang/src/org/lflang/generator/GeneratorUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.lflang.lf.Action;
import org.lflang.lf.ActionOrigin;
import org.lflang.lf.Import;
import org.lflang.lf.Instantiation;
import org.lflang.lf.KeyValuePair;
import org.lflang.lf.KeyValuePairs;
import org.lflang.lf.Model;
Expand All @@ -55,16 +56,14 @@ private GeneratorUtils() {
* Return the target declaration found in the given resource.
*/
public static TargetDecl findTarget(Resource resource) {
int cnt = 0;
housengw marked this conversation as resolved.
Show resolved Hide resolved
TargetDecl targetDecl = null;
for (TargetDecl t : findAll(resource, TargetDecl.class)) { // getAllContents should never return null.
housengw marked this conversation as resolved.
Show resolved Hide resolved
if (targetDecl != null) {
throw new InvalidSourceException("There is more than one target!"); // FIXME: check this in validator
}
targetDecl = t;
housengw marked this conversation as resolved.
Show resolved Hide resolved
cnt++;
housengw marked this conversation as resolved.
Show resolved Hide resolved
}
housengw marked this conversation as resolved.
Show resolved Hide resolved
if (targetDecl == null) {
throw new InvalidSourceException("No target found!");
}
if (cnt > 1) throw new InvalidSourceException("There is more than one target!"); // FIXME: check this in validator
housengw marked this conversation as resolved.
Show resolved Hide resolved
if (cnt == 0) throw new InvalidSourceException("No target found!");
housengw marked this conversation as resolved.
Show resolved Hide resolved
return targetDecl;
}

Expand Down Expand Up @@ -130,30 +129,31 @@ public static void setTargetConfig(
*/
public static void accommodatePhysicalActionsIfPresent(
List<Resource> resources,
Target target,
boolean setsKeepAliveOptionAutomatically,
TargetConfig targetConfig,
ErrorReporter errorReporter
) {
if (!target.setsKeepAliveOptionAutomatically()) {
if (!setsKeepAliveOptionAutomatically) {
return;
}
for (Resource resource : resources) {
for (Action action : findAll(resource, Action.class)) {
if (action.getOrigin() == ActionOrigin.PHYSICAL) {
if (action.getOrigin() == ActionOrigin.PHYSICAL &&
// Check if the user has explicitly set keepalive to false
if (!targetConfig.setByUser.contains(TargetProperty.KEEPALIVE) && !targetConfig.keepalive) {
// If not, set it to true
targetConfig.keepalive = true;
errorReporter.reportWarning(
action,
String.format(
"Setting %s to true because of the physical action %s.",
TargetProperty.KEEPALIVE.getDisplayName(),
action.getName()
)
);
return;
}
!targetConfig.setByUser.contains(TargetProperty.KEEPALIVE) &&
!targetConfig.keepalive
) {
// If not, set it to true
targetConfig.keepalive = true;
errorReporter.reportWarning(
action,
String.format(
"Setting %s to true because of the physical action %s.",
TargetProperty.KEEPALIVE.getDisplayName(),
action.getName()
)
);
return;
}
}
}
Expand Down Expand Up @@ -306,14 +306,13 @@ public static LFResource getLFResource(
List<KeyValuePair> pairs = config.getPairs();
TargetProperty.set(targetConfig, pairs != null ? pairs : List.of(), errorReporter);
}
FileConfig fc;
try {
fc = new FileConfig(resource, srcGenBasePath, context.useHierarchicalBin());
FileConfig fc = new FileConfig(resource, srcGenBasePath, context.useHierarchicalBin());
return new LFResource(resource, fc, targetConfig);
} catch (IOException e) {
throw new RuntimeException("Failed to instantiate an imported resource because an I/O error "
+ "occurred.");
}
return new LFResource(resource, fc, targetConfig);
}

/**
Expand Down Expand Up @@ -341,4 +340,29 @@ public static void refreshProject(Resource resource, Mode compilerMode) {
public static boolean isHostWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}

/**
* Check whether code can be generated; report any problems
* and inform the context accordingly.
* @return Whether it is possible to generate code.
*/
public static boolean canGenerate(
Boolean errorsOccurred,
Instantiation mainDef,
ErrorReporter errorReporter,
LFGeneratorContext context
) {
// stop if there are any errors found in the program by doGenerate() in GeneratorBase
if (errorsOccurred) {
context.finish(GeneratorResult.FAILED);
return false;
}
// abort if there is no main reactor
if (mainDef == null) {
errorReporter.reportWarning("WARNING: The given Lingua Franca program does not define a main reactor. Therefore, no code was generated.");
context.finish(GeneratorResult.NOTHING);
return false;
}
return true;
}
}
26 changes: 0 additions & 26 deletions org.lflang/src/org/lflang/generator/GeneratorUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import org.lflang.toUnixString
import org.lflang.toTextTokenBased
import org.lflang.lf.Instantiation


/** A transparent type alias to document when a string contains target code. */
typealias TargetCode = String

Expand Down Expand Up @@ -43,28 +42,3 @@ fun EObject.locationInfo(): LocationInfo {
lfText = toTextTokenBased() ?: ""
)
}

/**
* Check whether code can be generated; report any problems
* and inform the context accordingly.
* @return Whether it is possible to generate code.
*/
fun canGenerate(
errorsOccurred: Boolean,
mainDef: Instantiation?,
errorReporter: ErrorReporter,
context: LFGeneratorContext
): Boolean {
// stop if there are any errors found in the program by doGenerate() in GeneratorBase
if (errorsOccurred) {
context.finish(GeneratorResult.FAILED)
return false
}
// abort if there is no main reactor
if (mainDef == null) {
errorReporter.reportWarning("WARNING: The given Lingua Franca program does not define a main reactor. Therefore, no code was generated.")
context.finish(GeneratorResult.NOTHING)
return false
}
return true
}
13 changes: 5 additions & 8 deletions org.lflang/src/org/lflang/generator/c/CGenerator.xtend
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,6 @@ class CGenerator extends GeneratorBase {

////////////////////////////////////////////
//// Public methods

override printInfo(LFGeneratorContext.Mode mode) {
super.printInfo(mode)
println('******** generated binaries: ' + fileConfig.binPath)
}

/**
* Set C-specific default target configurations if needed.
*/
Expand Down Expand Up @@ -385,6 +379,7 @@ class CGenerator extends GeneratorBase {
'''Using the threaded C runtime to allow for asynchronous handling of«
» physical action «action.name».'''
);
return;
}
}
}
Expand Down Expand Up @@ -435,9 +430,10 @@ class CGenerator extends GeneratorBase {
* whether it is a standalone context
*/
override void doGenerate(Resource resource, LFGeneratorContext context) {

// The following generates code needed by all the reactors.
super.doGenerate(resource, context)

if (!GeneratorUtils.canGenerate(errorsOccurred, mainDef, errorReporter, context)) return;

accommodatePhysicalActionsIfPresent()
setCSpecificDefaults(context)
generatePreamble()
Expand Down Expand Up @@ -936,6 +932,7 @@ class CGenerator extends GeneratorBase {
GeneratorResult.Status.COMPILED, fileConfig.name, fileConfig, null
);
}
println("Compiled binary is in " + fileConfig.binPath);
} else {
context.finish(GeneratorResult.GENERATED_NO_EXECUTABLE.apply(null));
}
Expand Down
2 changes: 1 addition & 1 deletion org.lflang/src/org/lflang/generator/cpp/CppGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import org.lflang.generator.GeneratorResult
import org.lflang.generator.IntegratedBuilder
import org.lflang.generator.LFGeneratorContext
import org.lflang.generator.TargetTypes
import org.lflang.generator.canGenerate
import org.lflang.generator.GeneratorUtils.canGenerate
import org.lflang.isGeneric
import org.lflang.lf.Action
import org.lflang.lf.VarRef
Expand Down
2 changes: 1 addition & 1 deletion org.lflang/src/org/lflang/generator/rust/RustGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import org.eclipse.emf.ecore.resource.Resource
import org.lflang.ErrorReporter
import org.lflang.Target
import org.lflang.TargetProperty.BuildType
import org.lflang.generator.canGenerate
import org.lflang.generator.GeneratorUtils.canGenerate
import org.lflang.generator.CodeMap
import org.lflang.generator.GeneratorBase
import org.lflang.generator.GeneratorResult
Expand Down
2 changes: 1 addition & 1 deletion org.lflang/src/org/lflang/generator/ts/TSGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import org.lflang.generator.PrependOperator
import org.lflang.generator.SubContext
import org.lflang.generator.TargetTypes
import org.lflang.generator.ValueGenerator
import org.lflang.generator.canGenerate
import org.lflang.generator.GeneratorUtils.canGenerate
import org.lflang.inferredType
import org.lflang.lf.Action
import org.lflang.lf.Delay
Expand Down