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

Python list initializers & equal initializer syntax #544

Closed
wants to merge 81 commits into from
Closed
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
5d1be6e
Support list literals in LF syntax
oowekyala Sep 26, 2021
328285a
turn [] token into two separate tokens
oowekyala Sep 26, 2021
419cc0d
Update python generator
oowekyala Sep 26, 2021
32e3385
Fix python test
oowekyala Sep 26, 2021
c92da0f
Merge branch 'master' into list-init-syntax
oowekyala Oct 4, 2021
0fa8c20
Update some test code
oowekyala Oct 4, 2021
7784b3a
Rename TuplePrint -> ArrayAsType
oowekyala Oct 4, 2021
f08bd72
Forbid writing [,] as list literal
oowekyala Oct 4, 2021
abfb605
Merge branch 'master' into list-init-syntax
oowekyala Oct 14, 2021
adc20a5
Refactor to use a new Initializer production
oowekyala Oct 14, 2021
599627c
Add tests
oowekyala Oct 14, 2021
03fcc57
Fix grammar
oowekyala Oct 14, 2021
ec1d7d8
Add tests
oowekyala Oct 14, 2021
9a8b6e7
Remove peelParens
oowekyala Oct 14, 2021
a8cf467
Fix checking of types
oowekyala Oct 14, 2021
48040d3
Fix C++ param initializer
oowekyala Oct 14, 2021
451e928
Fix C tests
oowekyala Oct 14, 2021
43fe613
Fix TS tests
oowekyala Oct 14, 2021
4bb0a66
Enrich c++ initializer test
oowekyala Oct 14, 2021
f500a34
Fix python empty lists
oowekyala Oct 14, 2021
57585df
Fix typo
oowekyala Oct 15, 2021
9c0697a
Merge branch 'master' into list-init-syntax
oowekyala Oct 15, 2021
30bd55a
1 class support for arithmetic exprs in more contexts
oowekyala Oct 15, 2021
1f78382
Test type inference with eq assignment
oowekyala Oct 15, 2021
6cb60fe
Remove offset checks
oowekyala Oct 15, 2021
0434933
Add common test for expressions
oowekyala Oct 15, 2021
6c0f65f
Move test
oowekyala Oct 15, 2021
8a3e49a
Apply suggestions from code review
lhstrh Oct 19, 2021
f4f3d4d
Merge branch 'master' into list-init-syntax
oowekyala Oct 20, 2021
f1924ad
Fix TargetTypes
oowekyala Oct 20, 2021
1605bec
Fix TargetTypes w/ arithmetic
oowekyala Oct 20, 2021
84d92a9
Simplify C++ generator
oowekyala Oct 20, 2021
0b5f021
Fix cpp state initializers
oowekyala Oct 21, 2021
c2f7490
Really fix C++
oowekyala Oct 22, 2021
b5bcd3d
Cleanups
oowekyala Oct 22, 2021
2cff9ea
Merge branch 'master' into list-init-syntax
oowekyala Oct 25, 2021
b257d1c
Merge branch 'master' into list-init-syntax
oowekyala Oct 27, 2021
b701c42
Fix merge
oowekyala Oct 27, 2021
b2dde5c
Merge branch 'master' into list-init-syntax
oowekyala Nov 7, 2021
6252667
Add support for array initializer literals in C
oowekyala Nov 7, 2021
640a048
Refactor GeneratorBase
oowekyala Nov 7, 2021
08ed643
More cleanups for TS
oowekyala Nov 7, 2021
8ebc6e6
Cleanup TS further
oowekyala Nov 7, 2021
ff2e42e
Make all generators use TargetTypes default methods
oowekyala Nov 7, 2021
bc08e83
Fix C++ parameters
oowekyala Nov 7, 2021
b19695d
Fix validation of state vars
oowekyala Nov 7, 2021
e2b009a
Fix validation tests
oowekyala Nov 7, 2021
30a0028
Fix TS state initializers
oowekyala Nov 7, 2021
39cbe2d
Fix TS ctor generation
oowekyala Nov 7, 2021
8348a1b
Remove dead code
oowekyala Nov 7, 2021
27b94cb
Fix C++ initializers
oowekyala Nov 7, 2021
2924bf8
Fix Python tuples
oowekyala Nov 7, 2021
f2207db
Support missing initializer in C
oowekyala Nov 7, 2021
ed3fde9
Convert some stuff from AstUtils to java
oowekyala Nov 8, 2021
006ec71
Fix C++ tests
oowekyala Nov 8, 2021
7093364
Missing ctor in typescript test
oowekyala Nov 8, 2021
4213044
Fix TS tests
oowekyala Nov 8, 2021
b1cd66a
Guard against null time values
oowekyala Nov 8, 2021
e268913
Hopefully fix C++ for good
oowekyala Nov 8, 2021
0ad105b
Merge branch 'allow-after-0' into list-init-syntax
oowekyala Dec 7, 2021
ce4a7ad
Merge branch 'master' into list-init-syntax
oowekyala Jan 23, 2022
35729b8
Fix some conflicts
oowekyala Jan 23, 2022
5d32616
Merge branch 'master' into list-init-syntax
oowekyala Jan 29, 2022
f02fa39
Fix conflicts...
oowekyala Jan 29, 2022
f073ec6
Fix conflicts...
oowekyala Jan 29, 2022
bfb524b
Fix conflicts...
oowekyala Jan 29, 2022
8043724
Fix conflicts...
oowekyala Jan 29, 2022
c618d57
Fix conflicts...
oowekyala Jan 29, 2022
01d3453
Resolved conflicts with master. Special attention paid to conflict wi…
lhstrh Feb 4, 2022
5dd07de
Update kotlin version
oowekyala Feb 5, 2022
554ec24
Merge branch 'update-kotlin-version' into list-init-syntax
oowekyala Feb 5, 2022
a675fbd
Fix validator tests
oowekyala Feb 5, 2022
30b7157
Fix some other tests
oowekyala Feb 5, 2022
5b93e15
Try to fix bugs in CGenerator
oowekyala Feb 5, 2022
3c195d5
Update reactor-c to master version
oowekyala Feb 6, 2022
14fe4c0
Fix TS delay tests
oowekyala Feb 6, 2022
8aa7ab9
Fix python errors
oowekyala Feb 6, 2022
7e7f215
Revert "Update kotlin version"
oowekyala Feb 8, 2022
fc26561
Merge remote-tracking branch 'origin/master' into list-init-syntax
oowekyala Feb 21, 2022
a4b7fe8
fix merge...
oowekyala Feb 22, 2022
19de993
Fix more conflicts - compiles
oowekyala Feb 22, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -915,9 +915,7 @@ class LinguaFrancaSynthesis extends AbstractDiagramSynthesis<Model> {
if (!t.nullOrEmpty) {
b.append(":").append(t)
}
if (!param.init.nullOrEmpty) {
b.append("(").append(param.init.join(", ", [it.toText])).append(")")
}
b.append(ASTUtils.toText(param.init))
return b.toString()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,7 @@ import org.lflang.lf.Value
class UtilityExtensions extends AbstractSynthesisExtensions {

extension KGraphFactory = KGraphFactory.eINSTANCE

/**
* Converts a timing value into readable text
*/
def String toText(Value value) {
if (value !== null) {
if (value.parameter !== null) {
return value.parameter.name
} else if (value.time !== null) {
return value.time.interval +
value.time.unit.toString
} else if (value.literal !== null) {
return value.literal
} else if (value.code !== null) {
ASTUtils.toText(value.code)
}
}
return ""
}


/**
* Converts a host value into readable text
*/
Expand Down
57 changes: 56 additions & 1 deletion org.lflang.tests/src/org/lflang/tests/LFParsingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class LFParsingTest {


@Test
public void testLexingEmptyTargetProperties() throws Exception {
public void testParsingEmptyTargetProperties() throws Exception {
assertNoParsingErrorsIn("target C { }; \nreactor Foo {}");
assertNoParsingErrorsIn("target C {a:b,}; \nreactor Foo {}");
expectParsingErrorIn("target C {,}; \nreactor Foo {}");
Expand All @@ -38,6 +38,61 @@ public void testLexingEmptyTargetProperties() throws Exception {
// assertNoParsingErrorsIn("target C {x:[,]}; \nreactor Foo {}");
}

@Test
public void testParsingListLiterals() throws Exception {
assertNoParsingErrorsIn("target Python; \nreactor Foo(p([1,])) {}");
// [,] is not an ok list literal
expectParsingErrorIn("target Python; \nreactor Foo(p([,])) {}");
}

@Test
public void testParsingInitializers() throws Exception {
assertNoParsingErrorsIn("target Python; \nreactor Foo(p = [1,]) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p = (1,)) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p = ()) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p = []) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p = 1) {}");

assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = [1,] }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = (1,) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = () }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = [] }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = 1 }");


// [,] is not an ok list literal
expectParsingErrorIn("target Python; \nreactor Foo(p = [,]) {}");
}

@Test
public void testParsingParenInitializers() throws Exception {
assertNoParsingErrorsIn("target Python; \nreactor Foo(p ([1,])) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p ((1,))) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p (())) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p ([])) {}");
assertNoParsingErrorsIn("target Python; \nreactor Foo(p (1)) {}");

assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p([1,]) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p((1,)) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p(()) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p([]) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p(1) }");


// [,] is not an ok list literal
expectParsingErrorIn("target Python; \nreactor Foo(p([,])) {}");
}

@Test
public void testParsingParentheses() throws Exception {
// unnecessary parentheses are allowed
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = ((1)) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = (1) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = (1,) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = (1,2) }");
assertNoParsingErrorsIn("target Python; \nreactor Foo{ state p = (1,2,) }");
}

@Test
public void testLexingLifetimeAnnots() throws Exception {
assertNoParsingErrorsIn(makeLfTargetCode("Rust",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import org.lflang.lf.Instantiation
import org.lflang.lf.Model
import org.lflang.lf.Parameter
import org.lflang.lf.StateVar
import org.lflang.lf.Value
import org.lflang.lf.Literal
import org.lflang.tests.LFInjectorProvider
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -183,28 +185,28 @@ class LinguaFrancaASTUtilsTest {
for (parameter : model.eAllContents.filter(Parameter).toList) {
if (parameter.name == 'x') {
var values = ASTUtils.initialValue(parameter, null);
Assertions.assertEquals(values.get(0).literal, "1");
assertIsLiteral(values.get(0), "1");

values = ASTUtils.initialValue(parameter, list_a1);
Assertions.assertEquals(values.get(0).literal, "2");
assertIsLiteral(values.get(0), "2");

values = ASTUtils.initialValue(parameter, list_a2);
Assertions.assertEquals(values.get(0).literal, "-1");
assertIsLiteral(values.get(0), "-1");

values = ASTUtils.initialValue(parameter, list_a1b1);
Assertions.assertEquals(values.get(0).literal, "3");
assertIsLiteral(values.get(0), "3");

values = ASTUtils.initialValue(parameter, list_a2b1);
Assertions.assertEquals(values.get(0).literal, "-1");
assertIsLiteral(values.get(0), "-1");

values = ASTUtils.initialValue(parameter, list_a1b2);
Assertions.assertEquals(values.get(0).literal, "-2");
assertIsLiteral(values.get(0), "-2");

values = ASTUtils.initialValue(parameter, list_a2b2);
Assertions.assertEquals(values.get(0).literal, "-1");
assertIsLiteral(values.get(0), "-1");
} else if (parameter.name == 'y') {
var values = ASTUtils.initialValue(parameter, null);
Assertions.assertEquals(values.get(0).literal, "2");
assertIsLiteral(values.get(0), "2");

try {
values = ASTUtils.initialValue(parameter, list_a1);
Expand All @@ -213,11 +215,16 @@ class LinguaFrancaASTUtilsTest {
}

values = ASTUtils.initialValue(parameter, list_b1);
Assertions.assertEquals(values.get(0).literal, "3");
assertIsLiteral(values.get(0), "3");

values = ASTUtils.initialValue(parameter, list_b2);
Assertions.assertEquals(values.get(0).literal, "-2");
assertIsLiteral(values.get(0), "-2");
}
}
}
}

def static assertIsLiteral(Value v, String literalValue) {
Assertions.assertTrue(v instanceof Literal, "Expected a literal, got " + v);
Assertions.assertEquals((v as Literal).literal, literalValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class LinguaFrancaValidationTest {
reactor Foo {
output out:int;
}
main reactor Bar {
main reactor {
output out:int;
x = new Foo();
x.out -> out;
Expand Down Expand Up @@ -495,7 +495,7 @@ class LinguaFrancaValidationTest {
printf("Hello World.\n");
=}
}
''').assertError(LfPackage::eINSTANCE.value,
''').assertError(LfPackage::eINSTANCE.timer,
null, "Missing time units. Should be one of " +
TimeUnit.VALUES.filter[it != TimeUnit.NONE])
}
Expand All @@ -513,8 +513,8 @@ class LinguaFrancaValidationTest {
printf("Hello World.\n");
=}
}
''').assertError(LfPackage::eINSTANCE.value,
null, 'Parameter is not of time type')
''').assertError(LfPackage::eINSTANCE.timer,
null, 'Referenced parameter does not have time type.')

}

Expand All @@ -531,7 +531,7 @@ class LinguaFrancaValidationTest {
printf("Hello World.\n");
=}
}
''').assertError(LfPackage::eINSTANCE.value,
''').assertError(LfPackage::eINSTANCE.timer,
null, 'Invalid time literal')
}

Expand Down Expand Up @@ -667,8 +667,96 @@ class LinguaFrancaValidationTest {
}
}
}



@Test
def void forbidListLiterals() {
parseWithoutError('''
target C;
reactor Contained {
state x: int[]([1, 2]);
state y: int[] = [1, 2];
}
''').assertError(LfPackage::eINSTANCE.listExpr,
null, 'Target C does not support list literals.')
}


@Test
def void forbidTupleLiterals() {
parseWithoutError('''
target C; // in C
reactor Contained {
state x: int[] = (1, 2);
}
''').assertError(LfPackage::eINSTANCE.tupleExpr,
null, 'Target C does not support tuple literals.')
}


@Test
def void allowListLiteralsInPython() {
parseWithoutError('''
target Python;
reactor Contained {
state x([1, 2]);
}
''').assertNoErrors()
}


@Test
def void forbidMalformedArithmetic() {
val model = parseWithoutError('''
target Python;
reactor Contained(p = 2) {
state x0 = 1 + 2 sec; // int + time
state x1 = 1 + (2,); // int + tuple
state x2 = 1 + [2]; // int + list

// following should probs be ok, currently aren't

state x3 = [2] + [3]; // list + list
}
''')

model.assertError(LfPackage::eINSTANCE.addExpr, null, 'Unexpected operand in arithmetic expression.')
model.assertError(LfPackage::eINSTANCE.addExpr, null, 'Unexpected operand in arithmetic expression.')
model.assertError(LfPackage::eINSTANCE.addExpr, null, 'Unexpected operand in arithmetic expression.')
model.assertError(LfPackage::eINSTANCE.addExpr, null, 'Unexpected operand in arithmetic expression.')
model.assertError(LfPackage::eINSTANCE.addExpr, null, 'Unexpected operand in arithmetic expression.')
}


@Test
def void wellFormedArithmetic() {
parseWithoutError('''
target Python;
reactor Contained(p = 2) {
state x1 = 1 * 2
state x2 = 1 + 2
state x3 = 1 + p
state x4 = 1 * p
state x5 = "a" + "b"
state x6 = "a" + p
state x7 = p + "a"
state x8 = p * "a"

// following should probs not be ok, currently are
state x9 = "a" * "b";
}
''').assertNoErrors()
}

@Test
def void typeInferenceWithEqAssignment() {
parseWithoutError('''
target C;
reactor Contained(p = 4 sec) {
state x1 = p;
}
''').assertNoErrors()
}

/**
* Tests for state and parameter declarations, including native lists.
*/
Expand All @@ -691,26 +779,15 @@ class LinguaFrancaValidationTest {
}
''')

model.assertError(LfPackage::eINSTANCE.parameter, null,
"Type declaration missing.")
model.assertError(LfPackage::eINSTANCE.parameter, null,
"Missing time units. Should be one of " +
TimeUnit.VALUES.filter[it != TimeUnit.NONE])
model.assertError(LfPackage::eINSTANCE.parameter, null,
"Invalid time literal.")
model.assertError(LfPackage::eINSTANCE.parameter, null,
"Time parameter cannot be initialized using a list.")
model.assertError(LfPackage::eINSTANCE.parameter, null,
"Parameter cannot be initialized using parameter.")
model.assertError(LfPackage::eINSTANCE.stateVar, null,
"Referenced parameter does not denote a time.")
model.assertError(LfPackage::eINSTANCE.stateVar, null,
"Invalid time literal.")
model.assertError(LfPackage::eINSTANCE.parameter, null,
"Uninitialized parameter.")
model.assertError(LfPackage::eINSTANCE.value, null,
"Missing time units. Should be one of " +
TimeUnit.VALUES.filter[it != TimeUnit.NONE])
model.assertError(LfPackage::eINSTANCE.parameter, null, "Type declaration missing.")
model.assertError(LfPackage::eINSTANCE.parameter, null, "Missing time units. Should be one of " + TimeUnit.VALUES.filter[it != TimeUnit.NONE])
model.assertError(LfPackage::eINSTANCE.parameter, null, "Invalid time literal.")
model.assertError(LfPackage::eINSTANCE.parameter, null, "Expected exactly one time value.")
model.assertError(LfPackage::eINSTANCE.parameter, null, "Parameter cannot be initialized using parameter.")
model.assertError(LfPackage::eINSTANCE.stateVar, null, "Referenced parameter does not have time type.")
model.assertError(LfPackage::eINSTANCE.stateVar, null, "Invalid time literal.")
// model.assertError(LfPackage::eINSTANCE.parameter, null, "Uninitialized parameter.")
model.assertError(LfPackage::eINSTANCE.timer, null, "Missing time units. Should be one of " + TimeUnit.VALUES.filter[it != TimeUnit.NONE])
}


Expand Down
Loading