Skip to content

Commit

Permalink
Simplification of grammar that encodes mutations with the same produc…
Browse files Browse the repository at this point in the history
…tions as reactions (#1318)

* Updates the Lingua Franca grammar to delete the Mutation class, and merge it with the Reaction class. (They have the similar properties `Trigger`, `Source`, `Effect`, `Code`)

* Updates the TypeScript code generator to uses a `WritablePort` for mutations
  • Loading branch information
Wonseo-C authored Sep 28, 2022
1 parent 577c63c commit f266f51
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 47 deletions.
10 changes: 1 addition & 9 deletions org.lflang/src/org/lflang/LinguaFranca.xtext
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ Reactor:
| (connections+=Connection)
| (reactions+=Reaction)
| (modes+=Mode)
| (mutations+=Mutation)
)* '}';


Expand Down Expand Up @@ -196,7 +195,7 @@ Action:

Reaction:
(attributes+=Attribute)*
('reaction')
(('reaction') | mutation ?= 'mutation')
('(' (triggers+=TriggerRef (',' triggers+=TriggerRef)*)? ')')?
(sources+=VarRef (',' sources+=VarRef)*)?
('->' effects+=VarRefOrModeTransition (',' effects+=VarRefOrModeTransition)*)?
Expand All @@ -216,13 +215,6 @@ Deadline:
STP:
'STP' '(' value=Expression ')' code=Code;

Mutation:
('mutation')
('(' (triggers+=TriggerRef (',' triggers+=TriggerRef)*)? ')')?
(sources+=VarRef (',' sources+=VarRef)*)?
('->' effects+=[VarRef] (',' effects+=[VarRef])*)?
code=Code;

Preamble:
(visibility=Visibility)? 'preamble' code=Code;

Expand Down
13 changes: 1 addition & 12 deletions org.lflang/src/org/lflang/ast/IsEqual.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;

import org.lflang.TimeUnit;
Expand Down Expand Up @@ -38,7 +37,6 @@
import org.lflang.lf.MethodArgument;
import org.lflang.lf.Mode;
import org.lflang.lf.Model;
import org.lflang.lf.Mutation;
import org.lflang.lf.NamedHost;
import org.lflang.lf.Output;
import org.lflang.lf.Parameter;
Expand Down Expand Up @@ -138,7 +136,6 @@ public Boolean caseReactor(Reactor object) {
.listsEquivalent(Reactor::getStateVars)
.listsEquivalent(Reactor::getReactions)
.listsEquivalent(Reactor::getMethods)
.listsEquivalent(Reactor::getMutations)
.listsEquivalent(Reactor::getModes)
.conclusion;
}
Expand Down Expand Up @@ -284,6 +281,7 @@ public Boolean caseReaction(Reaction object) {
.listsEquivalent(Reaction::getTriggers)
.listsEquivalent(Reaction::getSources)
.listsEquivalent(Reaction::getEffects)
.equalAsObjects(Reaction::isMutation)
.equivalent(Reaction::getCode)
.equivalent(Reaction::getStp)
.equivalent(Reaction::getDeadline)
Expand Down Expand Up @@ -318,15 +316,6 @@ public Boolean caseSTP(STP object) {
.conclusion;
}

@Override
public Boolean caseMutation(Mutation object) {
return new ComparisonMachine<>(object, Mutation.class)
.listsEquivalent(Mutation::getTriggers)
.listsEquivalent(Mutation::getSources)
.listsEquivalent(Mutation::getEffects)
.equivalent(Mutation::getCode)
.conclusion;
}

@Override
public Boolean casePreamble(Preamble object) {
Expand Down
19 changes: 5 additions & 14 deletions org.lflang/src/org/lflang/ast/ToLf.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import org.lflang.lf.MethodArgument;
import org.lflang.lf.Mode;
import org.lflang.lf.Model;
import org.lflang.lf.Mutation;
import org.lflang.lf.NamedHost;
import org.lflang.lf.Output;
import org.lflang.lf.Parameter;
Expand Down Expand Up @@ -453,7 +452,6 @@ public MalleableString caseReactor(Reactor object) {
List.of(
object.getReactions(),
object.getMethods(),
object.getMutations(),
object.getModes()
),
true
Expand Down Expand Up @@ -653,7 +651,11 @@ public MalleableString caseReaction(Reaction object) {
// (deadline=Deadline)?
Builder msb = new Builder();
addAttributes(msb, object::getAttributes);
msb.append("reaction");
if (object.isMutation()) {
msb.append("mutation");
} else {
msb.append("reaction");
}
msb.append(list(true, object.getTriggers()));
msb.append(list(", ", " ", "", true, false, object.getSources()));
if (!object.getEffects().isEmpty()) {
Expand Down Expand Up @@ -714,17 +716,6 @@ private <T extends EObject> MalleableString handler(
.get();
}

@Override
public MalleableString caseMutation(Mutation object) {
// ('mutation')
// ('(' (triggers+=TriggerRef (',' triggers+=TriggerRef)*)? ')')?
// (sources+=VarRef (',' sources+=VarRef)*)?
// ('->' effects+=[VarRef] (',' effects+=[VarRef])*)?
// code=Code
return new Builder()
.append("mutation").append(list(true, object.getTriggers()))
.get();
}

@Override
public MalleableString casePreamble(Preamble object) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class TSImportPreambleGenerator(
|import {Action as __Action, Startup as __Startup, FederatePortAction as __FederatePortAction} from 'reactor-ts'
|import {Bank as __Bank} from 'reactor-ts'
|import {FederatedApp as __FederatedApp} from 'reactor-ts'
|import {InPort as __InPort, OutPort as __OutPort, Port as __Port} from 'reactor-ts'
|import {InPort as __InPort, OutPort as __OutPort, Port as __Port, WritablePort as __WritablePort, WritableMultiPort as __WritableMultiPort} from 'reactor-ts'
|import {InMultiPort as __InMultiPort, OutMultiPort as __OutMultiPort} from 'reactor-ts'
|import {Reaction as __Reaction} from 'reactor-ts'
|import {State as __State} from 'reactor-ts'
Expand Down
26 changes: 15 additions & 11 deletions org.lflang/src/org/lflang/generator/ts/TSReactionGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import org.lflang.isMultiport
import org.lflang.lf.*
import org.lflang.lf.Timer
import org.lflang.toText
import java.util.*
import kotlin.collections.HashSet
import java.util.StringJoiner
import java.util.LinkedList


/**
* Reaction generator for TypeScript target.
Expand Down Expand Up @@ -103,11 +105,12 @@ class TSReactionGenerator(
reaction: Reaction,
reactPrologue: String,
reactEpilogue: String,
reactFunctArgs: StringJoiner,
reactFuncArgs: StringJoiner,
reactSignature: StringJoiner
): String {
// Assemble reaction triggers
val reactionTriggers = StringJoiner(",\n")

for (trigger in reaction.triggers) {
if (trigger is VarRef) {
reactionTriggers.add(trigger.generateVarRef())
Expand All @@ -119,12 +122,13 @@ class TSReactionGenerator(
}
}
}

return with(PrependOperator) {
"""
|
|this.addReaction(
|this.add${if (reaction.isMutation()) "Mutation" else "Reaction"}(
| new __Triggers($reactionTriggers),
| new __Args($reactFunctArgs),
| new __Args($reactFuncArgs),
| function ($reactSignature) {
| // =============== START react prologue
${" | "..reactPrologue}
Expand All @@ -133,13 +137,13 @@ class TSReactionGenerator(
${" | "..reaction.code.toText()}
| } finally {
| // =============== START react epilogue
${" | "..reactEpilogue}
${" | "..reactEpilogue}
| // =============== END react epilogue
| }
${" | "..if (reaction.deadline != null) generateDeadlineHandler(reaction, reactPrologue, reactEpilogue, reactSignature) else "}"}
|);
""".trimMargin()
}
|""".trimMargin()
}
}

private fun generateReactionSignatureForTrigger(trigOrSource: VarRef): String {
Expand All @@ -165,12 +169,12 @@ class TSReactionGenerator(
}
}

private fun generateReactionSignatureElementForPortEffect(effect: VarRef): String {
private fun generateReactionSignatureElementForPortEffect(effect: VarRef, isMutation: Boolean): String {
val outputPort = effect.variable as Port
val portClassType = if (outputPort.isMultiport) {
"MultiReadWrite<${getPortType(effect.variable as Port)}>"
(if (isMutation) "__WritableMultiPort" else "MultiReadWrite") + "<${getPortType(effect.variable as Port)}>"
} else {
"ReadWrite<${getPortType(effect.variable as Port)}>"
(if (isMutation) "__WritablePort" else "ReadWrite") + "<${getPortType(effect.variable as Port)}>"
}

return if (effect.container != null && effect.container.isBank) {
Expand Down Expand Up @@ -333,7 +337,7 @@ class TSReactionGenerator(
reactSignatureElement += ": Sched<" + getActionType(effect.variable as Action) + ">"
schedActionSet.add(effect.variable as Action)
} else if (effect.variable is Port){
reactSignatureElement += ": ${generateReactionSignatureElementForPortEffect(effect)}"
reactSignatureElement += ": ${generateReactionSignatureElementForPortEffect(effect, reaction.isMutation())}"
reactEpilogue.add(generateReactionEpilogueForPortEffect(effect))
}

Expand Down

0 comments on commit f266f51

Please sign in to comment.