Skip to content

Commit

Permalink
Merge pull request #1580 from lf-lang/clem.new-equals-initializers
Browse files Browse the repository at this point in the history
Add equals initializer syntax
  • Loading branch information
cmnrd authored Mar 27, 2023
2 parents dcdcc4f + 63d2fa0 commit 6547cea
Show file tree
Hide file tree
Showing 682 changed files with 2,303 additions and 1,944 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void testSimple() {

@Test
public void testAssignments() {
assertIsFormatted(
assertFormatsTo(
"""
target C
Expand All @@ -43,6 +43,15 @@ public void testAssignments() {
input in: int
state last_invoked: tag_t({= NEVER_TAG_INITIALIZER =})
}
""",
"""
target C
reactor Destination {
input ok: bool
input in: int
state last_invoked: tag_t = {= NEVER_TAG_INITIALIZER =}
}
"""
);
}
Expand All @@ -56,16 +65,34 @@ public void testState() {
reactor Destination {
state one_init: tag_t( {= NEVER_TAG_INITIALIZER =})
state no_init: tag_t
state list_init(1,2)
state list_init(1,2) // this syntax is deprecated
}
""",
"""
target Python
reactor Destination {
state one_init: tag_t = {= NEVER_TAG_INITIALIZER =}
state no_init: tag_t
state list_init(1, 2) # this syntax is deprecated
}
"""
);
}

@Test
public void testCppInits() {
assertIsFormatted(
"""
target Cpp
reactor Destination {
state one_init: tag_t({= NEVER_TAG_INITIALIZER =})
state no_init: tag_t
state list_init(1, 2)
state assign: int = 0
state paren: int(0)
state brace: std::vector<int>{1, 2}
state paren_list: std::vector<int>(1, 2)
}
"""
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void testLet() throws Exception {
));

Assertions.assertNotNull(model);
final var ctypes = new CTypes(new DefaultErrorReporter());
final var ctypes = CTypes.getInstance();
final var resource = model.eResource();
final var transformation = new DelayedConnectionTransformation(new CDelayBodyGenerator(ctypes), ctypes, resource, true, true);
transformation.applyTransformation(ASTUtils.getAllReactors(resource));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Collections.emptyList;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -28,11 +29,15 @@
public class RoundTripTests {

@Test
public void roundTripTest() throws Exception {
public void roundTripTest() {
for (Target target : Target.values()) {
for (TestCategory category : TestCategory.values()) {
for (LFTest test : TestRegistry.getRegisteredTests(target, category, false)) {
run(test.getSrcPath());
try {
run(test.getSrcPath());
} catch (Throwable thrown) {
fail("Test case " + test.getSrcPath() + " failed", thrown);
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions org.lflang/src/org/lflang/ASTUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ public static boolean changeTargetName(Resource resource, String newTargetName)
return true;
}

/**
* Return the target of the file in which the given node lives.
*/
public static Target getTarget(EObject object) {
TargetDecl targetDecl = targetDecl(object.eResource());
return Target.fromDecl(targetDecl);
}

/**
* Add a new target property to the given resource.
*
Expand Down
19 changes: 14 additions & 5 deletions org.lflang/src/org/lflang/LinguaFranca.xtext
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ TargetDecl:
Initializer:
parens?='(' (exprs+=Expression (',' exprs+=Expression)* (trailingComma?=',')?)? ')'
| braces?='{' (exprs+=Expression (',' exprs+=Expression)* (trailingComma?=',')?)? '}'
// | assign?='=' exprs+=Expression // todo later
| assign?='=' exprs+=Expression
;


Expand Down Expand Up @@ -285,13 +285,15 @@ VarRefOrModeTransition returns VarRef:

Assignment:
lhs=[Parameter]
(equals='=')? rhs=AssignmentInitializer
rhs=AssignmentInitializer
;

// TODO Only allow = based parameter assignment
AssignmentInitializer returns Initializer:
exprs+=Expression
| parens?='(' (exprs+=Expression (',' exprs+=Expression)* (trailingComma?=',')?)? ')'
assign?='=' exprs+=Expression
// these syntaxes are legacy and now deprecated
// todo remove in future version.
| '='? parens?='(' (exprs+=Expression (',' exprs+=Expression)* (trailingComma?=',')?)? ')'
// note: the previous syntax `= { expr* }` is now parsed as a BracedListExpression
| braces?='{' (exprs+=Expression (',' exprs+=Expression)* (trailingComma?=',')?)? '}'
;

Expand All @@ -310,6 +312,13 @@ Expression:
| Time
| ParameterReference
| {CodeExpr} code=Code
| BracedListExpression
;

// A list of expressions within braces.
// In C/C++, this is an array initializer, struct initializer, or std::initializer_list.
BracedListExpression:
'{' {BracedListExpression} (items+=Expression (',' items+=Expression)*)? ','? '}'
;

ParameterReference:
Expand Down
18 changes: 15 additions & 3 deletions org.lflang/src/org/lflang/Target.java
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,7 @@ public boolean supportsMultiports() {
* on constants).
*/
public boolean supportsParameterizedWidths() {
return switch (this) {
case C, CCPP, CPP, Python, Rust, TS -> true;
};
return true;
}

/**
Expand All @@ -502,6 +500,20 @@ public boolean buildsUsingDocker() {
};
}

/**
* Whether the target requires using an equal sign to assign a default value to a parameter,
* or initialize a state variable. All targets mandate an equal sign when passing
* arguments to a reactor constructor call, regardless of this method.
*/
public boolean mandatesEqualsInitializers() {
return this != CPP;
}

/** Allow expressions of the form {@code {a, b, c}}. */
public boolean allowsBracedListExpressions() {
return this == C || this == CCPP || this == CPP;
}

/**
* Return a string that demarcates the beginning of a single-line comment.
*/
Expand Down
12 changes: 10 additions & 2 deletions org.lflang/src/org/lflang/ast/IsEqual.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.lflang.lf.Assignment;
import org.lflang.lf.AttrParm;
import org.lflang.lf.Attribute;
import org.lflang.lf.BracedListExpression;
import org.lflang.lf.BuiltinTriggerRef;
import org.lflang.lf.Code;
import org.lflang.lf.CodeExpr;
Expand Down Expand Up @@ -415,7 +416,6 @@ public Boolean caseVarRef(VarRef object) {
public Boolean caseAssignment(Assignment object) {
return new ComparisonMachine<>(object, Assignment.class)
.equivalent(Assignment::getLhs)
.equalAsObjects(Assignment::getEquals)
.equivalent(Assignment::getRhs)
.conclusion;
}
Expand All @@ -437,10 +437,18 @@ public Boolean caseExpression(Expression object) {
Literal.class,
Time.class,
ParameterReference.class,
Code.class
Code.class,
BracedListExpression.class
);
}

@Override
public Boolean caseBracedListExpression(BracedListExpression object) {
return new ComparisonMachine<>(object, BracedListExpression.class)
.listsEquivalent(BracedListExpression::getItems)
.conclusion;
}

@Override
public Boolean caseParameterReference(ParameterReference object) {
return new ComparisonMachine<>(object, ParameterReference.class)
Expand Down
60 changes: 46 additions & 14 deletions org.lflang/src/org/lflang/ast/ToLf.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.xbase.lib.StringExtensions;
import org.lflang.ASTUtils;
import org.lflang.Target;
import org.lflang.ast.MalleableString.Builder;
import org.lflang.ast.MalleableString.Joiner;
import org.lflang.lf.Action;
Expand All @@ -29,6 +30,7 @@
import org.lflang.lf.Assignment;
import org.lflang.lf.AttrParm;
import org.lflang.lf.Attribute;
import org.lflang.lf.BracedListExpression;
import org.lflang.lf.BuiltinTriggerRef;
import org.lflang.lf.Code;
import org.lflang.lf.CodeExpr;
Expand All @@ -46,6 +48,7 @@
import org.lflang.lf.Instantiation;
import org.lflang.lf.KeyValuePair;
import org.lflang.lf.KeyValuePairs;
import org.lflang.lf.LfFactory;
import org.lflang.lf.Literal;
import org.lflang.lf.Method;
import org.lflang.lf.MethodArgument;
Expand Down Expand Up @@ -476,7 +479,7 @@ public MalleableString caseStateVar(StateVar object) {
}
msb.append("state ").append(object.getName());
msb.append(typeAnnotationFor(object.getType()));
msb.append(initializer(object.getInit(), true));
msb.append(initializer(object.getInit()));

return msb.get();
}
Expand Down Expand Up @@ -757,14 +760,26 @@ public MalleableString caseSerializer(Serializer object) {
@Override
public MalleableString caseKeyValuePairs(KeyValuePairs object) {
// {KeyValuePairs} '{' (pairs+=KeyValuePair (',' (pairs+=KeyValuePair))* ','?)? '}'
if (object.getPairs().isEmpty()) return MalleableString.anyOf("");
if (object.getPairs().isEmpty()) {
return MalleableString.anyOf("");
}
return new Builder()
.append("{\n")
.append(list(",\n", "", "\n", true, true, object.getPairs()).indent())
.append("}")
.get();
}

@Override
public MalleableString caseBracedListExpression(BracedListExpression object) {
if (object.getItems().isEmpty()) {
return MalleableString.anyOf("{}");
}
// Note that this strips the trailing comma. There is no way
// to implement trailing commas with the current set of list() methods AFAIU.
return list(", ", "{", "}", false, false, object.getItems());
}

@Override
public MalleableString caseKeyValuePair(KeyValuePair object) {
// name=Kebab ':' value=Element
Expand Down Expand Up @@ -819,35 +834,52 @@ public MalleableString caseAssignment(Assignment object) {
// ));
Builder msb = new Builder();
msb.append(object.getLhs().getName());
if (object.getEquals() != null) {
msb.append(" = ");
}
msb.append(initializer(object.getRhs(), false));
msb.append(initializer(object.getRhs()));
return msb.get();
}

@Override
public MalleableString caseInitializer(Initializer object) {
return initializer(object, false);
return initializer(object);
}

private MalleableString initializer(Initializer init, boolean nothingIfEmpty) {
/**
* Return true if the initializer should be output with an equals initializer.
* Old-style assignments with parentheses are also output that
* way to help with the transition.
*/
private boolean shouldOutputAsAssignment(Initializer init) {
return init.isAssign()
|| init.getExprs().size() == 1 && ASTUtils.getTarget(init).mandatesEqualsInitializers();
}

private MalleableString initializer(Initializer init) {
if (init == null) {
return MalleableString.anyOf("");
}
if (shouldOutputAsAssignment(init)) {
Expression expr = ASTUtils.asSingleExpr(init);
Objects.requireNonNull(expr);
return new Builder().append(" = ").append(doSwitch(expr)).get();
}
if (ASTUtils.getTarget(init) == Target.C) {
// This turns C array initializers into a braced expression.
// C++ variants are not converted.
BracedListExpression list = LfFactory.eINSTANCE.createBracedListExpression();
list.getItems().addAll(init.getExprs());
return new Builder().append(" = ").append(doSwitch(list)).get();
}
String prefix;
String suffix;
if (init.isBraces()) {
prefix = "{";
suffix = "}";
} else if (init.isParens()) {
} else {
assert init.isParens();
prefix = "(";
suffix = ")";
} else {
// unparenthesized parameter assignment.
prefix = suffix = "";
}
return list(", ", prefix, suffix, nothingIfEmpty, false, init.getExprs());
return list(", ", prefix, suffix, false, false, init.getExprs());
}


Expand All @@ -862,7 +894,7 @@ public MalleableString caseParameter(Parameter object) {
return builder
.append(object.getName())
.append(typeAnnotationFor(object.getType()))
.append(initializer(object.getInit(), true))
.append(initializer(object.getInit()))
.get();
}

Expand Down
6 changes: 6 additions & 0 deletions org.lflang/src/org/lflang/ast/ToText.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.lflang.ASTUtils;
import org.lflang.lf.ArraySpec;
import org.lflang.lf.BracedListExpression;
import org.lflang.lf.Code;
import org.lflang.lf.CodeExpr;
import org.lflang.lf.Host;
Expand Down Expand Up @@ -78,6 +79,11 @@ public String caseCode(Code code) {
return "";
}

@Override
public String caseBracedListExpression(BracedListExpression object) {
return ToLf.instance.caseBracedListExpression(object).toString();
}

@Override
public String caseHost(Host host) {
return ToLf.instance.caseHost(host).toString();
Expand Down
Loading

0 comments on commit 6547cea

Please sign in to comment.